001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026: package com.sun.perseus.model;
027:
028: /**
029: * <code>SMILSample</code> is the root of the SMIL Timing engine operation.
030: * This class simply samples the time graph at the current time where the
031: * current time is controlled by a <code>Clock</code> abstraction.
032: *
033: * @version $Id: SMILSample.java,v 1.2 2006/04/21 06:38:28 st125089 Exp $
034: */
035: public class SMILSample implements Runnable {
036: /**
037: * The <code>Clock</code> abstraction is used to encapsulate the
038: * notion of time in the SMIL engine. By default, the clock will
039: * be the real-world clock. However, some other implementations
040: * might be useful, for example to render a given sequence of times
041: * or to force rendering at a fixed frame rate.
042: */
043: public static interface Clock {
044: /**
045: * @return the current time, according to the clock.
046: */
047: long currentTimeMillis();
048: }
049:
050: /**
051: * The <code>DocumentWallClock</code> implementation is used to sample the
052: * time graph according to the perceived user time.
053: */
054: public static class DocumentWallClock implements Clock {
055: /**
056: * The associated Document's time support.
057: */
058: TimeContainerRootSupport tcrs;
059:
060: /**
061: * Time at which the document was last sampled
062: */
063: long lastSample = Long.MAX_VALUE;
064:
065: /**
066: * true if the document's clock was started.
067: * @see #start
068: */
069: boolean reset = false;
070:
071: /**
072: * @param doc the associated Document
073: */
074: public DocumentWallClock(final DocumentNode doc) {
075: this .tcrs = doc.timeContainerRootSupport;
076: }
077:
078: /**
079: * @return the current time. For a DocumentWallClock, this is the
080: * system's current time minus the document start time so
081: * that 0 maps to the time the document was started.
082: */
083: public long currentTimeMillis() {
084: if (!reset) {
085: long ds = System.currentTimeMillis() - lastSample;
086: lastSample += ds;
087: return tcrs.lastSampleTime.value + ds;
088: } else {
089: lastSample = System.currentTimeMillis();
090: reset = false;
091: if (!tcrs.lastSampleTime.isResolved()) {
092: // We have never sampled the graph, start from 0
093: return 0;
094: } else {
095: // We actually paused for a while. We are resuming
096: // the clock.
097: return tcrs.lastSampleTime.value;
098: }
099: }
100: }
101:
102: /**
103: * Should be called when the document's time line is ready to
104: * begin. As a result, the first time currentTimeMillis is called,
105: * the return value should be exactly zero.
106: */
107: public void start() {
108: reset = true;
109: }
110: }
111:
112: /**
113: * The document on which sampling is done.
114: */
115: protected DocumentNode doc;
116:
117: /**
118: * The root of the time graph to sample.
119: */
120: protected TimeContainerRootSupport root;
121:
122: /**
123: * The time at which we are currently sampling.
124: */
125: protected Time currentTime = new Time(0);
126:
127: /**
128: * The clock used by this sampler to define the current document time.
129: */
130: protected Clock clock;
131:
132: /**
133: * Builds a new time graph sampler which samples the time graph
134: * at the current real-world time.
135: *
136: * @param doc the document, root of the time graph to sample. Should not
137: * be null. The DocumentNode's timeContainerRootSupport should not
138: * be null either.
139: * @param clock the clock used to provide the current time. Should not
140: * be null.
141: */
142: public SMILSample(final DocumentNode doc, final Clock clock) {
143: if (doc == null || doc.timeContainerRootSupport == null) {
144: throw new NullPointerException();
145: }
146:
147: if (clock == null) {
148: throw new NullPointerException();
149: }
150:
151: this .doc = doc;
152: this .root = doc.timeContainerRootSupport;
153: this .clock = clock;
154: }
155:
156: /**
157: * <code>Runnable</code> implementation.
158: */
159: public void run() {
160: currentTime.value = clock.currentTimeMillis();
161: doc.sample(currentTime);
162: // System.err.println("\n\n\n");
163: // root.dump();
164: doc.applyAnimations();
165: doc.applyMedia();
166: }
167: }
|