Source Code Cross Referenced for SoundRetained.java in  » 6.0-JDK-Modules » java-3d » javax » media » j3d » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » java 3d » javax.media.j3d 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: SoundRetained.java,v $
0003:         *
0004:         * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0006:         *
0007:         * This code is free software; you can redistribute it and/or modify it
0008:         * under the terms of the GNU General Public License version 2 only, as
0009:         * published by the Free Software Foundation.  Sun designates this
0010:         * particular file as subject to the "Classpath" exception as provided
0011:         * by Sun in the LICENSE file that accompanied this code.
0012:         *
0013:         * This code is distributed in the hope that it will be useful, but WITHOUT
0014:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0016:         * version 2 for more details (a copy is included in the LICENSE file that
0017:         * accompanied this code).
0018:         *
0019:         * You should have received a copy of the GNU General Public License version
0020:         * 2 along with this work; if not, write to the Free Software Foundation,
0021:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0022:         *
0023:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0024:         * CA 95054 USA or visit www.sun.com if you need additional information or
0025:         * have any questions.
0026:         *
0027:         * $Revision: 1.8 $
0028:         * $Date: 2008/02/28 20:17:30 $
0029:         * $State: Exp $
0030:         */
0031:
0032:        package javax.media.j3d;
0033:
0034:        import java.util.Vector;
0035:        import java.util.ArrayList;
0036:
0037:        /**
0038:         * SoundRetained is an abstract class that contains instance varables common
0039:         * to all retained sounds.
0040:         */
0041:
0042:        abstract class SoundRetained extends LeafRetained {
0043:
0044:            /**
0045:             * Null Sound identifier denotes sound is not created or initialized
0046:             */
0047:            static final int NULL_SOUND = -1;
0048:
0049:            /**
0050:             *  sound data associated with sound source
0051:             */
0052:            MediaContainer soundData = null;
0053:
0054:            /**
0055:             *  Overall Scale Factor applied to sound.
0056:             */
0057:            float initialGain = 1.0f; // Valid values are >= 0.0.
0058:
0059:            /**
0060:             *  Number of times sound is looped/repeated during play
0061:             */
0062:            int loopCount = 0; //  Range from 0 to POSITIVE_INFINITY(-1)
0063:
0064:            /**
0065:             *  Switch for turning sound on or off while the sound is "active"
0066:             */
0067:            boolean enable = false;
0068:
0069:            /**
0070:             * Type of release when sound is disabled.
0071:             *     If true, sound plays thru to end of sample before disabled
0072:             *     Otherwise, sound is disabled immediately.
0073:             */
0074:            boolean release = false;
0075:
0076:            /**
0077:             * Flag denoting if sound silently continues playing when it's deactivated.
0078:             */
0079:            boolean continuous = false;
0080:
0081:            /**
0082:             * Flag denoting if sound is explicitly muted, so that if begins playing
0083:             * it will be played silently.
0084:             */
0085:            boolean mute = false;
0086:
0087:            /**
0088:             * Flag denoting if sound is paused from playing - waiting to be resumed
0089:             */
0090:            boolean pause = false;
0091:
0092:            /**
0093:             * Sound priority ranking value.
0094:             * Valid values are 0.0 to 1.0
0095:             */
0096:            float priority = 1.0f;
0097:
0098:            /**
0099:             * Rate Scale Factor applied to sounds playback sample rate in Hertz.
0100:             * Valid values are 0.0 to 1.0
0101:             */
0102:            float rate = 1.0f;
0103:
0104:            /**
0105:             * The Boundary object defining the sound's scheduling region.
0106:             */
0107:            Bounds schedulingRegion = null;
0108:
0109:            /** 
0110:             * The bounding leaf reference
0111:             */
0112:            BoundingLeafRetained boundingLeaf = null;
0113:
0114:            /**
0115:             * The transformed bounds from either schedulingRegion or boundingLeaf
0116:             */
0117:            Bounds transformedRegion = null;
0118:
0119:            // Dirty bit flags used to pass change as part of message, and are
0120:            // acclummuated/stored in SoundSchedulerAtoms.
0121:            // These flags are grouped into two catagories:
0122:            // attribsDirty for sound node fields
0123:            // stateDirty for changes to sound state not reflected by sound fields.
0124:
0125:            // Attributes Dirty bit flags
0126:            // This bitmask is set when sound node attribute is changed by the user.
0127:            static final int SOUND_DATA_DIRTY_BIT = 0x0001;
0128:            static final int INITIAL_GAIN_DIRTY_BIT = 0x0002;
0129:            static final int LOOP_COUNT_DIRTY_BIT = 0x0004;
0130:            static final int BOUNDS_DIRTY_BIT = 0x0008;
0131:            static final int BOUNDING_LEAF_DIRTY_BIT = 0x0010;
0132:            static final int PRIORITY_DIRTY_BIT = 0x0020;
0133:            static final int POSITION_DIRTY_BIT = 0x0040;
0134:            static final int DISTANCE_GAIN_DIRTY_BIT = 0x0080;
0135:            static final int BACK_DISTANCE_GAIN_DIRTY_BIT = 0x0100;
0136:            static final int DIRECTION_DIRTY_BIT = 0x0200;
0137:            static final int ANGULAR_ATTENUATION_DIRTY_BIT = 0x0400;
0138:            static final int RATE_DIRTY_BIT = 0x0800;
0139:
0140:            static final int BOUNDS_CHANGED = BOUNDS_DIRTY_BIT
0141:                    | BOUNDING_LEAF_DIRTY_BIT;
0142:
0143:            static final int ATTRIBUTE_DIRTY_BITS = SOUND_DATA_DIRTY_BIT
0144:                    | INITIAL_GAIN_DIRTY_BIT | LOOP_COUNT_DIRTY_BIT
0145:                    | PRIORITY_DIRTY_BIT | RATE_DIRTY_BIT;
0146:
0147:            static final int POSITIONAL_DIRTY_BITS = ATTRIBUTE_DIRTY_BITS
0148:                    | POSITION_DIRTY_BIT | DISTANCE_GAIN_DIRTY_BIT;
0149:
0150:            static final int DIRECTIONAL_DIRTY_BITS = POSITIONAL_DIRTY_BITS
0151:                    | BACK_DISTANCE_GAIN_DIRTY_BIT | DIRECTION_DIRTY_BIT
0152:                    | ANGULAR_ATTENUATION_DIRTY_BIT;
0153:
0154:            // All attribute bits that are specifically set or cleared for any node */
0155:            static final int ALL_ATTIBS_DIRTY_BITS = 0x0FFF;
0156:
0157:            // State Dirty bit flags
0158:            // This bitmask is set when scene graph state is changed.
0159:            static final int LIVE_DIRTY_BIT = 0x0001;
0160:            static final int IMMEDIATE_MODE_DIRTY_BIT = 0x0002;
0161:            static final int LOAD_SOUND_DIRTY_BIT = 0x0004;
0162:            static final int RELEASE_DIRTY_BIT = 0x0008;
0163:            static final int CONTINUOUS_DIRTY_BIT = 0x0010;
0164:            static final int ENABLE_DIRTY_BIT = 0x0020;
0165:            static final int MUTE_DIRTY_BIT = 0x0040;
0166:            static final int PAUSE_DIRTY_BIT = 0x0080;
0167:            static final int XFORM_DIRTY_BIT = 0x8000;
0168:
0169:            // All attribute bits that are specifically set or cleared for any node */
0170:            static final int ALL_STATE_DIRTY_BITS = 0x80FF;
0171:
0172:            // The type of sound node: Background, Point, Cone
0173:            int soundType = NULL_SOUND;
0174:
0175:            // A back reference to the scene graph sound, when this is a mirror sound
0176:            SoundRetained sgSound = null;
0177:
0178:            // A HashKey for sounds in a shared group
0179:            HashKey key = null;
0180:
0181:            // An array of mirror sounds, one for each instance of this sound in a
0182:            // shared group.  Entry 0 is the only one valid if we are not in a shared
0183:            // group.
0184:            SoundRetained[] mirrorSounds = new SoundRetained[1];
0185:
0186:            // The number of valid sounds in mirrorSounds
0187:            int numMirrorSounds = 0;
0188:
0189:            /**
0190:             * Array of references to sound scheduler atoms associated with this node.
0191:             * For each view that a sound node is associated with a sound scheduler
0192:             * atom is created and maintained 
0193:             */
0194:            // for a particular view that are playing either audibly or silently.
0195:            private SoundSchedulerAtom[] loadedAtoms = new SoundSchedulerAtom[1];
0196:            private int atomCount = 0;
0197:
0198:            /**
0199:             * This is true when this sound is referenced in an immediate mode context
0200:             */
0201:            boolean inImmCtx = false;
0202:
0203:            /**
0204:             * Load Sound Data Status
0205:             */
0206:            static final int LOAD_COMPLETE = 2;
0207:            // load requested but could not be performed due because sound not live
0208:            static final int LOAD_PENDING = 1;
0209:            static final int LOAD_NULL = 0;
0210:            static final int LOAD_FAILED = -1;
0211:            int loadStatus = LOAD_NULL;
0212:            long duration = Sound.DURATION_UNKNOWN;
0213:
0214:            // Static initializer for SoundRetained class
0215:            static {
0216:                VirtualUniverse.loadLibraries();
0217:            }
0218:
0219:            // Target threads to be notified when sound changes
0220:            static final int targetThreads = J3dThread.UPDATE_SOUND
0221:                    | J3dThread.SOUND_SCHEDULER;
0222:
0223:            // Is true, if the mirror light is viewScoped
0224:            boolean isViewScoped = false;
0225:
0226:            /**
0227:             * Dispatch a message about a sound attribute change
0228:             */
0229:            void dispatchAttribChange(int dirtyBit, Object argument) {
0230:                // Send message including a integer argument
0231:                J3dMessage createMessage = new J3dMessage();
0232:                createMessage.threads = J3dThread.UPDATE_SOUND
0233:                        | J3dThread.SOUND_SCHEDULER;
0234:                createMessage.type = J3dMessage.SOUND_ATTRIB_CHANGED;
0235:                createMessage.universe = universe;
0236:                createMessage.args[0] = this ;
0237:                createMessage.args[1] = new Integer(dirtyBit);
0238:                if (inSharedGroup)
0239:                    createMessage.args[2] = new Integer(numMirrorSounds);
0240:                else
0241:                    createMessage.args[2] = new Integer(1);
0242:                createMessage.args[3] = mirrorSounds.clone();
0243:                createMessage.args[4] = argument;
0244:                if (debugFlag)
0245:                    debugPrint("dispatchAttribChange with " + dirtyBit);
0246:                VirtualUniverse.mc.processMessage(createMessage);
0247:            }
0248:
0249:            /**
0250:             * Dispatch a message about a sound state change
0251:             */
0252:            void dispatchStateChange(int dirtyBit, Object argument) {
0253:                // Send message including a integer argument
0254:                J3dMessage createMessage = new J3dMessage();
0255:                createMessage.threads = J3dThread.UPDATE_SOUND
0256:                        | J3dThread.SOUND_SCHEDULER;
0257:                createMessage.type = J3dMessage.SOUND_STATE_CHANGED;
0258:                createMessage.universe = universe;
0259:                createMessage.args[0] = this ;
0260:                createMessage.args[1] = new Integer(dirtyBit);
0261:                if (inSharedGroup)
0262:                    createMessage.args[2] = new Integer(numMirrorSounds);
0263:                else
0264:                    createMessage.args[2] = new Integer(1);
0265:                createMessage.args[3] = mirrorSounds.clone();
0266:                createMessage.args[4] = argument;
0267:                if (debugFlag)
0268:                    debugPrint("dispatchStateChange with " + dirtyBit);
0269:                VirtualUniverse.mc.processMessage(createMessage);
0270:            }
0271:
0272:            /**
0273:             * Assign value into sound data field
0274:             * @param soundData description of sound source data
0275:             */
0276:            void setSoundDataState(MediaContainer soundData) {
0277:                this .soundData = soundData;
0278:            }
0279:
0280:            /**
0281:             * Associates sound data with this sound source node
0282:             * Attempt to load sound 
0283:             * @param soundData descrition of sound source data
0284:             */
0285:            void setSoundData(MediaContainer soundData) {
0286:                // if resetting soundData to the same value don't bother doing anything
0287:                if (this .soundData == soundData) {
0288:                    return;
0289:                }
0290:
0291:                if (this .soundData != null) {
0292:                    // this sound node had older sound data; clear it out
0293:                    ((MediaContainerRetained) this .soundData.retained)
0294:                            .removeUser(this );
0295:                }
0296:
0297:                if (source != null && source.isLive()) {
0298:                    if (this .soundData != null) {
0299:                        ((MediaContainerRetained) this .soundData.retained)
0300:                                .clearLive(refCount);
0301:                    }
0302:
0303:                    if (soundData != null) {
0304:                        ((MediaContainerRetained) soundData.retained).setLive(
0305:                                inBackgroundGroup, refCount);
0306:                        ((MediaContainerRetained) soundData.retained)
0307:                                .addUser(this );
0308:                    }
0309:                }
0310:
0311:                this .soundData = soundData;
0312:                dispatchAttribChange(SOUND_DATA_DIRTY_BIT, soundData);
0313:
0314:                if (source != null && source.isLive()) {
0315:                    notifySceneGraphChanged(false);
0316:                }
0317:            }
0318:
0319:            /**
0320:             * Retrieves sound data associated with this sound source node
0321:             * @return sound source data container
0322:             */
0323:            MediaContainer getSoundData() {
0324:                return (this .soundData);
0325:            }
0326:
0327:            /**
0328:             * Set the gain scale factor applied to this sound
0329:             * @param amplitude gain scale factor
0330:             */
0331:            void setInitialGain(float scaleFactor) {
0332:                if (scaleFactor < 0.0f)
0333:                    this .initialGain = 0.0f;
0334:                else
0335:                    this .initialGain = scaleFactor;
0336:
0337:                dispatchAttribChange(INITIAL_GAIN_DIRTY_BIT, (new Float(
0338:                        scaleFactor)));
0339:                if (source != null && source.isLive()) {
0340:                    notifySceneGraphChanged(false);
0341:                }
0342:            }
0343:
0344:            /**
0345:             * Get the overall gain (applied to the sound data associated with source).
0346:             * @return overall gain of sound source
0347:             */
0348:            float getInitialGain() {
0349:                return (float) this .initialGain;
0350:            }
0351:
0352:            /**
0353:             * Sets the sound's loop count
0354:             * @param loopCount number of times sound is looped during play
0355:             */
0356:            void setLoop(int loopCount) {
0357:                if (loopCount < -1)
0358:                    this .loopCount = -1;
0359:                else
0360:                    this .loopCount = (int) loopCount;
0361:                if (debugFlag)
0362:                    debugPrint("setLoopCount called with " + this .loopCount);
0363:
0364:                dispatchAttribChange(LOOP_COUNT_DIRTY_BIT, (new Integer(
0365:                        loopCount)));
0366:                if (source != null && source.isLive()) {
0367:                    notifySceneGraphChanged(false);
0368:                }
0369:            }
0370:
0371:            /**
0372:             * Retrieves the loop count
0373:             * @return loop count for data associated with sound
0374:             */
0375:            int getLoop() {
0376:                return (int) this .loopCount;
0377:            }
0378:
0379:            /**
0380:             * Enable or disable the release flag for this sound source
0381:             * @param state flag denoting release sound before stopping
0382:             */
0383:            void setReleaseEnable(boolean state) {
0384:                this .release = state;
0385:                dispatchAttribChange(RELEASE_DIRTY_BIT, (state ? Boolean.TRUE
0386:                        : Boolean.FALSE));
0387:                if (source != null && source.isLive()) {
0388:                    notifySceneGraphChanged(false);
0389:                }
0390:            }
0391:
0392:            /**
0393:             * Retrieves release flag for sound associated with this source node
0394:             * @return sound's release flag
0395:             */
0396:            boolean getReleaseEnable() {
0397:                return (boolean) this .release;
0398:            }
0399:
0400:            /**
0401:             * Enable or disable continuous play flag
0402:             * @param state denotes if sound continues playing silently when deactivated
0403:             */
0404:            void setContinuousEnable(boolean state) {
0405:                this .continuous = state;
0406:                dispatchAttribChange(CONTINUOUS_DIRTY_BIT,
0407:                        (state ? Boolean.TRUE : Boolean.FALSE));
0408:                if (source != null && source.isLive()) {
0409:                    notifySceneGraphChanged(false);
0410:                }
0411:            }
0412:
0413:            /**
0414:             * Retrieves sound's continuous play flag
0415:             * @return flag denoting if deactivated sound silently continues playing
0416:             */
0417:            boolean getContinuousEnable() {
0418:                return (boolean) this .continuous;
0419:            }
0420:
0421:            /**
0422:             * Sets the flag denotine sound enabled/disabled and sends a message
0423:             * for the following to be done:
0424:             *   If state is true:
0425:             *     if sound is not playing, sound is started.
0426:             *     if sound is playing, sound is stopped, then re-started.
0427:             *   If state is false:
0428:             *     if sound is playing, sound is stopped
0429:             * @param state true or false to enable or disable the sound
0430:             */
0431:            void setEnable(boolean state) {
0432:                enable = state;
0433:                // QUESTION: Is this still valid code?
0434:                if (source != null && source.isLive()) {
0435:                    notifySceneGraphChanged(false);
0436:                }
0437:                dispatchStateChange(ENABLE_DIRTY_BIT, (new Boolean(enable)));
0438:            }
0439:
0440:            /**
0441:             * Retrieves sound's enabled flag
0442:             * @return sound enabled flag
0443:             */
0444:            boolean getEnable() {
0445:                return enable;
0446:            }
0447:
0448:            /**
0449:             * Set the Sound's scheduling region.
0450:             * @param region a region that contains the Sound's new scheduling region
0451:             */
0452:            void setSchedulingBounds(Bounds region) {
0453:                if (region != null) {
0454:                    schedulingRegion = (Bounds) region.clone();
0455:                    if (staticTransform != null) {
0456:                        schedulingRegion.transform(staticTransform.transform);
0457:                    }
0458:                    // QUESTION: Clone into transformedRegion IS required.  Why?
0459:                    transformedRegion = (Bounds) schedulingRegion.clone();
0460:                    if (debugFlag)
0461:                        debugPrint("setSchedulingBounds for a non-null region");
0462:                } else {
0463:                    schedulingRegion = null;
0464:                    // QUESTION: Is transformedRegion of node (not mirror node)
0465:                    //           even looked at???
0466:                    transformedRegion = null;
0467:                    if (debugFlag)
0468:                        debugPrint("setSchedulingBounds for a NULL region");
0469:                }
0470:                // XXXX: test that this works - could not new Bounds() since
0471:                //       Bounds is an abstract class and can't be instantiated
0472:                dispatchAttribChange(BOUNDS_DIRTY_BIT, region);
0473:                if (source != null && source.isLive()) {
0474:                    notifySceneGraphChanged(false);
0475:                }
0476:            }
0477:
0478:            /**
0479:             * Get the Sound's scheduling region.
0480:             * @return this Sound's scheduling region information
0481:             */
0482:            Bounds getSchedulingBounds() {
0483:                Bounds b = null;
0484:
0485:                if (this .schedulingRegion != null) {
0486:                    b = (Bounds) schedulingRegion.clone();
0487:                    if (staticTransform != null) {
0488:                        Transform3D invTransform = staticTransform
0489:                                .getInvTransform();
0490:                        b.transform(invTransform);
0491:                    }
0492:                }
0493:                return b;
0494:            }
0495:
0496:            /**
0497:             * Set the Sound's scheduling region to the specified Leaf node.
0498:             */
0499:            void setSchedulingBoundingLeaf(BoundingLeaf region) {
0500:                int i;
0501:                int numSnds = numMirrorSounds;
0502:                if (numMirrorSounds == 0)
0503:                    numSnds = 1;
0504:
0505:                if ((boundingLeaf != null)
0506:                        && (source != null && source.isLive())) {
0507:                    // Remove the mirror lights as users of the original bounding leaf
0508:                    for (i = 0; i < numSnds; i++) {
0509:                        boundingLeaf.mirrorBoundingLeaf
0510:                                .removeUser(mirrorSounds[i]);
0511:                    }
0512:                }
0513:
0514:                if (region != null) {
0515:                    boundingLeaf = (BoundingLeafRetained) region.retained;
0516:                    // Add all mirror sounds as user of this bounding leaf
0517:                    if (source != null && source.isLive()) {
0518:                        for (i = 0; i < numSnds; i++) {
0519:                            boundingLeaf.mirrorBoundingLeaf
0520:                                    .addUser(mirrorSounds[i]);
0521:                        }
0522:                    }
0523:                } else {
0524:                    boundingLeaf = null;
0525:                }
0526:                // XXXX: since BoundingLeaf constructor only takes Bounds 
0527:                //       test if region passed into dispatchAttribChange correctly.
0528:                dispatchAttribChange(BOUNDING_LEAF_DIRTY_BIT, region);
0529:                if (source != null && source.isLive()) {
0530:                    notifySceneGraphChanged(false);
0531:                }
0532:            }
0533:
0534:            /**
0535:             * Get the Sound's scheduling region
0536:             */
0537:            BoundingLeaf getSchedulingBoundingLeaf() {
0538:                if (boundingLeaf != null) {
0539:                    return ((BoundingLeaf) boundingLeaf.source);
0540:                } else {
0541:                    return null;
0542:                }
0543:            }
0544:
0545:            // The update Object function.
0546:            synchronized void updateMirrorObject(Object[] objs) {
0547:                Transform3D trans = null;
0548:                int component = ((Integer) objs[1]).intValue();
0549:                if (component == -1) { // update everything
0550:                    // object 2 contains the mirror object that needs to be
0551:                    // updated
0552:                    initMirrorObject(((SoundRetained) objs[2]));
0553:                }
0554:
0555:                // call the parent's mirror object update routine
0556:                super .updateMirrorObject(objs);
0557:
0558:            }
0559:
0560:            void updateBoundingLeaf(long refTime) {
0561:                // This is necessary, if for example, the region
0562:                // changes from sphere to box.
0563:                if (boundingLeaf != null
0564:                        && boundingLeaf.switchState.currentSwitchOn) {
0565:                    transformedRegion = boundingLeaf.transformedRegion;
0566:                } else { // evaluate schedulingRegion if not null
0567:                    if (schedulingRegion != null) {
0568:                        transformedRegion = schedulingRegion
0569:                                .copy(transformedRegion);
0570:                        transformedRegion.transform(schedulingRegion,
0571:                                getLastLocalToVworld());
0572:                    } else {
0573:                        transformedRegion = null;
0574:                    }
0575:                }
0576:            }
0577:
0578:            /**  
0579:             * Set sound's proirity value.
0580:             * @param priority value used to order sound's importance for playback.
0581:             */
0582:            void setPriority(float rank) {
0583:                if (rank == this .priority)
0584:                    // changing priority is expensive in the sound scheduler(s)
0585:                    // so only dispatch a message if 'new' priority value is really
0586:                    // different
0587:                    return;
0588:
0589:                this .priority = rank;
0590:                dispatchAttribChange(PRIORITY_DIRTY_BIT, (new Float(rank)));
0591:                if (source != null && source.isLive()) {
0592:                    notifySceneGraphChanged(false);
0593:                }
0594:            }
0595:
0596:            /**  
0597:             * Retrieves sound's priority value.
0598:             * @return sound priority value    
0599:             */
0600:            float getPriority() {
0601:                return (this .priority);
0602:            }
0603:
0604:            /**
0605:             * Retrieves sound's duration in milliseconds
0606:             * @return sound's duration, returns DURATION_UNKNOWN if duration could 
0607:             * not be queried from the audio device
0608:             */
0609:            long getDuration() {
0610:                return (duration);
0611:            }
0612:
0613:            /**  
0614:             * Set scale factor 
0615:             * @param scaleFactor applied to sound playback rate
0616:             */
0617:            void setRateScaleFactor(float scaleFactor) {
0618:                this .rate = scaleFactor;
0619:                dispatchAttribChange(RATE_DIRTY_BIT, (new Float(scaleFactor)));
0620:                if (source != null && source.isLive()) {
0621:                    notifySceneGraphChanged(false);
0622:                }
0623:            }
0624:
0625:            /**  
0626:             * Retrieves sound's rate scale factor
0627:             * @return sound rate scale factor
0628:             */
0629:            float getRateScaleFactor() {
0630:                return (this .rate);
0631:            }
0632:
0633:            void changeAtomList(SoundSchedulerAtom atom, int loadStatus) {
0634:                if (atom == null)
0635:                    return;
0636:                if (loadStatus == SoundRetained.LOAD_COMPLETE) {
0637:                    // atom is successfully loaded, so add this atom to array of atoms
0638:                    // associated with this sound, if not already in list
0639:                    for (int i = 0; i < atomCount; i++) {
0640:                        if (atom == loadedAtoms[i])
0641:                            return;
0642:                    }
0643:                    // add atom to list
0644:                    atomCount++;
0645:                    int currentArrayLength = loadedAtoms.length;
0646:                    if (atomCount > currentArrayLength) {
0647:                        // expand array - replace with a larger array
0648:                        loadedAtoms = new SoundSchedulerAtom[2 * currentArrayLength];
0649:                    }
0650:                    loadedAtoms[atomCount - 1] = atom; // store reference to new atom
0651:                    // all atoms sample durations SHOULD be the same so store it in node
0652:                    this .duration = atom.sampleLength; // XXXX: refine later? in ms
0653:                } else { // atom is NOT loaded or has been unloaded; remove from list
0654:                    if (atomCount == 0)
0655:                        return;
0656:
0657:                    // remove atom from array of playing atoms if it is in list
0658:                    boolean atomFound = false;
0659:                    int i;
0660:                    for (i = 0; i < atomCount; i++) {
0661:                        if (atom == loadedAtoms[i]) {
0662:                            atomFound = true;
0663:                            continue;
0664:                        }
0665:                    }
0666:                    if (!atomFound)
0667:                        return;
0668:
0669:                    // otherwise remove atom from list by close up list
0670:                    for (int j = i; j < atomCount; j++) {
0671:                        loadedAtoms[j] = loadedAtoms[j + 1];
0672:                    }
0673:                    atomCount--;
0674:                    if (atomCount == 0)
0675:                        this .duration = Sound.DURATION_UNKNOWN; // clear sound duration
0676:                }
0677:            }
0678:
0679:            /**
0680:             * Retrieves sound's ready state for ALL active views.
0681:             * For this node, the list of sound scheduler atoms associated with
0682:             * each view is maintained.   The 'loaded' (=is ready) state is
0683:             * true only if the following are true for all views/sound schedulers:
0684:             *
0685:             * <ul>
0686:             * 1) the Sound node has a non-null sound data and this data has 
0687:             *    sucessfully been loaded/opened/copied/attached;<br>
0688:             * 2) the Sound node is live;<br>
0689:             * 3) there is at least one active View in the Universe; and<br>
0690:             * 4) an instance of an AudioDevice is attached to the current 
0691:             *    PhysicalEnvironment.
0692:             * </ul>
0693:             *
0694:             * @return true if potentially playable (audibly or silently); false otherwise
0695:             */
0696:            boolean isReady() {
0697:                // all the atoms in the atom list must be are ready for this
0698:                // method to return true
0699:                // if any non-null atoms are found NOT ready, return false.
0700:                boolean atomFoundReady = true;
0701:                for (int i = 0; i < atomCount; i++) {
0702:                    SoundSchedulerAtom atom = loadedAtoms[i];
0703:                    if (atom == null || atom.soundScheduler == null)
0704:                        continue;
0705:                    else if (atom.loadStatus == SoundRetained.LOAD_COMPLETE) {
0706:                        atomFoundReady = true;
0707:                        continue;
0708:                    } else
0709:                        return false;
0710:                }
0711:                if (atomFoundReady) // at least on atom found ready
0712:                    return true;
0713:                else
0714:                    // not even one atom is associated with node so none are loaded
0715:                    return false;
0716:            }
0717:
0718:            /**
0719:             * Retrieves sound's ready state for a particular view.
0720:             * For this node, the list of sound scheduler atoms associated with
0721:             * each view is maintained.   The 'loaded' (=is ready) state is
0722:             * true only if the following are true for the given view:
0723:             *
0724:             * <ul>
0725:             * 1) the Sound node has a non-null sound data and this data has 
0726:             *    sucessfully been loaded/opened/copied/attached;<br>
0727:             * 2) the Sound node is live;<br>
0728:             * 3) the given View is active in the Universe; and<br>
0729:             * 4) an instance of an AudioDevice is attached to the current 
0730:             *    PhysicalEnvironment.
0731:             * </ul>
0732:             *
0733:             * @param viewRef view to test sound readiness for
0734:             * @return true if potentially playable (audibly or silently); false otherwise
0735:             */
0736:            boolean isReady(View viewRef) {
0737:                // if an atom in the atom list that is associated with the
0738:                // given view is found and has been loaded than return true,
0739:                // otherwise return false.
0740:                if (viewRef == null)
0741:                    return false;
0742:                for (int i = 0; i < atomCount; i++) {
0743:                    SoundSchedulerAtom atom = loadedAtoms[i];
0744:                    if (atom == null || atom.soundScheduler == null)
0745:                        continue;
0746:                    if (atom.soundScheduler.view == viewRef)
0747:                        if (atom.loadStatus != SoundRetained.LOAD_COMPLETE)
0748:                            return false;
0749:                        else
0750:                            return true;
0751:                    else
0752:                        // atom is not associated with given referenced view
0753:                        continue;
0754:                }
0755:                return false; // sound scheduler atom for given view not found
0756:
0757:            }
0758:
0759:            // *******************************
0760:            //  Play Status - isPlaying states
0761:            // *******************************
0762:
0763:            /**
0764:             * Retrieves sound's playing status
0765:             * true if potentially audible (enabled and active) on ANY audio device
0766:             * false otherwise
0767:             * @return sound playing flag
0768:             */
0769:            boolean isPlaying() {
0770:                for (int i = 0; i < atomCount; i++) {
0771:                    SoundSchedulerAtom atom = loadedAtoms[i];
0772:                    if (atom == null || atom.soundScheduler == null)
0773:                        continue;
0774:                    if (atom.status == SoundSchedulerAtom.SOUND_AUDIBLE)
0775:                        return true;
0776:                    else
0777:                        continue; // look for at lease one atom that is playing
0778:                }
0779:                // not even one atom is associated with this node so none are playing
0780:                return false;
0781:            }
0782:
0783:            /**
0784:             * Retrieves sound's playing status for a particular view
0785:             * true if potentially audible (enabled and active) on audio device
0786:             * associated with the given view
0787:             * false otherwise
0788:             * @param viewRef view to test sound playing state for
0789:             * @return sound playing flag
0790:             */
0791:            boolean isPlaying(View viewRef) {
0792:                if (viewRef == null)
0793:                    return false;
0794:                for (int i = 0; i < atomCount; i++) {
0795:                    SoundSchedulerAtom atom = loadedAtoms[i];
0796:                    if (atom == null || atom.soundScheduler == null)
0797:                        continue;
0798:                    if (atom.soundScheduler.view == viewRef) {
0799:                        if (atom.status == SoundSchedulerAtom.SOUND_AUDIBLE)
0800:                            return true;
0801:                        else
0802:                            return false;
0803:                    } else
0804:                        // atom is not associated with given referenced view
0805:                        continue;
0806:                }
0807:                return false; // atom associated with this view not found in list
0808:            }
0809:
0810:            /**
0811:             * Retrieves sound's playing silently status
0812:             * true if enabled but not active (on any device)
0813:             * false otherwise
0814:             * @return sound playing flag
0815:             */
0816:            boolean isPlayingSilently() {
0817:                for (int i = 0; i < atomCount; i++) {
0818:                    SoundSchedulerAtom atom = loadedAtoms[i];
0819:                    if (atom == null || atom.soundScheduler == null)
0820:                        continue;
0821:                    if (atom.status == SoundSchedulerAtom.SOUND_SILENT)
0822:                        return true;
0823:                    else
0824:                        return false;
0825:                }
0826:                return false; // atom not found in list or not playing audibilly 
0827:            }
0828:
0829:            /**
0830:             * Retrieves sound's playing silently status for a particular view
0831:             * true if potentially audible (enabled and active) on audio device
0832:             * associated with the given view
0833:             * false otherwise
0834:             * @param viewRef view to test sound playing silently state for
0835:             * @return sound playing flag
0836:             */
0837:            boolean isPlayingSilently(View viewRef) {
0838:                if (viewRef == null)
0839:                    return false;
0840:                for (int i = 0; i < atomCount; i++) {
0841:                    SoundSchedulerAtom atom = loadedAtoms[i];
0842:                    if (atom == null || atom.soundScheduler == null)
0843:                        continue;
0844:                    if (atom.soundScheduler.view == viewRef) {
0845:                        if (atom.status == SoundSchedulerAtom.SOUND_SILENT)
0846:                            return true;
0847:                        else
0848:                            return false;
0849:                    } else
0850:                        // atom is not associated with given referenced view
0851:                        continue;
0852:                }
0853:                return false; // atom associated with this view not found in list
0854:            }
0855:
0856:            /**
0857:             * Retrieves number of channels allocated for this sound on the primary
0858:             * view's audio device.
0859:             * @return number of channels used by sound across all devices
0860:             */
0861:            int getNumberOfChannelsUsed() {
0862:                // retrieves the number of channels used by the atom that is:
0863:                //     loaded, and
0864:                //     playing either audibily or silently 
0865:                // on the device associated with the primary view.
0866:                View primaryView = this .universe.getCurrentView();
0867:                if (primaryView == null)
0868:                    return 0;
0869:
0870:                // find atom associated with primary view (VirtualUniverse currentView)
0871:                // then return the number of channels associated with that atom
0872:                SoundSchedulerAtom atom;
0873:                for (int i = 0; i < atomCount; i++) {
0874:                    atom = loadedAtoms[i];
0875:                    if (atom == null || atom.soundScheduler == null)
0876:                        continue;
0877:                    if (atom.soundScheduler.view == primaryView) {
0878:                        return atom.numberChannels;
0879:                    }
0880:                }
0881:                return 0; // atom associated with primary view not found
0882:            }
0883:
0884:            /**
0885:             * Retrieves number of channels allocated for this sound on the audio
0886:             * devices associated with a given view.
0887:             * @param viewRef view to test sound playing silently state for
0888:             * @return number of channels used by this sound on a particular device
0889:             */
0890:            int getNumberOfChannelsUsed(View viewRef) {
0891:                // retrieves the number of channels used by the atom that is:
0892:                //     loaded, and
0893:                //     playing either audibily or silently 
0894:                // on the device associated with the given view.
0895:                if (viewRef == null)
0896:                    return 0;
0897:                SoundSchedulerAtom atom;
0898:                for (int i = 0; i < atomCount; i++) {
0899:                    atom = loadedAtoms[i];
0900:                    if (atom == null || atom.soundScheduler == null)
0901:                        continue;
0902:                    if (atom.soundScheduler.view == viewRef) {
0903:                        return atom.numberChannels;
0904:                    }
0905:                }
0906:                return 0; // atom associated with primary view not found
0907:            }
0908:
0909:            /**
0910:             * Set mute state flag.  If the sound is playing it will be set to
0911:             * play silently
0912:             * @param state flag
0913:             * @since Java 3D 1.3
0914:             */
0915:            void setMute(boolean state) {
0916:                this .mute = state;
0917:                dispatchAttribChange(MUTE_DIRTY_BIT, (state ? Boolean.TRUE
0918:                        : Boolean.FALSE));
0919:                if (source != null && source.isLive()) {
0920:                    notifySceneGraphChanged(false);
0921:                }
0922:            }
0923:
0924:            /**  
0925:             * Retrieves sound Mute state.
0926:             * A return value of true does not imply that the sound has  
0927:             * been started playing or is still playing silently. 
0928:             * @return mute state flag
0929:             * @since Java 3D 1.3
0930:             */
0931:            boolean getMute() {
0932:                return (boolean) this .mute;
0933:            }
0934:
0935:            /**
0936:             * Set pause state flag.  If the sound is playing it will be paused
0937:             * @param state flag
0938:             * @since Java 3D 1.3
0939:             */
0940:            void setPause(boolean state) {
0941:                this .pause = state;
0942:                dispatchAttribChange(PAUSE_DIRTY_BIT, (state ? Boolean.TRUE
0943:                        : Boolean.FALSE));
0944:                if (source != null && source.isLive()) {
0945:                    notifySceneGraphChanged(false);
0946:                }
0947:            }
0948:
0949:            /**  
0950:             * Retrieves sound Pause state.
0951:             * A return value of true does not imply that the sound has  
0952:             * been started playing auditibly or silently.
0953:             * @return mute state flag
0954:             * @since Java 3D 1.3
0955:             */
0956:            boolean getPause() {
0957:                return (boolean) this .pause;
0958:            }
0959:
0960:            /**
0961:             * This sets the immedate mode context flag
0962:             */
0963:            void setInImmCtx(boolean inCtx) {
0964:                inImmCtx = inCtx;
0965:            }
0966:
0967:            /**
0968:             * This gets the immedate mode context flag
0969:             */
0970:            boolean getInImmCtx() {
0971:                return (inImmCtx);
0972:            }
0973:
0974:            /**
0975:             * This gets the mirror sound for this sound given the key.
0976:             */
0977:            SoundRetained getMirrorSound(HashKey key) {
0978:                int i;
0979:                SoundRetained[] newSounds;
0980:
0981:                if (inSharedGroup) {
0982:                    for (i = 0; i < numMirrorSounds; i++) {
0983:                        if (mirrorSounds[i].key.equals(key)) {
0984:                            return (mirrorSounds[i]);
0985:                        }
0986:                    }
0987:                    if (numMirrorSounds == mirrorSounds.length) {
0988:                        newSounds = new SoundRetained[numMirrorSounds * 2];
0989:                        for (i = 0; i < numMirrorSounds; i++) {
0990:                            newSounds[i] = mirrorSounds[i];
0991:                        }
0992:                        mirrorSounds = newSounds;
0993:                    }
0994:                    //	    mirrorSounds[numMirrorSounds] = (SoundRetained) this.clone();
0995:                    mirrorSounds[numMirrorSounds] = (SoundRetained) this 
0996:                            .clone();
0997:                    //mirrorSounds[numMirrorSounds].key = new HashKey(key);
0998:                    mirrorSounds[numMirrorSounds].key = key;
0999:                    mirrorSounds[numMirrorSounds].sgSound = this ;
1000:                    return (mirrorSounds[numMirrorSounds++]);
1001:                } else {
1002:                    if (mirrorSounds[0] == null) {
1003:                        //  mirrorSounds[0] = (SoundRetained) this.clone(true);
1004:                        mirrorSounds[0] = (SoundRetained) this .clone();
1005:                        mirrorSounds[0].sgSound = this ;
1006:                    }
1007:                    return (mirrorSounds[0]);
1008:                }
1009:            }
1010:
1011:            synchronized void initMirrorObject(SoundRetained ms) {
1012:                GroupRetained group;
1013:                Transform3D trans;
1014:                Bounds region = null;
1015:
1016:                ms.setSchedulingBounds(getSchedulingBounds());
1017:                ms.setSchedulingBoundingLeaf(getSchedulingBoundingLeaf());
1018:                ms.sgSound = sgSound;
1019:                /*
1020:                 // QUESTION: these are not set in LightRetained???
1021:                 ms.key = null;
1022:                 ms.mirrorSounds = new SoundRetained[1];
1023:                 ms.numMirrorSounds = 0;
1024:                 */
1025:                ms.inImmCtx = inImmCtx;
1026:                ms.setSoundData(getSoundData());
1027:
1028:                // XXXX: copy ms.atoms array from this.atoms
1029:
1030:                ms.parent = parent;
1031:                ms.inSharedGroup = false;
1032:                ms.locale = locale;
1033:                ms.parent = parent;
1034:                ms.localBounds = (Bounds) localBounds.clone();
1035:
1036:                ms.transformedRegion = null;
1037:                if (boundingLeaf != null) {
1038:                    if (ms.boundingLeaf != null)
1039:                        ms.boundingLeaf.removeUser(ms);
1040:                    ms.boundingLeaf = boundingLeaf.mirrorBoundingLeaf;
1041:                    // Add this mirror object as user
1042:                    ms.boundingLeaf.addUser(ms);
1043:                    ms.transformedRegion = ms.boundingLeaf.transformedRegion;
1044:                } else {
1045:                    ms.boundingLeaf = null;
1046:                }
1047:
1048:                if (schedulingRegion != null) {
1049:                    ms.schedulingRegion = (Bounds) schedulingRegion.clone();
1050:                    // Assign region only if bounding leaf is null
1051:                    if (ms.transformedRegion == null) {
1052:                        ms.transformedRegion = (Bounds) ms.schedulingRegion
1053:                                .clone();
1054:                        ms.transformedRegion.transform(ms.schedulingRegion, ms
1055:                                .getLastLocalToVworld());
1056:                    }
1057:
1058:                } else {
1059:                    ms.schedulingRegion = null;
1060:                }
1061:            }
1062:
1063:            void setLive(SetLiveState s) {
1064:                SoundRetained ms;
1065:                int i, j;
1066:
1067:                if (debugFlag)
1068:                    debugPrint("Sound.setLive");
1069:
1070:                if (inImmCtx) {
1071:                    throw new IllegalSharingException(J3dI18N
1072:                            .getString("SoundRetained2"));
1073:                }
1074:                super .setLive(s);
1075:                if (inBackgroundGroup) {
1076:                    throw new IllegalSceneGraphException(J3dI18N
1077:                            .getString("SoundRetained3"));
1078:                }
1079:
1080:                if (this .loadStatus == LOAD_PENDING) {
1081:                    if (debugFlag)
1082:                        debugPrint("Sound.setLive load Sound");
1083:                    dispatchStateChange(LOAD_SOUND_DIRTY_BIT, soundData);
1084:                }
1085:
1086:                if (this .soundData != null) {
1087:                    ((MediaContainerRetained) this .soundData.retained).setLive(
1088:                            inBackgroundGroup, s.refCount);
1089:                }
1090:
1091:                if (s.inSharedGroup) {
1092:                    for (i = 0; i < s.keys.length; i++) {
1093:                        ms = this .getMirrorSound(s.keys[i]);
1094:                        ms.localToVworld = new Transform3D[1][];
1095:                        ms.localToVworldIndex = new int[1][];
1096:
1097:                        j = s.keys[i].equals(localToVworldKeys, 0,
1098:                                localToVworldKeys.length);
1099:                        if (j < 0) {
1100:                            System.err
1101:                                    .println("SoundRetained : Can't find hashKey");
1102:                        }
1103:
1104:                        ms.localToVworld[0] = localToVworld[j];
1105:                        ms.localToVworldIndex[0] = localToVworldIndex[j];
1106:                        // If its view Scoped, then add this list
1107:                        // to be sent to Sound Structure
1108:                        if ((s.viewScopedNodeList != null)
1109:                                && (s.viewLists != null)) {
1110:                            s.viewScopedNodeList.add(ms);
1111:                            s.scopedNodesViewList.add(s.viewLists.get(i));
1112:                        } else {
1113:                            s.nodeList.add(ms);
1114:                        }
1115:                        // Initialization of the mirror object during the INSERT_NODE
1116:                        // message (in updateMirrorObject)
1117:                        if (s.switchTargets != null
1118:                                && s.switchTargets[i] != null) {
1119:                            s.switchTargets[i].addNode(ms, Targets.SND_TARGETS);
1120:                        }
1121:                        ms.switchState = (SwitchState) s.switchStates.get(j);
1122:                        if (s.transformTargets != null
1123:                                && s.transformTargets[i] != null) {
1124:                            s.transformTargets[i].addNode(ms,
1125:                                    Targets.SND_TARGETS);
1126:                            s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
1127:                        }
1128:                    }
1129:                } else {
1130:                    ms = this .getMirrorSound(null);
1131:                    ms.localToVworld = new Transform3D[1][];
1132:                    ms.localToVworldIndex = new int[1][];
1133:                    ms.localToVworld[0] = this .localToVworld[0];
1134:                    ms.localToVworldIndex[0] = this .localToVworldIndex[0];
1135:                    // If its view Scoped, then add this list
1136:                    // to be sent to Sound Structure
1137:                    if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
1138:                        s.viewScopedNodeList.add(ms);
1139:                        s.scopedNodesViewList.add(s.viewLists.get(0));
1140:                    } else {
1141:                        s.nodeList.add(ms);
1142:                    }
1143:                    // Initialization of the mirror object during the INSERT_NODE
1144:                    // message (in updateMirrorObject)
1145:                    if (s.switchTargets != null && s.switchTargets[0] != null) {
1146:                        s.switchTargets[0].addNode(ms, Targets.SND_TARGETS);
1147:                    }
1148:                    ms.switchState = (SwitchState) s.switchStates.get(0);
1149:                    if (s.transformTargets != null
1150:                            && s.transformTargets[0] != null) {
1151:                        s.transformTargets[0].addNode(ms, Targets.SND_TARGETS);
1152:                        s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
1153:                    }
1154:                }
1155:                dispatchStateChange(LIVE_DIRTY_BIT, soundData);
1156:                s.notifyThreads |= targetThreads;
1157:            }
1158:
1159:            void clearLive(SetLiveState s) {
1160:                SoundRetained ms;
1161:
1162:                super .clearLive(s);
1163:
1164:                // XXXX: if (inSharedGroup)
1165:
1166:                if (s.inSharedGroup) {
1167:                    for (int i = 0; i < s.keys.length; i++) {
1168:                        ms = this .getMirrorSound(s.keys[i]);
1169:                        if (s.switchTargets != null
1170:                                && s.switchTargets[i] != null) {
1171:                            s.switchTargets[i].addNode(ms, Targets.SND_TARGETS);
1172:                        }
1173:                        if (s.transformTargets != null
1174:                                && s.transformTargets[i] != null) {
1175:                            s.transformTargets[i].addNode(ms,
1176:                                    Targets.SND_TARGETS);
1177:                            s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
1178:                        }
1179:                        // If its view Scoped, then add this list
1180:                        // to be sent to Sound Structure
1181:                        if ((s.viewScopedNodeList != null)
1182:                                && (s.viewLists != null)) {
1183:                            s.viewScopedNodeList.add(ms);
1184:                            s.scopedNodesViewList.add(s.viewLists.get(i));
1185:                        } else {
1186:                            s.nodeList.add(ms);
1187:                        }
1188:                    }
1189:                } else {
1190:                    ms = this .getMirrorSound(null);
1191:                    if (s.switchTargets != null && s.switchTargets[0] != null) {
1192:                        s.switchTargets[0].addNode(ms, Targets.SND_TARGETS);
1193:                    }
1194:                    if (s.transformTargets != null
1195:                            && s.transformTargets[0] != null) {
1196:                        s.transformTargets[0].addNode(ms, Targets.SND_TARGETS);
1197:                        s.notifyThreads |= J3dThread.UPDATE_TRANSFORM;
1198:                    }
1199:                    // If its view Scoped, then add this list
1200:                    // to be sent to Sound Structure
1201:                    if ((s.viewScopedNodeList != null) && (s.viewLists != null)) {
1202:                        s.viewScopedNodeList.add(ms);
1203:                        s.scopedNodesViewList.add(s.viewLists.get(0));
1204:                    } else {
1205:                        s.nodeList.add(ms);
1206:                    }
1207:                }
1208:                s.notifyThreads |= targetThreads;
1209:
1210:                if (this .soundData != null) {
1211:                    ((MediaContainerRetained) this .soundData.retained)
1212:                            .clearLive(s.refCount);
1213:                }
1214:            }
1215:
1216:            void mergeTransform(TransformGroupRetained xform) {
1217:                super .mergeTransform(xform);
1218:                if (schedulingRegion != null) {
1219:                    schedulingRegion.transform(xform.transform);
1220:                }
1221:            }
1222:
1223:            /*
1224:             // This makes passed in sound look just like this sound
1225:             // QUESTION: DOesn't appread to be called
1226:             // XXXX:      ...if so, remove...
1227:             synchronized void update(SoundRetained sound) {
1228:             if (debugFlag)
1229:             debugPrint("Sound.update ******** entered ***** this = " + this +
1230:             ", and sound param = " + sound);
1231:
1232:             sound.soundData = soundData;
1233:             sound.initialGain = initialGain;
1234:             sound.loopCount = loopCount;
1235:             sound.release = release;
1236:             sound.continuous = continuous;
1237:             sound.enable = enable;  // used to be 'on'
1238:             sound.inImmCtx = inImmCtx;
1239:
1240:             // QUESTION:
1241:             //     This line removed from 1.1.1 version; why ???
1242:             sound.currentSwitchOn = currentSwitchOn;
1243:
1244:             // NEW:
1245:             sound.priority = priority;
1246:
1247:             // QUESTION: With code below, no sound schedulingRegion found
1248:             //        sound.schedulingRegion = schedulingRegion;
1249:             //        sound.boundingLeaf = boundingLeaf;
1250:             // XXXX: clone of region used in Traverse code, why not here???
1251:             //        if (schedulingRegion != null)
1252:             //            sound.schedulingRegion = (Bounds)schedulingRegion.clone();
1253:             // XXXX:  BoundingLeafRetained boundingLeaf ...
1254:             //        WHAT ABOUT transformedRegion??
1255:
1256:             // XXXX: Update ALL fields
1257:             // ALL THE BELOW USED TO COMMENTED OUT vvvvvvvvvvvvvvvvvvvvvvvvvvvvv
1258:             sound.sampleLength = sampleLength;
1259:             sound.loopStartOffset = loopStartOffset;
1260:             sound.loopLength = loopLength;
1261:             sound.attackLength = attackLength;
1262:             sound.releaseLength = releaseLength;
1263:
1264:             sound.sgSound = sgSound;
1265:             sound.key = key;
1266:             sound.numMirrorSounds = numMirrorSounds;
1267:             for (int index=0; index<numMirrorSounds; index++) 
1268:             sound.mirrorSounds = mirrorSounds;
1269:             sound.universe = universe;
1270:             if (universe.sounds.contains(sound) == false) {
1271:             universe.sounds.addElement(sound);
1272:             }
1273:             if (debugFlag)
1274:             debugPrint("update****************************** exited");
1275:             ^^^^^^^^^^^ COMMENTED OUT
1276:             }
1277:             */
1278:
1279:            // Called on mirror object
1280:            // QUESTION: doesn't transformed region need to be saved???
1281:            void updateTransformChange() {
1282:                // If bounding leaf is null, tranform the bounds object
1283:                if (debugFlag)
1284:                    debugPrint("SoundRetained.updateTransformChange()");
1285:                if (boundingLeaf == null) {
1286:                    if (schedulingRegion != null) {
1287:                        transformedRegion = schedulingRegion
1288:                                .copy(transformedRegion);
1289:                        transformedRegion.transform(schedulingRegion,
1290:                                getLastLocalToVworld());
1291:                    }
1292:                }
1293:                dispatchStateChange(XFORM_DIRTY_BIT, null);
1294:            }
1295:
1296:            // QUESTION:
1297:            //     Clone method (from 1.1.1 version) removed!?!?!? yet LightRetained has it
1298:
1299:            // Debug print mechanism for Sound nodes
1300:            static final boolean debugFlag = false;
1301:            static final boolean internalErrors = false;
1302:
1303:            void debugPrint(String message) {
1304:                if (debugFlag) {
1305:                    System.err.println(message);
1306:                }
1307:            }
1308:
1309:            void getMirrorObjects(ArrayList leafList, HashKey key) {
1310:                if (key == null) {
1311:                    leafList.add(mirrorSounds[0]);
1312:                } else {
1313:                    for (int i = 0; i < numMirrorSounds; i++) {
1314:                        if (mirrorSounds[i].key.equals(key)) {
1315:                            leafList.add(mirrorSounds[i]);
1316:                            break;
1317:                        }
1318:                    }
1319:
1320:                }
1321:            }
1322:
1323:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.