diff options
Diffstat (limited to 'src/javax/media/j3d/SoundRetained.java')
-rw-r--r-- | src/javax/media/j3d/SoundRetained.java | 1316 |
1 files changed, 0 insertions, 1316 deletions
diff --git a/src/javax/media/j3d/SoundRetained.java b/src/javax/media/j3d/SoundRetained.java deleted file mode 100644 index 246e9dc..0000000 --- a/src/javax/media/j3d/SoundRetained.java +++ /dev/null @@ -1,1316 +0,0 @@ -/* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - */ - -package javax.media.j3d; - -import java.util.ArrayList; - - - -/** - * SoundRetained is an abstract class that contains instance varables common - * to all retained sounds. - */ - -abstract class SoundRetained extends LeafRetained -{ - - /** - * Null Sound identifier denotes sound is not created or initialized - */ - static final int NULL_SOUND = -1; - - /** - * sound data associated with sound source - */ - MediaContainer soundData = null; - - /** - * Overall Scale Factor applied to sound. - */ - float initialGain = 1.0f; // Valid values are >= 0.0. - - /** - * Number of times sound is looped/repeated during play - */ - int loopCount = 0; // Range from 0 to POSITIVE_INFINITY(-1) - - /** - * Switch for turning sound on or off while the sound is "active" - */ - boolean enable = false; - - /** - * Type of release when sound is disabled. - * If true, sound plays thru to end of sample before disabled - * Otherwise, sound is disabled immediately. - */ - boolean release = false; - - /** - * Flag denoting if sound silently continues playing when it's deactivated. - */ - boolean continuous = false; - - /** - * Flag denoting if sound is explicitly muted, so that if begins playing - * it will be played silently. - */ - boolean mute = false; - - /** - * Flag denoting if sound is paused from playing - waiting to be resumed - */ - boolean pause = false; - - /** - * Sound priority ranking value. - * Valid values are 0.0 to 1.0 - */ - float priority = 1.0f; - - /** - * Rate Scale Factor applied to sounds playback sample rate in Hertz. - * Valid values are 0.0 to 1.0 - */ - float rate = 1.0f; - - /** - * The Boundary object defining the sound's scheduling region. - */ - Bounds schedulingRegion = null; - - /** - * The bounding leaf reference - */ - BoundingLeafRetained boundingLeaf = null; - - /** - * The transformed bounds from either schedulingRegion or boundingLeaf - */ - Bounds transformedRegion = null; - - // Dirty bit flags used to pass change as part of message, and are - // acclummuated/stored in SoundSchedulerAtoms. - // These flags are grouped into two catagories: - // attribsDirty for sound node fields - // stateDirty for changes to sound state not reflected by sound fields. - - // Attributes Dirty bit flags - // This bitmask is set when sound node attribute is changed by the user. - static final int SOUND_DATA_DIRTY_BIT = 0x0001; - static final int INITIAL_GAIN_DIRTY_BIT = 0x0002; - static final int LOOP_COUNT_DIRTY_BIT = 0x0004; - static final int BOUNDS_DIRTY_BIT = 0x0008; - static final int BOUNDING_LEAF_DIRTY_BIT = 0x0010; - static final int PRIORITY_DIRTY_BIT = 0x0020; - static final int POSITION_DIRTY_BIT = 0x0040; - static final int DISTANCE_GAIN_DIRTY_BIT = 0x0080; - static final int BACK_DISTANCE_GAIN_DIRTY_BIT = 0x0100; - static final int DIRECTION_DIRTY_BIT = 0x0200; - static final int ANGULAR_ATTENUATION_DIRTY_BIT = 0x0400; - static final int RATE_DIRTY_BIT = 0x0800; - - static final int BOUNDS_CHANGED = - BOUNDS_DIRTY_BIT | BOUNDING_LEAF_DIRTY_BIT; - - static final int ATTRIBUTE_DIRTY_BITS = - SOUND_DATA_DIRTY_BIT | INITIAL_GAIN_DIRTY_BIT | - LOOP_COUNT_DIRTY_BIT | PRIORITY_DIRTY_BIT | - RATE_DIRTY_BIT; - - static final int POSITIONAL_DIRTY_BITS = - ATTRIBUTE_DIRTY_BITS | - POSITION_DIRTY_BIT | DISTANCE_GAIN_DIRTY_BIT; - - static final int DIRECTIONAL_DIRTY_BITS = - POSITIONAL_DIRTY_BITS | BACK_DISTANCE_GAIN_DIRTY_BIT | - DIRECTION_DIRTY_BIT | ANGULAR_ATTENUATION_DIRTY_BIT; - - // All attribute bits that are specifically set or cleared for any node */ - static final int ALL_ATTIBS_DIRTY_BITS = 0x0FFF; - - // State Dirty bit flags - // This bitmask is set when scene graph state is changed. - static final int LIVE_DIRTY_BIT = 0x0001; - static final int IMMEDIATE_MODE_DIRTY_BIT = 0x0002; - static final int LOAD_SOUND_DIRTY_BIT = 0x0004; - static final int RELEASE_DIRTY_BIT = 0x0008; - static final int CONTINUOUS_DIRTY_BIT = 0x0010; - static final int ENABLE_DIRTY_BIT = 0x0020; - static final int MUTE_DIRTY_BIT = 0x0040; - static final int PAUSE_DIRTY_BIT = 0x0080; - static final int XFORM_DIRTY_BIT = 0x8000; - - // All attribute bits that are specifically set or cleared for any node */ - static final int ALL_STATE_DIRTY_BITS = 0x80FF; - - // The type of sound node: Background, Point, Cone - int soundType = NULL_SOUND; - - // A back reference to the scene graph sound, when this is a mirror sound - SoundRetained sgSound = null; - - // A HashKey for sounds in a shared group - HashKey key = null; - - // An array of mirror sounds, one for each instance of this sound in a - // shared group. Entry 0 is the only one valid if we are not in a shared - // group. - SoundRetained[] mirrorSounds = new SoundRetained[1]; - - // The number of valid sounds in mirrorSounds - int numMirrorSounds = 0; - - /** - * Array of references to sound scheduler atoms associated with this node. - * For each view that a sound node is associated with a sound scheduler - * atom is created and maintained - */ - // for a particular view that are playing either audibly or silently. - private SoundSchedulerAtom[] loadedAtoms = new SoundSchedulerAtom[1]; - private int atomCount = 0; - - /** - * This is true when this sound is referenced in an immediate mode context - */ - boolean inImmCtx = false; - - /** - * Load Sound Data Status - */ - static final int LOAD_COMPLETE = 2; - // load requested but could not be performed due because sound not live - static final int LOAD_PENDING = 1; - static final int LOAD_NULL = 0; - static final int LOAD_FAILED = -1; - int loadStatus = LOAD_NULL; - long duration = Sound.DURATION_UNKNOWN; - - // Static initializer for SoundRetained class - static { - VirtualUniverse.loadLibraries(); - } - - // Target threads to be notified when sound changes - static final int targetThreads = J3dThread.UPDATE_SOUND | - J3dThread.SOUND_SCHEDULER; - - // Is true, if the mirror light is viewScoped - boolean isViewScoped = false; - - - /** - * Dispatch a message about a sound attribute change - */ - void dispatchAttribChange(int dirtyBit, Object argument) { - // Send message including a integer argument - J3dMessage createMessage = new J3dMessage(); - createMessage.threads = J3dThread.UPDATE_SOUND | - J3dThread.SOUND_SCHEDULER; - createMessage.type = J3dMessage.SOUND_ATTRIB_CHANGED; - createMessage.universe = universe; - createMessage.args[0] = this; - createMessage.args[1]= new Integer(dirtyBit); - if (inSharedGroup) - createMessage.args[2] = new Integer(numMirrorSounds); - else - createMessage.args[2] = new Integer(1); - createMessage.args[3] = mirrorSounds.clone(); - createMessage.args[4] = argument; - if (debugFlag) - debugPrint("dispatchAttribChange with " + dirtyBit); - VirtualUniverse.mc.processMessage(createMessage); - } - - /** - * Dispatch a message about a sound state change - */ - void dispatchStateChange(int dirtyBit, Object argument) { - // Send message including a integer argument - J3dMessage createMessage = new J3dMessage(); - createMessage.threads = J3dThread.UPDATE_SOUND | - J3dThread.SOUND_SCHEDULER; - createMessage.type = J3dMessage.SOUND_STATE_CHANGED; - createMessage.universe = universe; - createMessage.args[0] = this; - createMessage.args[1]= new Integer(dirtyBit); - if (inSharedGroup) - createMessage.args[2] = new Integer(numMirrorSounds); - else - createMessage.args[2] = new Integer(1); - createMessage.args[3] = mirrorSounds.clone(); - createMessage.args[4] = argument; - if (debugFlag) - debugPrint("dispatchStateChange with " + dirtyBit); - VirtualUniverse.mc.processMessage(createMessage); - } - - /** - * Assign value into sound data field - * @param soundData description of sound source data - */ - void setSoundDataState(MediaContainer soundData) { - this.soundData = soundData; - } - - /** - * Associates sound data with this sound source node - * Attempt to load sound - * @param soundData descrition of sound source data - */ - void setSoundData(MediaContainer soundData) { - // if resetting soundData to the same value don't bother doing anything - if (this.soundData == soundData) { - return; - } - - if (this.soundData != null) { - // this sound node had older sound data; clear it out - ((MediaContainerRetained)this.soundData.retained).removeUser(this); - } - - if (source != null && source.isLive()) { - if (this.soundData != null) { - ((MediaContainerRetained)this.soundData.retained).clearLive(refCount); - } - - if (soundData != null) { - ((MediaContainerRetained)soundData.retained).setLive(inBackgroundGroup, refCount); - ((MediaContainerRetained)soundData.retained).addUser(this); - } - } - - this.soundData = soundData; - dispatchAttribChange(SOUND_DATA_DIRTY_BIT, soundData); - - if (source != null && source.isLive()) { - notifySceneGraphChanged(false); - } - } - - /** - * Retrieves sound data associated with this sound source node - * @return sound source data container - */ - MediaContainer getSoundData() { - return ( this.soundData ); - } - - - /** - * Set the gain scale factor applied to this sound - * @param amplitude gain scale factor - */ - void setInitialGain(float scaleFactor) { - if (scaleFactor < 0.0f) - this.initialGain = 0.0f; - else - this.initialGain = scaleFactor; - - dispatchAttribChange(INITIAL_GAIN_DIRTY_BIT, (new Float(scaleFactor))); - if (source != null && source.isLive()) { - notifySceneGraphChanged(false); - } - } - /** - * Get the overall gain (applied to the sound data associated with source). - * @return overall gain of sound source - */ - float getInitialGain() { - return (float) this.initialGain; - } - - - /** - * Sets the sound's loop count - * @param loopCount number of times sound is looped during play - */ - void setLoop(int loopCount) { - if (loopCount < -1) - this.loopCount = -1; - else - this.loopCount = (int) loopCount; - if (debugFlag) - debugPrint("setLoopCount called with " + this.loopCount); - - dispatchAttribChange(LOOP_COUNT_DIRTY_BIT, (new Integer(loopCount))); - if (source != null && source.isLive()) { - notifySceneGraphChanged(false); - } - } - - /** - * Retrieves the loop count - * @return loop count for data associated with sound - */ - int getLoop() { - return (int) this.loopCount; - } - - /** - * Enable or disable the release flag for this sound source - * @param state flag denoting release sound before stopping - */ - void setReleaseEnable(boolean state) { - this.release = state; - dispatchAttribChange(RELEASE_DIRTY_BIT, (state ? Boolean.TRUE: Boolean.FALSE)); - if (source != null && source.isLive()) { - notifySceneGraphChanged(false); - } - } - - /** - * Retrieves release flag for sound associated with this source node - * @return sound's release flag - */ - boolean getReleaseEnable() { - return (boolean) this.release; - } - - /** - * Enable or disable continuous play flag - * @param state denotes if sound continues playing silently when deactivated - */ - void setContinuousEnable(boolean state) { - this.continuous = state; - dispatchAttribChange(CONTINUOUS_DIRTY_BIT, (state ? Boolean.TRUE: Boolean.FALSE)); - if (source != null && source.isLive()) { - notifySceneGraphChanged(false); - } - } - - /** - * Retrieves sound's continuous play flag - * @return flag denoting if deactivated sound silently continues playing - */ - boolean getContinuousEnable() { - return (boolean) this.continuous; - } - - /** - * Sets the flag denotine sound enabled/disabled and sends a message - * for the following to be done: - * If state is true: - * if sound is not playing, sound is started. - * if sound is playing, sound is stopped, then re-started. - * If state is false: - * if sound is playing, sound is stopped - * @param state true or false to enable or disable the sound - */ - void setEnable(boolean state) { - enable = state; - // QUESTION: Is this still valid code? - if (source != null && source.isLive()) { - notifySceneGraphChanged(false); - } - dispatchStateChange(ENABLE_DIRTY_BIT, (new Boolean(enable))); - } - - /** - * Retrieves sound's enabled flag - * @return sound enabled flag - */ - boolean getEnable() { - return enable; - } - - /** - * Set the Sound's scheduling region. - * @param region a region that contains the Sound's new scheduling region - */ - void setSchedulingBounds(Bounds region) { - if (region != null) { - schedulingRegion = (Bounds) region.clone(); - if (staticTransform != null) { - schedulingRegion.transform(staticTransform.transform); - } - // QUESTION: Clone into transformedRegion IS required. Why? - transformedRegion = (Bounds) schedulingRegion.clone(); - if (debugFlag) - debugPrint("setSchedulingBounds for a non-null region"); - } - else { - schedulingRegion = null; - // QUESTION: Is transformedRegion of node (not mirror node) - // even looked at??? - transformedRegion = null; - if (debugFlag) - debugPrint("setSchedulingBounds for a NULL region"); - } - // XXXX: test that this works - could not new Bounds() since - // Bounds is an abstract class and can't be instantiated - dispatchAttribChange(BOUNDS_DIRTY_BIT, region); - if (source != null && source.isLive()) { - notifySceneGraphChanged(false); - } - } - - /** - * Get the Sound's scheduling region. - * @return this Sound's scheduling region information - */ - Bounds getSchedulingBounds() { - Bounds b = null; - - if (this.schedulingRegion != null) { - b = (Bounds) schedulingRegion.clone(); - if (staticTransform != null) { - Transform3D invTransform = staticTransform.getInvTransform(); - b.transform(invTransform); - } - } - return b; - } - - /** - * Set the Sound's scheduling region to the specified Leaf node. - */ - void setSchedulingBoundingLeaf(BoundingLeaf region) { - int i; - int numSnds = numMirrorSounds; - if (numMirrorSounds == 0) - numSnds = 1; - - if ((boundingLeaf != null) && - (source != null && source.isLive())) { - // Remove the mirror lights as users of the original bounding leaf - for (i = 0; i < numSnds; i++) { - boundingLeaf.mirrorBoundingLeaf.removeUser(mirrorSounds[i]); - } - } - - if (region != null) { - boundingLeaf = (BoundingLeafRetained)region.retained; - // Add all mirror sounds as user of this bounding leaf - if (source != null && source.isLive()) { - for (i = 0; i < numSnds; i++) { - boundingLeaf.mirrorBoundingLeaf.addUser(mirrorSounds[i]); - } - } - } else { - boundingLeaf = null; - } - // XXXX: since BoundingLeaf constructor only takes Bounds - // test if region passed into dispatchAttribChange correctly. - dispatchAttribChange(BOUNDING_LEAF_DIRTY_BIT, region); - if (source != null && source.isLive()) { - notifySceneGraphChanged(false); - } - } - - /** - * Get the Sound's scheduling region - */ - BoundingLeaf getSchedulingBoundingLeaf() { - if (boundingLeaf != null) { - return((BoundingLeaf)boundingLeaf.source); - } else { - return null; - } - } - - // The update Object function. - @Override - synchronized void updateMirrorObject(Object[] objs) { - Transform3D trans = null; - int component = ((Integer)objs[1]).intValue(); - if (component == -1) { // update everything - // object 2 contains the mirror object that needs to be - // updated - initMirrorObject(((SoundRetained)objs[2])); - } - - // call the parent's mirror object update routine - super.updateMirrorObject(objs); - - } - - void updateBoundingLeaf(long refTime) { - // This is necessary, if for example, the region - // changes from sphere to box. - if (boundingLeaf != null && boundingLeaf.switchState.currentSwitchOn) { - transformedRegion = boundingLeaf.transformedRegion; - } else { // evaluate schedulingRegion if not null - if (schedulingRegion != null) { - transformedRegion = schedulingRegion.copy(transformedRegion); - transformedRegion.transform(schedulingRegion, - getLastLocalToVworld()); - } else { - transformedRegion = null; - } - } - } - - - /** - * Set sound's proirity value. - * @param priority value used to order sound's importance for playback. - */ - void setPriority(float rank) { - if (rank == this.priority) - // changing priority is expensive in the sound scheduler(s) - // so only dispatch a message if 'new' priority value is really - // different - return; - - this.priority = rank; - dispatchAttribChange(PRIORITY_DIRTY_BIT, (new Float(rank))); - if (source != null && source.isLive()) { - notifySceneGraphChanged(false); - } - } - - /** - * Retrieves sound's priority value. - * @return sound priority value - */ - float getPriority() { - return (this.priority); - } - - - /** - * Retrieves sound's duration in milliseconds - * @return sound's duration, returns DURATION_UNKNOWN if duration could - * not be queried from the audio device - */ - long getDuration() { - return (duration); - } - - - /** - * Set scale factor - * @param scaleFactor applied to sound playback rate - */ - void setRateScaleFactor(float scaleFactor) { - this.rate = scaleFactor; - dispatchAttribChange(RATE_DIRTY_BIT, (new Float(scaleFactor))); - if (source != null && source.isLive()) { - notifySceneGraphChanged(false); - } - } - - /** - * Retrieves sound's rate scale factor - * @return sound rate scale factor - */ - float getRateScaleFactor() { - return (this.rate); - } - - void changeAtomList(SoundSchedulerAtom atom, int loadStatus) { - if (atom == null) - return; - if (loadStatus == SoundRetained.LOAD_COMPLETE) { - // atom is successfully loaded, so add this atom to array of atoms - // associated with this sound, if not already in list - for (int i=0; i<atomCount; i++) { - if (atom == loadedAtoms[i]) - return; - } - // add atom to list - atomCount++; - int currentArrayLength = loadedAtoms.length; - if (atomCount > currentArrayLength) { - // expand array - replace with a larger array - loadedAtoms = new SoundSchedulerAtom[2*currentArrayLength]; - } - loadedAtoms[atomCount-1] = atom; // store reference to new atom - // all atoms sample durations SHOULD be the same so store it in node - this.duration = atom.sampleLength; // XXXX: refine later? in ms - } - else { // atom is NOT loaded or has been unloaded; remove from list - if (atomCount == 0) - return; - - // remove atom from array of playing atoms if it is in list - boolean atomFound = false; - int i; - for (i=0; i<atomCount; i++) { - if (atom == loadedAtoms[i]) { - atomFound = true; - continue; - } - } - if (!atomFound) - return; - - // otherwise remove atom from list by close up list - for (int j=i; j<atomCount; j++) { - loadedAtoms[j] = loadedAtoms[j+1]; - } - atomCount--; - if (atomCount == 0) - this.duration = Sound.DURATION_UNKNOWN; // clear sound duration - } - } - - /** - * Retrieves sound's ready state for ALL active views. - * For this node, the list of sound scheduler atoms associated with - * each view is maintained. The 'loaded' (=is ready) state is - * true only if the following are true for all views/sound schedulers: - * - * <ul> - * 1) the Sound node has a non-null sound data and this data has - * sucessfully been loaded/opened/copied/attached;<br> - * 2) the Sound node is live;<br> - * 3) there is at least one active View in the Universe; and<br> - * 4) an instance of an AudioDevice is attached to the current - * PhysicalEnvironment. - * </ul> - * - * @return true if potentially playable (audibly or silently); false otherwise - */ - boolean isReady() { - // all the atoms in the atom list must be are ready for this - // method to return true - // if any non-null atoms are found NOT ready, return false. - boolean atomFoundReady = true; - for (int i=0; i<atomCount; i++) { - SoundSchedulerAtom atom = loadedAtoms[i]; - if (atom == null || atom.soundScheduler == null) - continue; - else - if (atom.loadStatus == SoundRetained.LOAD_COMPLETE) { - atomFoundReady = true; - continue; - } - else - return false; - } - if (atomFoundReady) // at least on atom found ready - return true; - else - // not even one atom is associated with node so none are loaded - return false; - } - - /** - * Retrieves sound's ready state for a particular view. - * For this node, the list of sound scheduler atoms associated with - * each view is maintained. The 'loaded' (=is ready) state is - * true only if the following are true for the given view: - * - * <ul> - * 1) the Sound node has a non-null sound data and this data has - * sucessfully been loaded/opened/copied/attached;<br> - * 2) the Sound node is live;<br> - * 3) the given View is active in the Universe; and<br> - * 4) an instance of an AudioDevice is attached to the current - * PhysicalEnvironment. - * </ul> - * - * @param viewRef view to test sound readiness for - * @return true if potentially playable (audibly or silently); false otherwise - */ - boolean isReady(View viewRef) { - // if an atom in the atom list that is associated with the - // given view is found and has been loaded than return true, - // otherwise return false. - if (viewRef == null) - return false; - for (int i=0; i<atomCount; i++) { - SoundSchedulerAtom atom = loadedAtoms[i]; - if (atom == null || atom.soundScheduler == null) - continue; - if (atom.soundScheduler.view == viewRef) - if (atom.loadStatus != SoundRetained.LOAD_COMPLETE) - return false; - else - return true; - else // atom is not associated with given referenced view - continue; - } - return false; // sound scheduler atom for given view not found - - } - - // ******************************* - // Play Status - isPlaying states - // ******************************* - - /** - * Retrieves sound's playing status - * true if potentially audible (enabled and active) on ANY audio device - * false otherwise - * @return sound playing flag - */ - boolean isPlaying() { - for (int i=0; i<atomCount; i++) { - SoundSchedulerAtom atom = loadedAtoms[i]; - if (atom == null || atom.soundScheduler == null) - continue; - if (atom.status == SoundSchedulerAtom.SOUND_AUDIBLE) - return true; - else - continue; // look for at lease one atom that is playing - } - // not even one atom is associated with this node so none are playing - return false; - } - - /** - * Retrieves sound's playing status for a particular view - * true if potentially audible (enabled and active) on audio device - * associated with the given view - * false otherwise - * @param viewRef view to test sound playing state for - * @return sound playing flag - */ - boolean isPlaying(View viewRef) { - if (viewRef == null) - return false; - for (int i=0; i<atomCount; i++) { - SoundSchedulerAtom atom = loadedAtoms[i]; - if (atom == null || atom.soundScheduler == null) - continue; - if (atom.soundScheduler.view == viewRef) { - if (atom.status == SoundSchedulerAtom.SOUND_AUDIBLE) - return true; - else - return false; - } - else // atom is not associated with given referenced view - continue; - } - return false; // atom associated with this view not found in list - } - - /** - * Retrieves sound's playing silently status - * true if enabled but not active (on any device) - * false otherwise - * @return sound playing flag - */ - boolean isPlayingSilently() { - for (int i=0; i<atomCount; i++) { - SoundSchedulerAtom atom = loadedAtoms[i]; - if (atom == null || atom.soundScheduler == null) - continue; - if (atom.status == SoundSchedulerAtom.SOUND_SILENT) - return true; - else - return false; - } - return false; // atom not found in list or not playing audibilly - } - - /** - * Retrieves sound's playing silently status for a particular view - * true if potentially audible (enabled and active) on audio device - * associated with the given view - * false otherwise - * @param viewRef view to test sound playing silently state for - * @return sound playing flag - */ - boolean isPlayingSilently(View viewRef) { - if (viewRef == null) - return false; - for (int i=0; i<atomCount; i++) { - SoundSchedulerAtom atom = loadedAtoms[i]; - if (atom == null || atom.soundScheduler == null) - continue; - if (atom.soundScheduler.view == viewRef) { - if (atom.status == SoundSchedulerAtom.SOUND_SILENT) - return true; - else - return false; - } - else // atom is not associated with given referenced view - continue; - } - return false; // atom associated with this view not found in list - } - - /** - * Retrieves number of channels allocated for this sound on the primary - * view's audio device. - * @return number of channels used by sound across all devices - */ - int getNumberOfChannelsUsed() { - // retrieves the number of channels used by the atom that is: - // loaded, and - // playing either audibily or silently - // on the device associated with the primary view. - View primaryView = this.universe.getCurrentView(); - if (primaryView == null) - return 0; - - // find atom associated with primary view (VirtualUniverse currentView) - // then return the number of channels associated with that atom - SoundSchedulerAtom atom; - for (int i=0; i<atomCount; i++) { - atom = loadedAtoms[i]; - if (atom == null || atom.soundScheduler == null) - continue; - if (atom.soundScheduler.view == primaryView) { - return atom.numberChannels; - } - } - return 0; // atom associated with primary view not found - } - - /** - * Retrieves number of channels allocated for this sound on the audio - * devices associated with a given view. - * @param viewRef view to test sound playing silently state for - * @return number of channels used by this sound on a particular device - */ - int getNumberOfChannelsUsed(View viewRef) { - // retrieves the number of channels used by the atom that is: - // loaded, and - // playing either audibily or silently - // on the device associated with the given view. - if (viewRef == null) - return 0; - SoundSchedulerAtom atom; - for (int i=0; i<atomCount; i++) { - atom = loadedAtoms[i]; - if (atom == null || atom.soundScheduler == null) - continue; - if (atom.soundScheduler.view == viewRef) { - return atom.numberChannels; - } - } - return 0; // atom associated with primary view not found - } - - /** - * Set mute state flag. If the sound is playing it will be set to - * play silently - * @param state flag - * @since Java 3D 1.3 - */ - void setMute(boolean state) { - this.mute = state; - dispatchAttribChange(MUTE_DIRTY_BIT, (state ? Boolean.TRUE: Boolean.FALSE)); - if (source != null && source.isLive()) { - notifySceneGraphChanged(false); - } - } - - /** - * Retrieves sound Mute state. - * A return value of true does not imply that the sound has - * been started playing or is still playing silently. - * @return mute state flag - * @since Java 3D 1.3 - */ - boolean getMute() { - return (boolean) this.mute; - } - - /** - * Set pause state flag. If the sound is playing it will be paused - * @param state flag - * @since Java 3D 1.3 - */ - void setPause(boolean state) { - this.pause = state; - dispatchAttribChange(PAUSE_DIRTY_BIT, (state ? Boolean.TRUE: Boolean.FALSE)); - if (source != null && source.isLive()) { - notifySceneGraphChanged(false); - } - } - - /** - * Retrieves sound Pause state. - * A return value of true does not imply that the sound has - * been started playing auditibly or silently. - * @return mute state flag - * @since Java 3D 1.3 - */ - boolean getPause() { - return (boolean) this.pause; - } - - - /** - * This sets the immedate mode context flag - */ - void setInImmCtx(boolean inCtx) { - inImmCtx = inCtx; - } - - /** - * This gets the immedate mode context flag - */ - boolean getInImmCtx() { - return (inImmCtx); - } - - /** - * This gets the mirror sound for this sound given the key. - */ - SoundRetained getMirrorSound(HashKey key) { - int i; - SoundRetained[] newSounds; - - if (inSharedGroup) { - for (i=0; i<numMirrorSounds; i++) { - if (mirrorSounds[i].key.equals(key)) { - return(mirrorSounds[i]); - } - } - if (numMirrorSounds == mirrorSounds.length) { - newSounds = new SoundRetained[numMirrorSounds*2]; - for (i=0; i<numMirrorSounds; i++) { - newSounds[i] = mirrorSounds[i]; - } - mirrorSounds = newSounds; - } - // mirrorSounds[numMirrorSounds] = (SoundRetained) this.clone(); - mirrorSounds[numMirrorSounds] = (SoundRetained) this.clone(); - //mirrorSounds[numMirrorSounds].key = new HashKey(key); - mirrorSounds[numMirrorSounds].key = key; - mirrorSounds[numMirrorSounds].sgSound = this; - return(mirrorSounds[numMirrorSounds++]); - } else { - if (mirrorSounds[0] == null) { - // mirrorSounds[0] = (SoundRetained) this.clone(true); - mirrorSounds[0] = (SoundRetained) this.clone(); - mirrorSounds[0].sgSound = this; - } - return(mirrorSounds[0]); - } - } - - synchronized void initMirrorObject(SoundRetained ms) { - GroupRetained group; - Transform3D trans; - Bounds region = null; - - ms.setSchedulingBounds(getSchedulingBounds()); - ms.setSchedulingBoundingLeaf(getSchedulingBoundingLeaf()); - ms.sgSound = sgSound; -/* -// QUESTION: these are not set in LightRetained??? - ms.key = null; - ms.mirrorSounds = new SoundRetained[1]; - ms.numMirrorSounds = 0; -*/ - ms.inImmCtx = inImmCtx; - ms.setSoundData(getSoundData()); - -// XXXX: copy ms.atoms array from this.atoms - - ms.parent = parent; - ms.inSharedGroup = false; - ms.locale = locale; - ms.parent = parent; - ms.localBounds = (Bounds)localBounds.clone(); - - ms.transformedRegion = null; - if (boundingLeaf != null) { - if (ms.boundingLeaf != null) - ms.boundingLeaf.removeUser(ms); - ms.boundingLeaf = boundingLeaf.mirrorBoundingLeaf; - // Add this mirror object as user - ms.boundingLeaf.addUser(ms); - ms.transformedRegion = ms.boundingLeaf.transformedRegion; - } - else { - ms.boundingLeaf = null; - } - - if (schedulingRegion != null) { - ms.schedulingRegion = (Bounds) schedulingRegion.clone(); - // Assign region only if bounding leaf is null - if (ms.transformedRegion == null) { - ms.transformedRegion = (Bounds) ms.schedulingRegion.clone(); - ms.transformedRegion.transform(ms.schedulingRegion, - ms.getLastLocalToVworld()); - } - - } - else { - ms.schedulingRegion = null; - } - } - - @Override - void setLive(SetLiveState s) { - SoundRetained ms; - int i, j; - - if (debugFlag) - debugPrint("Sound.setLive"); - - if (inImmCtx) { - throw new - IllegalSharingException(J3dI18N.getString("SoundRetained2")); - } - super.setLive(s); - if (inBackgroundGroup) { - throw new - IllegalSceneGraphException(J3dI18N.getString("SoundRetained3")); - } - - if (this.loadStatus == LOAD_PENDING) { - if (debugFlag) - debugPrint("Sound.setLive load Sound"); - dispatchStateChange(LOAD_SOUND_DIRTY_BIT, soundData); - } - - if (this.soundData != null) { - ((MediaContainerRetained)this.soundData.retained).setLive(inBackgroundGroup, s.refCount); - } - - if (s.inSharedGroup) { - for (i=0; i<s.keys.length; i++) { - ms = this.getMirrorSound(s.keys[i]); - ms.localToVworld = new Transform3D[1][]; - ms.localToVworldIndex = new int[1][]; - - j = s.keys[i].equals(localToVworldKeys, 0, - localToVworldKeys.length); - if(j < 0) { - System.err.println("SoundRetained : Can't find hashKey"); - } - - ms.localToVworld[0] = localToVworld[j]; - ms.localToVworldIndex[0] = localToVworldIndex[j]; - // If its view Scoped, then add this list - // to be sent to Sound Structure - if ((s.viewScopedNodeList != null) && (s.viewLists != null)) { - s.viewScopedNodeList.add(ms); - s.scopedNodesViewList.add(s.viewLists.get(i)); - } else { - s.nodeList.add(ms); - } - // Initialization of the mirror object during the INSERT_NODE - // message (in updateMirrorObject) - if (s.switchTargets != null && s.switchTargets[i] != null) { - s.switchTargets[i].addNode(ms, Targets.SND_TARGETS); - } - ms.switchState = s.switchStates.get(j); - if (s.transformTargets != null && - s.transformTargets[i] != null) { - s.transformTargets[i].addNode(ms, Targets.SND_TARGETS); - s.notifyThreads |= J3dThread.UPDATE_TRANSFORM; - } - } - } else { - ms = this.getMirrorSound(null); - ms.localToVworld = new Transform3D[1][]; - ms.localToVworldIndex = new int[1][]; - ms.localToVworld[0] = this.localToVworld[0]; - ms.localToVworldIndex[0] = this.localToVworldIndex[0]; - // If its view Scoped, then add this list - // to be sent to Sound Structure - if ((s.viewScopedNodeList != null) && (s.viewLists != null)) { - s.viewScopedNodeList.add(ms); - s.scopedNodesViewList.add(s.viewLists.get(0)); - } else { - s.nodeList.add(ms); - } - // Initialization of the mirror object during the INSERT_NODE - // message (in updateMirrorObject) - if (s.switchTargets != null && s.switchTargets[0] != null) { - s.switchTargets[0].addNode(ms, Targets.SND_TARGETS); - } - ms.switchState = s.switchStates.get(0); - if (s.transformTargets != null && - s.transformTargets[0] != null) { - s.transformTargets[0].addNode(ms, Targets.SND_TARGETS); - s.notifyThreads |= J3dThread.UPDATE_TRANSFORM; - } - } - dispatchStateChange(LIVE_DIRTY_BIT, soundData); - s.notifyThreads |= targetThreads; - } - - @Override - void clearLive(SetLiveState s) { - SoundRetained ms; - - super.clearLive(s); - -// XXXX: if (inSharedGroup) - - if (s.inSharedGroup) { - for (int i=0; i<s.keys.length; i++) { - ms = this.getMirrorSound(s.keys[i]); - if (s.switchTargets != null && - s.switchTargets[i] != null) { - s.switchTargets[i].addNode(ms, Targets.SND_TARGETS); - } - if (s.transformTargets != null && s.transformTargets[i] != null) { - s.transformTargets[i].addNode(ms, Targets.SND_TARGETS); - s.notifyThreads |= J3dThread.UPDATE_TRANSFORM; - } - // If its view Scoped, then add this list - // to be sent to Sound Structure - if ((s.viewScopedNodeList != null) && (s.viewLists != null)) { - s.viewScopedNodeList.add(ms); - s.scopedNodesViewList.add(s.viewLists.get(i)); - } else { - s.nodeList.add(ms); - } - } - } else { - ms = this.getMirrorSound(null); - if (s.switchTargets != null && - s.switchTargets[0] != null) { - s.switchTargets[0].addNode(ms, Targets.SND_TARGETS); - } - if (s.transformTargets != null && - s.transformTargets[0] != null) { - s.transformTargets[0].addNode(ms, Targets.SND_TARGETS); - s.notifyThreads |= J3dThread.UPDATE_TRANSFORM; - } - // If its view Scoped, then add this list - // to be sent to Sound Structure - if ((s.viewScopedNodeList != null) && (s.viewLists != null)) { - s.viewScopedNodeList.add(ms); - s.scopedNodesViewList.add(s.viewLists.get(0)); - } else { - s.nodeList.add(ms); - } - } - s.notifyThreads |= targetThreads; - - if (this.soundData != null) { - ((MediaContainerRetained)this.soundData.retained).clearLive(s.refCount); - } - } - - @Override - void mergeTransform(TransformGroupRetained xform) { - super.mergeTransform(xform); - if (schedulingRegion != null) { - schedulingRegion.transform(xform.transform); - } - } - -/* - // This makes passed in sound look just like this sound -// QUESTION: DOesn't appread to be called -// XXXX: ...if so, remove... - synchronized void update(SoundRetained sound) { - if (debugFlag) - debugPrint("Sound.update ******** entered ***** this = " + this + - ", and sound param = " + sound); - - sound.soundData = soundData; - sound.initialGain = initialGain; - sound.loopCount = loopCount; - sound.release = release; - sound.continuous = continuous; - sound.enable = enable; // used to be 'on' - sound.inImmCtx = inImmCtx; - -// QUESTION: -// This line removed from 1.1.1 version; why ??? - sound.currentSwitchOn = currentSwitchOn; - -// NEW: - sound.priority = priority; - -// QUESTION: With code below, no sound schedulingRegion found -// sound.schedulingRegion = schedulingRegion; -// sound.boundingLeaf = boundingLeaf; -// XXXX: clone of region used in Traverse code, why not here??? -// if (schedulingRegion != null) -// sound.schedulingRegion = (Bounds)schedulingRegion.clone(); -// XXXX: BoundingLeafRetained boundingLeaf ... -// WHAT ABOUT transformedRegion?? - -// XXXX: Update ALL fields -// ALL THE BELOW USED TO COMMENTED OUT vvvvvvvvvvvvvvvvvvvvvvvvvvvvv - sound.sampleLength = sampleLength; - sound.loopStartOffset = loopStartOffset; - sound.loopLength = loopLength; - sound.attackLength = attackLength; - sound.releaseLength = releaseLength; - - sound.sgSound = sgSound; - sound.key = key; - sound.numMirrorSounds = numMirrorSounds; - for (int index=0; index<numMirrorSounds; index++) - sound.mirrorSounds = mirrorSounds; - sound.universe = universe; - if (universe.sounds.contains(sound) == false) { - universe.sounds.addElement(sound); - } - if (debugFlag) - debugPrint("update****************************** exited"); -^^^^^^^^^^^ COMMENTED OUT - } -*/ - - - // Called on mirror object -// QUESTION: doesn't transformed region need to be saved??? - @Override - void updateTransformChange() { - // If bounding leaf is null, tranform the bounds object - if (debugFlag) - debugPrint("SoundRetained.updateTransformChange()"); - if (boundingLeaf == null) { - if (schedulingRegion != null) { - transformedRegion = schedulingRegion.copy(transformedRegion); - transformedRegion.transform(schedulingRegion, - getLastLocalToVworld()); - } - } - dispatchStateChange(XFORM_DIRTY_BIT, null); - } - -// QUESTION: -// Clone method (from 1.1.1 version) removed!?!?!? yet LightRetained has it - - - - // Debug print mechanism for Sound nodes - static final boolean debugFlag = false; - static final boolean internalErrors = false; - - void debugPrint(String message) { - if (debugFlag) { - System.err.println(message); - } - } - @Override - void getMirrorObjects(ArrayList leafList, HashKey key) { - if (key == null) { - leafList.add(mirrorSounds[0]); - } - else { - for (int i=0; i<numMirrorSounds; i++) { - if (mirrorSounds[i].key.equals(key)) { - leafList.add(mirrorSounds[i]); - break; - } - } - - } - } - -} |