From 7a2e20caac9db6f789a7b3fab344b9758af45335 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Sun, 19 Apr 2015 21:02:06 -0700 Subject: j3dcore: flatten the directory structure a bit Signed-off-by: Harvey Harrison --- src/javax/media/j3d/SoundStructure.java | 741 ++++++++++++++++++++++++++++++++ 1 file changed, 741 insertions(+) create mode 100644 src/javax/media/j3d/SoundStructure.java (limited to 'src/javax/media/j3d/SoundStructure.java') diff --git a/src/javax/media/j3d/SoundStructure.java b/src/javax/media/j3d/SoundStructure.java new file mode 100644 index 0000000..05df38f --- /dev/null +++ b/src/javax/media/j3d/SoundStructure.java @@ -0,0 +1,741 @@ +/* + * Copyright 1998-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; +import java.util.Arrays; +import java.util.HashMap; + +/** + * A sound structure is a object that organizes Sounds and + * soundscapes. + * This structure parallels the RenderingEnv structure and + * is used for sounds + */ + +class SoundStructure extends J3dStructure { + /** + * The list of Sound nodes + */ + UnorderList nonViewScopedSounds = new UnorderList(SoundRetained.class); + HashMap viewScopedSounds = new HashMap(); + + /** + * The list of Soundscapes + */ + UnorderList nonViewScopedSoundscapes = new UnorderList(SoundscapeRetained.class); + HashMap viewScopedSoundscapes = new HashMap(); + + /** + * The list of view platforms + */ + UnorderList viewPlatforms = new UnorderList(ViewPlatformRetained.class); + + /** + * A bounds used for getting a view platform scheduling BoundingSphere + */ + BoundingSphere tempSphere = new BoundingSphere(); + BoundingSphere vpsphere = new BoundingSphere(); + + // ArrayList of leafRetained object whose mirrorObjects + // should be updated + ArrayList objList = new ArrayList(); + + // ArrayList of leafRetained object whose boundingleaf xform + // should be updated + ArrayList xformChangeList = new ArrayList(); + + // ArrayList of switches that have changed + ArrayList switchChangeLeafNodes = new ArrayList(); + ArrayList switchChangeLeafMasks = new ArrayList(); + + // variables for processing transform messages + boolean transformMsg = false; + UpdateTargets targets = null; + + /** + * This constructor does nothing + */ + SoundStructure(VirtualUniverse u) { + super(u, J3dThread.UPDATE_SOUND); + if (debugFlag) + debugPrint("SoundStructure constructed"); + } + + @Override + void processMessages(long referenceTime) { + J3dMessage messages[] = getMessages(referenceTime); + int nMsg = getNumMessage(); + J3dMessage m; + + if (nMsg <= 0) { + return; + } + + + for (int i=0; i < nMsg; i++) { + m = messages[i]; + + switch (m.type) { + case J3dMessage.INSERT_NODES : + // Prioritize retained and non-retained sounds for this view + insertNodes(m); + break; + case J3dMessage.REMOVE_NODES: + removeNodes(m); + break; + case J3dMessage.SOUND_ATTRIB_CHANGED: + changeNodeAttrib(m); + break; + case J3dMessage.SOUND_STATE_CHANGED: + changeNodeState(m); + break; + case J3dMessage.SOUNDSCAPE_CHANGED: + case J3dMessage.AURALATTRIBUTES_CHANGED: + // XXXX: this needs to be changed + changeNodeAttrib(m); + break; + case J3dMessage.TRANSFORM_CHANGED: + transformMsg = true; + break; + case J3dMessage.SWITCH_CHANGED: + // This method isn't implemented yet. + // processSwitchChanged(m); + // may need to process dirty switched-on transform + if (universe.transformStructure.getLazyUpdate()) { + transformMsg = true; + } + break; + case J3dMessage.VIEWSPECIFICGROUP_CHANGED: + updateViewSpecificGroupChanged(m); + break; + // XXXX: case J3dMessage.BOUNDINGLEAF_CHANGED + } + + /* + // NOTE: this should already be handled by including/ORing + // SOUND_SCHEDULER in targetThread for these message types!! + // Dispatch a message about a sound change + ViewPlatformRetained vpLists[] = (ViewPlatformRetained []) + viewPlatforms.toArray(false); + + // QUESTION: can I just use this message to pass to all the Sound Bins + for (int k=viewPlatforms.arraySize()- 1; k>=0; k--) { + View[] views = vpLists[k].getViewList(); + for (int j=(views.length-1); j>=0; j--) { + View v = (View)(views[j]); + m.view = v; + VirtualUniverse.mc.processMessage(m); + } + } + */ + m.decRefcount(); + } + if (transformMsg) { + targets = universe.transformStructure.getTargetList(); + updateTransformChange(targets, referenceTime); + transformMsg = false; + targets = null; + } + + Arrays.fill(messages, 0, nMsg, null); + } + + void insertNodes(J3dMessage m) { + Object[] nodes = (Object[])m.args[0]; + ArrayList viewScopedNodes = (ArrayList)m.args[3]; + ArrayList> scopedNodesViewList = (ArrayList>)m.args[4]; + + for (int i=0; i vl = scopedNodesViewList.get(i); + int vsize = vl.size(); + if (node instanceof SoundRetained) { + ((SoundRetained)node).isViewScoped = true; + for (int k = 0; k < vsize; k++) { + View view = vl.get(k); + addScopedSound((SoundRetained) node, view); + } + } + else if (node instanceof SoundscapeRetained) { + ((SoundscapeRetained)node).isViewScoped = true; + for (int k = 0; k < vsize; k++) { + View view = vl.get(k); + addScopedSoundscape((SoundscapeRetained) node, view); + } + } + } + } + /* + // XXXX: + if (node instanceof AuralAttributesRetained) { + } + else if (node instanceof ViewPlatformRetained) { + addViewPlatform((ViewPlatformRetained) node); + } + */ + } + + + /** + * Add sound to sounds list. + */ + void addScopedSound(SoundRetained mirSound, View view) { + if (debugFlag) + debugPrint("SoundStructure.addSound()"); + ArrayList l = (ArrayList) viewScopedSounds.get(view); + if (l == null) { + l = new ArrayList(); + viewScopedSounds.put(view, l); + } + l.add(mirSound); + } // end addSound() + + void addNonScopedSound(SoundRetained mirSound) { + if (debugFlag) + debugPrint("SoundStructure.addSound()"); + nonViewScopedSounds.add(mirSound); + } // end addSound() + + + void addScopedSoundscape(SoundscapeRetained soundscape, View view) { + if (debugFlag) + debugPrint("SoundStructure.addSoundscape()"); + ArrayList l = (ArrayList) viewScopedSoundscapes.get(view); + if (l == null) { + l = new ArrayList(); + viewScopedSoundscapes.put(view, l); + } + l.add(soundscape); + } + + void addNonSoundscape(SoundscapeRetained soundscape) { + if (debugFlag) + debugPrint("SoundStructure.addSoundscape()"); + nonViewScopedSoundscapes.add(soundscape); + } + + + @Override + void removeNodes(J3dMessage m) { + Object[] nodes = (Object[])m.args[0]; + ArrayList viewScopedNodes = (ArrayList)m.args[3]; + ArrayList> scopedNodesViewList = (ArrayList>)m.args[4]; + + for (int i=0; i vl = scopedNodesViewList.get(i); + // If the node object is scoped to this view, then .. + int vsize = vl.size(); + + if (node instanceof SoundRetained) { + ((SoundRetained)node).isViewScoped = false; + for (int k = 0; k < vsize; k++) { + View view = vl.get(k); + deleteScopedSound((SoundRetained) node, view); + } + } + else if (node instanceof SoundscapeRetained) { + ((SoundscapeRetained)node).isViewScoped = false; + for (int k = 0; k < vsize; k++) { + View view = vl.get(k); + deleteScopedSoundscape((SoundscapeRetained) node, view); + } + } + } + } + } + + void deleteNonScopedSound(SoundRetained sound) { + if (!nonViewScopedSounds.isEmpty()) { + // find sound in list and remove it + int index = nonViewScopedSounds.indexOf(sound); + nonViewScopedSounds.remove(index); + } + } + + void deleteNonScopedSoundscape(SoundscapeRetained soundscape) { + boolean error = nonViewScopedSoundscapes.remove(soundscape); + } + + void deleteScopedSound(SoundRetained sound, View view) { + ArrayList l = (ArrayList) viewScopedSounds.get(view); + if (!l.isEmpty()) { + // find sound in list and remove it + int index = l.indexOf(sound); + l.remove(index); + } + if (l.isEmpty()) + viewScopedSounds.remove(view); + } + + void deleteScopedSoundscape(SoundscapeRetained soundscape, View view) { + ArrayList l = (ArrayList) viewScopedSoundscapes.get(view); + if (!l.isEmpty()) { + // find sound in list and remove it + int index = l.indexOf(soundscape); + l.remove(index); + } + if (l.isEmpty()) + viewScopedSoundscapes.remove(view); + + } + + void changeNodeAttrib(J3dMessage m) { + int attribDirty; + Object node = m.args[0]; + Object value = m.args[1]; + if (debugFlag) + debugPrint("SoundStructure.changeNodeAttrib:"); + + if (node instanceof SoundRetained) { + attribDirty = ((Integer)value).intValue(); + if (debugFlag) + debugPrint(" Sound node dirty bit = " + attribDirty); + if ((attribDirty & SoundRetained.PRIORITY_DIRTY_BIT) > 0) { + // XXXX: shuffle in SoundScheduler + /* + shuffleSound((SoundRetained) node); + */ + } + if ((attribDirty & SoundRetained.SOUND_DATA_DIRTY_BIT) > 0) { + loadSound((SoundRetained) node, true); + } + ((SoundRetained)node).updateMirrorObject(m.args); + } + if (node instanceof SoundscapeRetained) { +/* + attribDirty = ((Integer)value).intValue(); + if (((attribDirty & SoundscapeRetained.BOUNDING_LEAF_CHANGED) != 0) || + ((attribDirty & SoundscapeRetained.APPLICATION_BOUNDS_CHANGED) != 0) ) { +*/ + ((SoundscapeRetained)node).updateTransformChange(); +/* + } +*/ +// XXXX: have no dirty flag for soundscape, just auralAttributes... +// what if reference to AA changes in soundscape??? + } + + } + + + void changeNodeState(J3dMessage m) { + int stateDirty; + Object node = m.args[0]; + Object value = m.args[1]; + if (debugFlag) + debugPrint("SoundStructure.changeNodeState:"); + if (node instanceof SoundRetained) { + stateDirty = ((Integer)value).intValue(); + if (debugFlag) + debugPrint(" Sound node dirty bit = " + stateDirty); + if ((stateDirty & SoundRetained.LIVE_DIRTY_BIT) > 0) { + loadSound((SoundRetained) node, false); + } + if ((stateDirty & SoundRetained.ENABLE_DIRTY_BIT) > 0) { + enableSound((SoundRetained) node); + } + ((SoundRetained)node).updateMirrorObject(m.args); + } + } + + // return true if one of ViewPlatforms intersect region + boolean intersect(Bounds region) { + if (region == null) + return false; + + ViewPlatformRetained vpLists[] = (ViewPlatformRetained []) + viewPlatforms.toArray(false); + + for (int i=viewPlatforms.arraySize()- 1; i>=0; i--) { + vpLists[i].schedSphere.getWithLock(tempSphere); + if (tempSphere.intersect(region)) { + return true; + } + } + return false; + } + + void loadSound(SoundRetained sound, boolean forceLoad) { +// QUESTION: should not be calling into soundScheduler directly??? + MediaContainer mediaContainer = sound.getSoundData(); + ViewPlatformRetained vpLists[] = (ViewPlatformRetained []) + viewPlatforms.toArray(false); + + for (int i=viewPlatforms.arraySize()- 1; i>=0; i--) { + View[] views = vpLists[i].getViewList(); + for (int j=(views.length-1); j>=0; j--) { + View v = views[j]; +// XXXX: Shouldn't this be done with messages?? + v.soundScheduler.loadSound(sound, forceLoad); + } + } + } + + void enableSound(SoundRetained sound) { + ViewPlatformRetained vpLists[] = (ViewPlatformRetained []) + viewPlatforms.toArray(false); + for (int i=viewPlatforms.arraySize()- 1; i>=0; i--) { + View[] views = vpLists[i].getViewList(); + for (int j=(views.length-1); j>=0; j--) { + View v = views[j]; + v.soundScheduler.enableSound(sound); + } + } + } + + void muteSound(SoundRetained sound) { + ViewPlatformRetained vpLists[] = (ViewPlatformRetained []) + viewPlatforms.toArray(false); + for (int i=viewPlatforms.arraySize()- 1; i>=0; i--) { + View[] views = vpLists[i].getViewList(); + for (int j=(views.length-1); j>=0; j--) { + View v = views[j]; + v.soundScheduler.muteSound(sound); + } + } + } + + void pauseSound(SoundRetained sound) { + ViewPlatformRetained vpLists[] = (ViewPlatformRetained []) + viewPlatforms.toArray(false); + for (int i=viewPlatforms.arraySize()- 1; i>=0; i--) { + View[] views = vpLists[i].getViewList(); + for (int j=(views.length-1); j>=0; j--) { + View v = views[j]; + v.soundScheduler.pauseSound(sound); + } + } + } + + // Implementation be needed. + void processSwitchChanged(J3dMessage m) { + /* + SoundRetained sound; + LeafRetained leaf; + UnorderList arrList; + int size; + Object[] nodes; + + UpdateTargets targets = (UpdateTargets)m.args[0]; + arrList = targets.targetList[Targets.SND_TARGETS]; + + if (arrList != null) { + size = arrList.size(); + nodes = arrList.toArray(false); + + for (int i=size-1; i>=0; i--) { + leaf = (LeafRetained)nodes[i]; + sound = (SoundRetained) leaf; + if (sound.switchState.currentSwitchOn) { + // System.err.println("SoundStructure.switch on"); + // add To Schedule List + } else { + // System.err.println("SoundStructure.switch off"); + // remove From Schedule List + } + } + } + */ + } + +// How can active flag (based on View orientataion) be set here for all Views?!? + + UnorderList getSoundList(View view) { + ArrayList l = (ArrayList)viewScopedSounds.get(view); + // No sounds scoped to this view + if (l == null) + return nonViewScopedSounds; + UnorderList newS = (UnorderList) nonViewScopedSounds.clone(); + int size = l.size(); + for (int i = 0; i < size; i++) { + newS.add(l.get(i)); + } + return newS; + + } + UnorderList getSoundscapeList(View view) { + ArrayList l = (ArrayList)viewScopedSoundscapes.get(view); + // No sounds scoped to this view + if (l == null) + return nonViewScopedSoundscapes; + UnorderList newS = (UnorderList) nonViewScopedSoundscapes.clone(); + int size = l.size(); + for (int i = 0; i < size; i++) { + newS.add(l.get(i)); + } + return newS; + + } + + +/* +// XXXX: how is immediate mode handled? below code taken from SoundSchedule +// Don't know how we'll process immediate mode sounds; +// Append immediate mode sounds to live sounds list + if (graphicsCtx != null) { + synchronized (graphicsCtx.sounds) { + nImmedSounds = graphicsCtx.numSounds(); + numSoundsToProcess = nSounds + nImmedSounds; + if (sounds.length < numSoundsToProcess) { + // increase the array length of sounds array list + // by added 32 elements more than universe list size + sounds = new SoundRetained[numSoundsToProcess + 32]; + } + for (int i=0; i