001: /*
002: * $RCSfile: SoundStructure.java,v $
003: *
004: * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
006: *
007: * This code is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License version 2 only, as
009: * published by the Free Software Foundation. Sun designates this
010: * particular file as subject to the "Classpath" exception as provided
011: * by Sun in the LICENSE file that accompanied this code.
012: *
013: * This code is distributed in the hope that it will be useful, but WITHOUT
014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: * version 2 for more details (a copy is included in the LICENSE file that
017: * accompanied this code).
018: *
019: * You should have received a copy of the GNU General Public License version
020: * 2 along with this work; if not, write to the Free Software Foundation,
021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
024: * CA 95054 USA or visit www.sun.com if you need additional information or
025: * have any questions.
026: *
027: * $Revision: 1.8 $
028: * $Date: 2008/02/28 20:17:30 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import java.util.*;
035:
036: /**
037: * A sound structure is a object that organizes Sounds and
038: * soundscapes.
039: * This structure parallels the RenderingEnv structure and
040: * is used for sounds
041: */
042:
043: class SoundStructure extends J3dStructure {
044: /**
045: * The list of Sound nodes
046: */
047: UnorderList nonViewScopedSounds = new UnorderList(
048: SoundRetained.class);
049: HashMap viewScopedSounds = new HashMap();
050:
051: /**
052: * The list of Soundscapes
053: */
054: UnorderList nonViewScopedSoundscapes = new UnorderList(
055: SoundscapeRetained.class);
056: HashMap viewScopedSoundscapes = new HashMap();
057:
058: /**
059: * The list of view platforms
060: */
061: UnorderList viewPlatforms = new UnorderList(
062: ViewPlatformRetained.class);
063:
064: /**
065: * A bounds used for getting a view platform scheduling BoundingSphere
066: */
067: BoundingSphere tempSphere = new BoundingSphere();
068: BoundingSphere vpsphere = new BoundingSphere();
069:
070: // ArrayList of leafRetained object whose mirrorObjects
071: // should be updated
072: ArrayList objList = new ArrayList();
073:
074: // ArrayList of leafRetained object whose boundingleaf xform
075: // should be updated
076: ArrayList xformChangeList = new ArrayList();
077:
078: // ArrayList of switches that have changed
079: ArrayList switchChangeLeafNodes = new ArrayList();
080: ArrayList switchChangeLeafMasks = new ArrayList();
081:
082: // variables for processing transform messages
083: boolean transformMsg = false;
084: UpdateTargets targets = null;
085:
086: /**
087: * This constructor does nothing
088: */
089: SoundStructure(VirtualUniverse u) {
090: super (u, J3dThread.UPDATE_SOUND);
091: if (debugFlag)
092: debugPrint("SoundStructure constructed");
093: }
094:
095: void processMessages(long referenceTime) {
096: J3dMessage messages[] = getMessages(referenceTime);
097: int nMsg = getNumMessage();
098: J3dMessage m;
099:
100: if (nMsg <= 0) {
101: return;
102: }
103:
104: for (int i = 0; i < nMsg; i++) {
105: m = messages[i];
106:
107: switch (m.type) {
108: case J3dMessage.INSERT_NODES:
109: // Prioritize retained and non-retained sounds for this view
110: insertNodes(m);
111: break;
112: case J3dMessage.REMOVE_NODES:
113: removeNodes(m);
114: break;
115: case J3dMessage.SOUND_ATTRIB_CHANGED:
116: changeNodeAttrib(m);
117: break;
118: case J3dMessage.SOUND_STATE_CHANGED:
119: changeNodeState(m);
120: break;
121: case J3dMessage.SOUNDSCAPE_CHANGED:
122: case J3dMessage.AURALATTRIBUTES_CHANGED:
123: // XXXX: this needs to be changed
124: changeNodeAttrib(m);
125: break;
126: case J3dMessage.TRANSFORM_CHANGED:
127: transformMsg = true;
128: break;
129: case J3dMessage.SWITCH_CHANGED:
130: // This method isn't implemented yet.
131: // processSwitchChanged(m);
132: // may need to process dirty switched-on transform
133: if (universe.transformStructure.getLazyUpdate()) {
134: transformMsg = true;
135: }
136: break;
137: case J3dMessage.VIEWSPECIFICGROUP_CHANGED:
138: updateViewSpecificGroupChanged(m);
139: break;
140: // XXXX: case J3dMessage.BOUNDINGLEAF_CHANGED
141: }
142:
143: /*
144: // NOTE: this should already be handled by including/ORing
145: // SOUND_SCHEDULER in targetThread for these message types!!
146: // Dispatch a message about a sound change
147: ViewPlatformRetained vpLists[] = (ViewPlatformRetained [])
148: viewPlatforms.toArray(false);
149:
150: // QUESTION: can I just use this message to pass to all the Sound Bins
151: for (int k=viewPlatforms.arraySize()- 1; k>=0; k--) {
152: View[] views = vpLists[k].getViewList();
153: for (int j=(views.length-1); j>=0; j--) {
154: View v = (View)(views[j]);
155: m.view = v;
156: VirtualUniverse.mc.processMessage(m);
157: }
158: }
159: */
160: m.decRefcount();
161: }
162: if (transformMsg) {
163: targets = universe.transformStructure.getTargetList();
164: updateTransformChange(targets, referenceTime);
165: transformMsg = false;
166: targets = null;
167: }
168:
169: Arrays.fill(messages, 0, nMsg, null);
170: }
171:
172: void insertNodes(J3dMessage m) {
173: Object[] nodes = (Object[]) m.args[0];
174: ArrayList viewScopedNodes = (ArrayList) m.args[3];
175: ArrayList scopedNodesViewList = (ArrayList) m.args[4];
176: Object node;
177:
178: for (int i = 0; i < nodes.length; i++) {
179: node = (Object) nodes[i];
180: if (node instanceof SoundRetained) {
181: addNonScopedSound((SoundRetained) node);
182: }
183: if (node instanceof SoundscapeRetained) {
184: addNonSoundscape((SoundscapeRetained) node);
185: }
186: }
187: // Handle ViewScoped Nodes
188: if (viewScopedNodes != null) {
189: int size = viewScopedNodes.size();
190: int vlsize;
191: for (int i = 0; i < size; i++) {
192: node = (NodeRetained) viewScopedNodes.get(i);
193: ArrayList vl = (ArrayList) scopedNodesViewList.get(i);
194: int vsize = vl.size();
195: if (node instanceof SoundRetained) {
196: ((SoundRetained) node).isViewScoped = true;
197: for (int k = 0; k < vsize; k++) {
198: View view = (View) vl.get(k);
199: addScopedSound((SoundRetained) node, view);
200: }
201: } else if (node instanceof SoundscapeRetained) {
202: ((SoundscapeRetained) node).isViewScoped = true;
203: for (int k = 0; k < vsize; k++) {
204: View view = (View) vl.get(k);
205: addScopedSoundscape((SoundscapeRetained) node,
206: view);
207: }
208: }
209: }
210: }
211: /*
212: // XXXX:
213: if (node instanceof AuralAttributesRetained) {
214: }
215: else if (node instanceof ViewPlatformRetained) {
216: addViewPlatform((ViewPlatformRetained) node);
217: }
218: */
219: }
220:
221: /**
222: * Add sound to sounds list.
223: */
224: void addScopedSound(SoundRetained mirSound, View view) {
225: if (debugFlag)
226: debugPrint("SoundStructure.addSound()");
227: ArrayList l = (ArrayList) viewScopedSounds.get(view);
228: if (l == null) {
229: l = new ArrayList();
230: viewScopedSounds.put(view, l);
231: }
232: l.add(mirSound);
233: } // end addSound()
234:
235: void addNonScopedSound(SoundRetained mirSound) {
236: if (debugFlag)
237: debugPrint("SoundStructure.addSound()");
238: nonViewScopedSounds.add(mirSound);
239: } // end addSound()
240:
241: void addScopedSoundscape(SoundscapeRetained soundscape, View view) {
242: if (debugFlag)
243: debugPrint("SoundStructure.addSoundscape()");
244: ArrayList l = (ArrayList) viewScopedSoundscapes.get(view);
245: if (l == null) {
246: l = new ArrayList();
247: viewScopedSoundscapes.put(view, l);
248: }
249: l.add(soundscape);
250: }
251:
252: void addNonSoundscape(SoundscapeRetained soundscape) {
253: if (debugFlag)
254: debugPrint("SoundStructure.addSoundscape()");
255: nonViewScopedSoundscapes.add(soundscape);
256: }
257:
258: void removeNodes(J3dMessage m) {
259: Object[] nodes = (Object[]) m.args[0];
260: ArrayList viewScopedNodes = (ArrayList) m.args[3];
261: ArrayList scopedNodesViewList = (ArrayList) m.args[4];
262: Object node;
263:
264: for (int i = 0; i < nodes.length; i++) {
265: node = (Object) nodes[i];
266: if (node instanceof SoundRetained) {
267: deleteNonScopedSound((SoundRetained) node);
268: }
269: if (node instanceof SoundscapeRetained) {
270: deleteNonScopedSoundscape((SoundscapeRetained) node);
271: }
272: }
273: // Handle ViewScoped Nodes
274: if (viewScopedNodes != null) {
275: int size = viewScopedNodes.size();
276: int vlsize;
277: for (int i = 0; i < size; i++) {
278: node = (NodeRetained) viewScopedNodes.get(i);
279: ArrayList vl = (ArrayList) scopedNodesViewList.get(i);
280: // If the node object is scoped to this view, then ..
281: int vsize = vl.size();
282:
283: if (node instanceof SoundRetained) {
284: ((SoundRetained) node).isViewScoped = false;
285: for (int k = 0; k < vsize; k++) {
286: View view = (View) vl.get(k);
287: deleteScopedSound((SoundRetained) node, view);
288: }
289: } else if (node instanceof SoundscapeRetained) {
290: ((SoundscapeRetained) node).isViewScoped = false;
291: for (int k = 0; k < vsize; k++) {
292: View view = (View) vl.get(k);
293: deleteScopedSoundscape(
294: (SoundscapeRetained) node, view);
295: }
296: }
297: }
298: }
299: }
300:
301: void deleteNonScopedSound(SoundRetained sound) {
302: if (!nonViewScopedSounds.isEmpty()) {
303: // find sound in list and remove it
304: int index = nonViewScopedSounds.indexOf(sound);
305: nonViewScopedSounds.remove(index);
306: }
307: }
308:
309: void deleteNonScopedSoundscape(SoundscapeRetained soundscape) {
310: boolean error = nonViewScopedSoundscapes.remove(soundscape);
311: }
312:
313: void deleteScopedSound(SoundRetained sound, View view) {
314: ArrayList l = (ArrayList) viewScopedSounds.get(view);
315: if (!l.isEmpty()) {
316: // find sound in list and remove it
317: int index = l.indexOf(sound);
318: l.remove(index);
319: }
320: if (l.isEmpty())
321: viewScopedSounds.remove(view);
322: }
323:
324: void deleteScopedSoundscape(SoundscapeRetained soundscape, View view) {
325: ArrayList l = (ArrayList) viewScopedSoundscapes.get(view);
326: if (!l.isEmpty()) {
327: // find sound in list and remove it
328: int index = l.indexOf(soundscape);
329: l.remove(index);
330: }
331: if (l.isEmpty())
332: viewScopedSoundscapes.remove(view);
333:
334: }
335:
336: void changeNodeAttrib(J3dMessage m) {
337: int attribDirty;
338: Object node = m.args[0];
339: Object value = m.args[1];
340: if (debugFlag)
341: debugPrint("SoundStructure.changeNodeAttrib:");
342:
343: if (node instanceof SoundRetained) {
344: attribDirty = ((Integer) value).intValue();
345: if (debugFlag)
346: debugPrint(" Sound node dirty bit = "
347: + attribDirty);
348: if ((attribDirty & SoundRetained.PRIORITY_DIRTY_BIT) > 0) {
349: // XXXX: shuffle in SoundScheduler
350: /*
351: shuffleSound((SoundRetained) node);
352: */
353: }
354: if ((attribDirty & SoundRetained.SOUND_DATA_DIRTY_BIT) > 0) {
355: loadSound((SoundRetained) node, true);
356: }
357: ((SoundRetained) node).updateMirrorObject(m.args);
358: }
359: if (node instanceof SoundscapeRetained) {
360: /*
361: attribDirty = ((Integer)value).intValue();
362: if (((attribDirty & SoundscapeRetained.BOUNDING_LEAF_CHANGED) != 0) ||
363: ((attribDirty & SoundscapeRetained.APPLICATION_BOUNDS_CHANGED) != 0) ) {
364: */
365: ((SoundscapeRetained) node).updateTransformChange();
366: /*
367: }
368: */
369: // XXXX: have no dirty flag for soundscape, just auralAttributes...
370: // what if reference to AA changes in soundscape???
371: }
372:
373: }
374:
375: void changeNodeState(J3dMessage m) {
376: int stateDirty;
377: Object node = m.args[0];
378: Object value = m.args[1];
379: if (debugFlag)
380: debugPrint("SoundStructure.changeNodeState:");
381: if (node instanceof SoundRetained) {
382: stateDirty = ((Integer) value).intValue();
383: if (debugFlag)
384: debugPrint(" Sound node dirty bit = "
385: + stateDirty);
386: if ((stateDirty & SoundRetained.LIVE_DIRTY_BIT) > 0) {
387: loadSound((SoundRetained) node, false);
388: }
389: if ((stateDirty & SoundRetained.ENABLE_DIRTY_BIT) > 0) {
390: enableSound((SoundRetained) node);
391: }
392: ((SoundRetained) node).updateMirrorObject(m.args);
393: }
394: }
395:
396: // return true if one of ViewPlatforms intersect region
397: boolean intersect(Bounds region) {
398: if (region == null)
399: return false;
400:
401: ViewPlatformRetained vpLists[] = (ViewPlatformRetained[]) viewPlatforms
402: .toArray(false);
403:
404: for (int i = viewPlatforms.arraySize() - 1; i >= 0; i--) {
405: vpLists[i].schedSphere.getWithLock(tempSphere);
406: if (tempSphere.intersect(region)) {
407: return true;
408: }
409: }
410: return false;
411: }
412:
413: void loadSound(SoundRetained sound, boolean forceLoad) {
414: // QUESTION: should not be calling into soundScheduler directly???
415: MediaContainer mediaContainer = sound.getSoundData();
416: ViewPlatformRetained vpLists[] = (ViewPlatformRetained[]) viewPlatforms
417: .toArray(false);
418:
419: for (int i = viewPlatforms.arraySize() - 1; i >= 0; i--) {
420: View[] views = vpLists[i].getViewList();
421: for (int j = (views.length - 1); j >= 0; j--) {
422: View v = (View) (views[j]);
423: // XXXX: Shouldn't this be done with messages??
424: v.soundScheduler.loadSound(sound, forceLoad);
425: }
426: }
427: }
428:
429: void enableSound(SoundRetained sound) {
430: ViewPlatformRetained vpLists[] = (ViewPlatformRetained[]) viewPlatforms
431: .toArray(false);
432: for (int i = viewPlatforms.arraySize() - 1; i >= 0; i--) {
433: View[] views = vpLists[i].getViewList();
434: for (int j = (views.length - 1); j >= 0; j--) {
435: View v = (View) (views[j]);
436: v.soundScheduler.enableSound(sound);
437: }
438: }
439: }
440:
441: void muteSound(SoundRetained sound) {
442: ViewPlatformRetained vpLists[] = (ViewPlatformRetained[]) viewPlatforms
443: .toArray(false);
444: for (int i = viewPlatforms.arraySize() - 1; i >= 0; i--) {
445: View[] views = vpLists[i].getViewList();
446: for (int j = (views.length - 1); j >= 0; j--) {
447: View v = (View) (views[j]);
448: v.soundScheduler.muteSound(sound);
449: }
450: }
451: }
452:
453: void pauseSound(SoundRetained sound) {
454: ViewPlatformRetained vpLists[] = (ViewPlatformRetained[]) viewPlatforms
455: .toArray(false);
456: for (int i = viewPlatforms.arraySize() - 1; i >= 0; i--) {
457: View[] views = vpLists[i].getViewList();
458: for (int j = (views.length - 1); j >= 0; j--) {
459: View v = (View) (views[j]);
460: v.soundScheduler.pauseSound(sound);
461: }
462: }
463: }
464:
465: // Implementation be needed.
466: void processSwitchChanged(J3dMessage m) {
467: /*
468: SoundRetained sound;
469: LeafRetained leaf;
470: UnorderList arrList;
471: int size;
472: Object[] nodes;
473:
474: UpdateTargets targets = (UpdateTargets)m.args[0];
475: arrList = targets.targetList[Targets.SND_TARGETS];
476:
477: if (arrList != null) {
478: size = arrList.size();
479: nodes = arrList.toArray(false);
480:
481: for (int i=size-1; i>=0; i--) {
482: leaf = (LeafRetained)nodes[i];
483: sound = (SoundRetained) leaf;
484: if (sound.switchState.currentSwitchOn) {
485: // System.err.println("SoundStructure.switch on");
486: // add To Schedule List
487: } else {
488: // System.err.println("SoundStructure.switch off");
489: // remove From Schedule List
490: }
491: }
492: }
493: */
494: }
495:
496: // How can active flag (based on View orientataion) be set here for all Views?!?
497:
498: UnorderList getSoundList(View view) {
499: ArrayList l = (ArrayList) viewScopedSounds.get(view);
500: // No sounds scoped to this view
501: if (l == null)
502: return nonViewScopedSounds;
503: UnorderList newS = (UnorderList) nonViewScopedSounds.clone();
504: int size = l.size();
505: for (int i = 0; i < size; i++) {
506: newS.add(l.get(i));
507: }
508: return newS;
509:
510: }
511:
512: UnorderList getSoundscapeList(View view) {
513: ArrayList l = (ArrayList) viewScopedSoundscapes.get(view);
514: // No sounds scoped to this view
515: if (l == null)
516: return nonViewScopedSoundscapes;
517: UnorderList newS = (UnorderList) nonViewScopedSoundscapes
518: .clone();
519: int size = l.size();
520: for (int i = 0; i < size; i++) {
521: newS.add(l.get(i));
522: }
523: return newS;
524:
525: }
526:
527: /*
528: // XXXX: how is immediate mode handled? below code taken from SoundSchedule
529: // Don't know how we'll process immediate mode sounds;
530: // Append immediate mode sounds to live sounds list
531: if (graphicsCtx != null) {
532: synchronized (graphicsCtx.sounds) {
533: nImmedSounds = graphicsCtx.numSounds();
534: numSoundsToProcess = nSounds + nImmedSounds;
535: if (sounds.length < numSoundsToProcess) {
536: // increase the array length of sounds array list
537: // by added 32 elements more than universe list size
538: sounds = new SoundRetained[numSoundsToProcess + 32];
539: }
540: for (int i=0; i<nImmedSounds; i++) {
541: sound = (SoundRetained)((graphicsCtx.getSound(i)).retained); if (debugFlag) {
542: debugPrint("#=#=#= sound at " + sound);
543: printSoundState(sound);
544: }
545:
546: if (sound != null && sound.getInImmCtx()) {
547: // There is no 'mirror' copy of Immediate mode sounds made.
548: // Put a reference to sound node itself in .sgSound field.
549: // For most purposes (except transforms & transformed fields)
550: // Scheduler code will treat live scenegraph sounds and
551: // immediate mode sound the same way.
552: sound.sgSound = sound;
553: sounds[nSounds] = sound;
554: if (debugFlag) {
555: debugPrint("#=#=#= sounds["+nSounds+"] at " +
556: sounds[nSounds]);
557: printSoundState(sounds[nSounds]);
558: }
559: nSounds++;
560: }
561: }
562: } // sync of GraphicsContext3D.sounds list
563: }
564: else { // graphics context not set yet, try setting it now
565: Canvas3D canvas = view.getFirstCanvas();
566: if (canvas != null)
567: graphicsCtx = canvas.getGraphicsContext3D();
568: }
569:
570: if (debugFlag) {
571: debugPrint("SoundStructure: number of sounds in scene graph = "+nRetainedSounds);
572: debugPrint("SoundStructure: number of immediate mode sounds = "+nImmedSounds);
573: }
574: */
575:
576: void updateTransformChange(UpdateTargets targets, long referenceTime) {
577: // QUESTION: how often and when should xformChangeList be processed
578: // node.updateTransformChange() called immediately rather than
579: // waiting for updateObject to be called and process xformChangeList
580: // which apprears to only happen when sound started...
581:
582: UnorderList arrList = targets.targetList[Targets.SND_TARGETS];
583: if (arrList != null) {
584: int j, i;
585: Object nodes[], nodesArr[];
586: int size = arrList.size();
587: nodesArr = arrList.toArray(false);
588:
589: for (j = 0; j < size; j++) {
590: nodes = (Object[]) nodesArr[j];
591:
592: for (i = 0; i < nodes.length; i++) {
593:
594: if (nodes[i] instanceof ConeSoundRetained) {
595: xformChangeList.add(nodes[i]);
596: ConeSoundRetained cnSndNode = (ConeSoundRetained) nodes[i];
597: cnSndNode.updateTransformChange();
598:
599: } else if (nodes[i] instanceof PointSoundRetained) {
600: xformChangeList.add(nodes[i]);
601: PointSoundRetained ptSndNode = (PointSoundRetained) nodes[i];
602: ptSndNode.updateTransformChange();
603:
604: } else if (nodes[i] instanceof SoundRetained) {
605: xformChangeList.add(nodes[i]);
606: SoundRetained sndNode = (SoundRetained) nodes[i];
607: sndNode.updateTransformChange();
608:
609: } else if (nodes[i] instanceof SoundscapeRetained) {
610: xformChangeList.add(nodes[i]);
611: SoundscapeRetained sndScapeNode = (SoundscapeRetained) nodes[i];
612: sndScapeNode.updateTransformChange();
613:
614: } else if (nodes[i] instanceof AuralAttributesRetained) {
615: xformChangeList.add(nodes[i]);
616: }
617: }
618: }
619: }
620: }
621:
622: // Debug print mechanism for Sound nodes
623: static final boolean debugFlag = false;
624: static final boolean internalErrors = false;
625:
626: void debugPrint(String message) {
627: if (debugFlag) {
628: System.err.println(message);
629: }
630: }
631:
632: boolean isSoundScopedToView(Object obj, View view) {
633: SoundRetained s = (SoundRetained) obj;
634: if (s.isViewScoped) {
635: ArrayList l = (ArrayList) viewScopedSounds.get(view);
636: if (!l.contains(s))
637: return false;
638: }
639: return true;
640: }
641:
642: boolean isSoundscapeScopedToView(Object obj, View view) {
643: SoundscapeRetained s = (SoundscapeRetained) obj;
644: if (s.isViewScoped) {
645: ArrayList l = (ArrayList) viewScopedSoundscapes.get(view);
646: if (!l.contains(s))
647: return false;
648: }
649: return true;
650: }
651:
652: void updateViewSpecificGroupChanged(J3dMessage m) {
653: int component = ((Integer) m.args[0]).intValue();
654: Object[] objAry = (Object[]) m.args[1];
655:
656: ArrayList soundList = null;
657: ArrayList soundsScapeList = null;
658:
659: if (((component & ViewSpecificGroupRetained.ADD_VIEW) != 0)
660: || ((component & ViewSpecificGroupRetained.SET_VIEW) != 0)) {
661: int i;
662: Object obj;
663: View view = (View) objAry[0];
664: ArrayList leafList = (ArrayList) objAry[2];
665: int size = leafList.size();
666: // Leaves is non-null only for the top VSG
667: if (size > 0) {
668: // Now process the list of affected leaved
669: for (i = 0; i < size; i++) {
670: obj = leafList.get(i);
671: if (obj instanceof SoundRetained) {
672: if (soundList == null) {
673: if ((soundList = (ArrayList) viewScopedSounds
674: .get(view)) == null) {
675: soundList = new ArrayList();
676: viewScopedSounds.put(view, soundList);
677: }
678: }
679: soundList.add(obj);
680: } else if (obj instanceof SoundscapeRetained) {
681: if (soundsScapeList == null) {
682: if ((soundsScapeList = (ArrayList) viewScopedSoundscapes
683: .get(view)) == null) {
684: soundsScapeList = new ArrayList();
685: viewScopedSoundscapes.put(view,
686: soundsScapeList);
687: }
688: }
689: soundsScapeList.add(obj);
690: }
691: }
692: }
693: }
694: if (((component & ViewSpecificGroupRetained.REMOVE_VIEW) != 0)
695: || ((component & ViewSpecificGroupRetained.SET_VIEW) != 0)) {
696: int i;
697: Object obj;
698: ArrayList leafList;
699: View view;
700:
701: if ((component & ViewSpecificGroupRetained.REMOVE_VIEW) != 0) {
702: view = (View) objAry[0];
703: leafList = (ArrayList) objAry[2];
704: } else {
705: view = (View) objAry[4];
706: leafList = (ArrayList) objAry[6];
707: }
708: int size = leafList.size();
709: // Leaves is non-null only for the top VSG
710: if (size > 0) {
711: // Now process the list of affected leaved
712: for (i = 0; i < size; i++) {
713: obj = leafList.get(i);
714: if (obj instanceof SoundRetained) {
715: if (soundList == null) {
716: soundList = (ArrayList) viewScopedSounds
717: .get(view);
718: }
719: soundList.remove(obj);
720: }
721: if (obj instanceof SoundscapeRetained) {
722: if (soundsScapeList == null) {
723: soundsScapeList = (ArrayList) viewScopedSoundscapes
724: .get(view);
725: }
726: soundsScapeList.remove(obj);
727: }
728: }
729: // If there are no more lights scoped to the view,
730: // remove the mapping
731: if (soundList != null && soundList.size() == 0)
732: viewScopedSounds.remove(view);
733: if (soundsScapeList != null
734: && soundsScapeList.size() == 0)
735: viewScopedSoundscapes.remove(view);
736: }
737:
738: }
739:
740: }
741:
742: void cleanup() {
743: }
744:
745: }
|