001: /*
002: * $RCSfile: AudioClip.java,v $
003: *
004: * @(#)AudioClip.java 1.33 98/11/19 15:44:48
005: *
006: * Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
007: *
008: * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
009: * modify and redistribute this software in source and binary code form,
010: * provided that i) this copyright notice and license appear on all copies of
011: * the software; and ii) Licensee does not utilize the software in a manner
012: * which is disparaging to Sun.
013: *
014: * This software is provided "AS IS," without a warranty of any kind. ALL
015: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
016: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
017: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
018: * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
019: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
020: * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
021: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
022: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
023: * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
024: * POSSIBILITY OF SUCH DAMAGES.
025: *
026: * This software is not designed or intended for use in on-line control of
027: * aircraft, air traffic, aircraft navigation or aircraft communications; or in
028: * the design, construction, operation or maintenance of any nuclear
029: * facility. Licensee represents and warrants that it will not use or
030: * redistribute the Software for such purposes.
031: *
032: * $Revision: 1.2 $
033: * $Date: 2005/02/03 23:06:51 $
034: * $State: Exp $
035: */
036: /*
037: *
038: * @Author: Rick Goldberg
039: * @Author: Doug Gehringer
040: */
041: package org.jdesktop.j3d.loaders.vrml97.impl;
042:
043: import java.net.URL;
044: import javax.media.j3d.MediaContainer;
045:
046: /** Description of the Class */
047: public class AudioClip extends Node {
048:
049: // exposedField
050: SFString description;
051: SFBool loop;
052: SFFloat pitch;
053: SFTime startTime;
054: SFTime stopTime;
055: MFString url;
056:
057: // eventOut
058: SFTime duration;
059: SFBool isActive;
060:
061: // if the clip's active, startTime, stopTime, cycleInterval
062: // events are ignored. these will store the previous values since
063: // our event mechanism automatically updates the value.
064: // but, there are really no cycleInterval assume that means
065: // duration.
066: double activeCycleInterval;
067: double activeStartTime;
068: double activeStopTime;
069:
070: MediaContainer impl;
071: Sound sound = null;
072:
073: /**
074: *Constructor for the AudioClip object
075: *
076: *@param loader Description of the Parameter
077: */
078: public AudioClip(Loader loader) {
079: super (loader);
080: description = new SFString();
081: loop = new SFBool(false);
082: pitch = new SFFloat(1.0f);
083: startTime = new SFTime(0.0);
084: stopTime = new SFTime(0.0);
085: url = new MFString();
086: duration = new SFTime();
087: isActive = new SFBool(false);
088: loader.addAudioClip(this );
089: initFields();
090: }
091:
092: /**
093: *Constructor for the AudioClip object
094: *
095: *@param loader Description of the Parameter
096: *@param description Description of the Parameter
097: *@param loop Description of the Parameter
098: *@param pitch Description of the Parameter
099: *@param startTime Description of the Parameter
100: *@param stopTime Description of the Parameter
101: *@param url Description of the Parameter
102: */
103: AudioClip(Loader loader, SFString description, SFBool loop,
104: SFFloat pitch, SFTime startTime, SFTime stopTime,
105: MFString url) {
106: super (loader);
107: this .description = description;
108: this .loop = loop;
109: this .pitch = pitch;
110: this .startTime = startTime;
111: this .stopTime = stopTime;
112: this .url = url;
113: this .duration = new SFTime();
114: this .isActive = new SFBool(false);
115: loader.addAudioClip(this );
116: initFields();
117: }
118:
119: /** Description of the Method */
120: void initImpl() {
121: impl = new MediaContainer();
122: impl.setCapability(MediaContainer.ALLOW_URL_READ);
123: impl.setCapability(MediaContainer.ALLOW_URL_WRITE);
124: impl.setCapability(MediaContainer.ALLOW_CACHE_READ);
125: impl.setCapability(MediaContainer.ALLOW_CACHE_WRITE);
126: impl.setCacheEnable(true);
127: doChangeUrl();
128: implReady = true;
129: if (browser.debug) {
130: System.out.println("AudioClip:initImpl()");
131: }
132: }
133:
134: /**
135: * Sets the sound attribute of the AudioClip object
136: *
137: *@param owner The new sound value
138: */
139: void setSound(Sound owner) {
140: sound = owner;
141: }
142:
143: /**
144: * Description of the Method
145: *
146: *@return Description of the Return Value
147: */
148: public Object clone() {
149: return new AudioClip(loader, (SFString) description.clone(),
150: (SFBool) loop.clone(), (SFFloat) pitch.clone(),
151: (SFTime) startTime.clone(), (SFTime) stopTime.clone(),
152: (MFString) url.clone());
153: }
154:
155: /**
156: * Description of the Method
157: *
158: *@param eventInName Description of the Parameter
159: *@param time Description of the Parameter
160: */
161: public void notifyMethod(String eventInName, double time) {
162: if (eventInName.equals("url")) {
163: doChangeUrl();
164: }
165: if (eventInName.equals("startTime")) {
166: if (isActive.value == true) {
167: startTime.time = activeStartTime;
168: } else {
169: activeCycleInterval = duration.time;
170: activeStartTime = startTime.time;
171: activeStopTime = stopTime.time;
172: }
173: } else if (eventInName.equals("stopTime")) {
174: if (isActive.value == true) {
175: // ignore by resetting value back
176: // spec says "Any set_stopTime events where
177: // stopTime <= startTime, to an active time-dependent
178: // node are also ignored." the interperetation of
179: // that is the stopTime < active startTime
180: if (stopTime.time < activeStartTime) {
181: stopTime.time = activeStopTime;
182: }
183: // this should be done only in simTick?
184: if ((activeStartTime < stopTime.time)
185: && (stopTime.time <= time)) {
186: setSoundEnable(false);
187: }
188: }
189: } else if (eventInName.equals("duration")) {
190: // this could be a problem if JavaSoundMixer is late to report
191: // the real duration which we need to calculate lots of things.
192: if (isActive.value == true) {
193: duration.time = activeCycleInterval;
194: }
195: // because of the latency in getting duration,
196: // need to set this.
197: activeCycleInterval = duration.time;
198: } else if (eventInName.equals("isActive")) {
199: if (!isActive.value) {
200: activeStartTime = time;
201: activeStopTime = stopTime.time;
202: activeCycleInterval = duration.time;
203: }
204: }
205: if (!eventInName.startsWith("route_")) {
206: simTick(time);
207: }
208: }
209:
210: // this is only used by the browser to sync duration
211: // that comes from the mixer late.
212: /**
213: * Sets the duration attribute of the AudioClip object
214: *
215: *@param inDuration The new duration value
216: */
217: public void setDuration(double inDuration) {
218: duration.setValue(inDuration);
219: duration.time = inDuration;
220: }
221:
222: /**
223: * Description of the Method
224: *
225: *@param now Description of the Parameter
226: */
227: void simTick(double now) {
228: //if(browser.debug)System.out.println("now"+now+" start"+startTime.time+" stop"+stopTime.time+" isActive"+isActive.value+" duration"+duration.time+" loop"+ loop.value);
229:
230: if (loop.value) {
231: sound.setLoop(javax.media.j3d.Sound.INFINITE_LOOPS);
232: } else {
233: sound.setLoop(0);
234: }
235:
236: if ((now >= stopTime.time) && (stopTime.time > startTime.time)
237: && (!loop.value)) {
238: if (isActive.value) {
239: setSoundEnable(false);
240: }
241: } else if ((now >= (startTime.time + duration.time))
242: && (!loop.value)) {
243: if (isActive.value) {
244: setSoundEnable(false);
245: }
246: } else if ((loop.value) && (stopTime.time > startTime.time)
247: && (now >= stopTime.time)) {
248: if (isActive.value) {
249: setSoundEnable(false);
250: }
251: } else if ((loop.value) && (stopTime.time <= startTime.time)
252: && (now >= startTime.time)) {
253: if (!isActive.value) {
254: setSoundEnable(true);
255: }
256: } else if ((now > startTime.time) && (!isActive.value)) {
257: setSoundEnable(true);
258: }
259:
260: }
261:
262: /**
263: * Sets the soundEnable attribute of the AudioClip object
264: *
265: *@param b The new soundEnable value
266: */
267: void setSoundEnable(boolean b) {
268: isActive.setValue(b);
269: // it is possible that the vrml file specified a clip
270: // without the sound associated.
271: if (sound != null) {
272: sound.setEnable(b);
273: }
274: }
275:
276: /** Description of the Method */
277: void doChangeUrl() {
278: if (url.strings == null) {
279: System.out.println("url is null!");
280: }
281: if (url.strings.length > 0) {
282: if (browser.debug) {
283: System.out.println(loader.worldURLBaseName
284: + url.strings[0]);
285: }
286: try {
287: URL u = new URL(loader.worldURLBaseName
288: + url.strings[0]);
289: //impl.setURL(loader.worldURLBaseName+url.strings[0]);
290: impl.setURL(u);
291: } catch (java.net.MalformedURLException murle) {
292: murle.printStackTrace();
293: }
294: }
295: }
296:
297: /**
298: * Gets the type attribute of the AudioClip object
299: *
300: *@return The type value
301: */
302: public String getType() {
303: return "AudioClip";
304: }
305:
306: /** Description of the Method */
307: void initFields() {
308: description.init(this , FieldSpec, Field.EXPOSED_FIELD,
309: "description");
310: loop.init(this , FieldSpec, Field.EXPOSED_FIELD, "loop");
311: pitch.init(this , FieldSpec, Field.EXPOSED_FIELD, "pitch");
312: startTime.init(this , FieldSpec, Field.EXPOSED_FIELD,
313: "startTime");
314: stopTime.init(this , FieldSpec, Field.EXPOSED_FIELD, "stopTime");
315: url.init(this , FieldSpec, Field.EXPOSED_FIELD, "url");
316: duration.init(this , FieldSpec, Field.EVENT_OUT, "duration");
317: isActive.init(this , FieldSpec, Field.EVENT_OUT, "isActive");
318: }
319:
320: }
|