/* * @(#)Clock.java 1.3 02/08/21 * * Copyright (c) 1996-2002 Sun Microsystems, Inc. All rights reserved. */ package javax.media; /** * * The <code>Clock</code> interface is implemented by objects that support * the Java Media time model. * For example, this interface might be implemented by an object that * decodes and renders MPEG movies. * * <p> * * <h2>Clock and TimeBase</h2> * * <p> * A <code>Clock</code> contains a <code>TimeBase</code> that provides a source of time, * much like a crystal oscillator. The only information that a <code>TimeBase</code> provides is * its current time; it does not provide any methods for influencing how time is kept. * * A <code>Clock</code> defines a transformation on the time that its <code>TimeBase</code> keeps, typically marking * time for a particular media stream. The time that a <code>Clock</code> keeps is referred to as the <i>media time</i>. * * <p> * <h3>Clock Transform</h3> * * The transformation that a <code>Clock</code> defines on a <code>TimeBase</code> * is defined by three parameters: rate, <i>media start-time</i> (mst), and * <i>time-base start-time</i> (tbst). * Given a <i>time-base time</i> (tbt), * the <i>media time</i> (mt) can be calculated * using the following transformation: * <p> * * <CENTER><CODE>mt = mst + (tbt - tbst)*rate </CODE></CENTER> * <p> * * The rate is simply a scale factor that is applied * to the <code>TimeBase</code>. * For example, a rate of 2.0 indicates that the <code>Clock</code> * will run at twice the rate * of its <code>TimeBase</code>. Similarly, a negative rate indicates that * the <code>Clock</code> runs in the opposite direction of its <code>TimeBase</code>. * <p> * * The <i>time-base start-time</i> and the * <i>media start-time</i> define a common point in time * at which the <code>Clock</code> and the <code>TimeBase</code> are synchronized. * <p> * * <h3>Default Time Base</h3> * * A <code>Clock</code> has a default <code>TimeBase</code>. * For many objects that support the <code>Clock</code> interface, the default * <code>TimeBase</code> is the system <code>TimeBase</code>. * The system <code>TimeBase</code> can be obtained from <code>Manager</code> through * the <code>getSystemTimeBase</code> method. * <p> * * Some <code>Clocks</code> have a <code>TimeBase</code> other than * the system <code>TimeBase</code>. For example, an audio renderer that implements the <code>Clock</code> * interface might have a <code>TimeBase</code> that represents a * hardware clock. * <p> * * * <h2>Using a Clock</h2> * * You can get the <code>TimeBase</code> associated with a <code>Clock</code> by calling the <code>getTimeBase</code> method. To change the * <CODE>TimeBase</CODE> that a <CODE>Clock</CODE> uses, you call the <code>setTimeBase</code> method. * These get and set methods can be used together to synchronize different <code>Clocks</code> to the * same <code>TimeBase</code>. * <p> * For example, an application might want to force a video renderer to sync to the <code>TimeBase</code> of an audio renderer. To do this, * the application would call <code>getTimeBase</code> on the audio renderer and then use the value returned to call <code>setTimeBase</code> on the video renderer. * This would ensure that the two rendering objects use the same source of time. * * You can reset a <CODE>Clock</CODE> to use its default <CODE>TimeBase</CODE> by * calling <CODE>setTimeBase(null)</CODE>. * <p> * * Some <code>Clocks</code> are incapable of using another <code>TimeBase</code>. * If this is the case, an <code>IncompatibleTimeBaseException</code> is thrown when <code>setTimeBase</code> * is called. * <p> * * <code>Clock</code> also provides methods for getting and setting a <code>Clock's</code> <i>media time</i> and rate: * <ul> * <li><code>getMediaTime</code> and <code>setMediaTime</code> * <li><code>getRate</code> and <code>setRate</code> * </ul> * <a name="start"> * <h3>Starting a Clock</h3></a> * * Until a <code>Clock's</code> <code>TimeBase</code> transformation takes effect, the <code>Clock</code> is * in the <i>Stopped</i> state. Once all three transformation parameters (<i>media start-time</i>, * <i>time-base start-time</i>, and rate) have been provided * to the <code>Clock</code>, it enters the <i>Started</i> state. * <p> * * To start a <code>Clock</code>, <code>syncStart</code> is called with * the <i>time-base start-time</i> as an argument. * The new <i>media start-time</i> is taken as the current * <i>media time</i>, and the current rate defines the <code>Clock's</code> rate parameter. * When <code>syncStart</code> is called, the <code>Clock</code> and its <code>TimeBase</code> are * locked in sync and the <code>Clock</code> is considered to be in the <i>Started</i> state. * <p> * * When a <code>Clock</code> is stopped and then restarted (using <code>syncStart</code>), * the <i>media start-time</i> * for the restarted <code>Clock</code> is the current <i>media time</i>. * * The <code>syncStart</code> method is often used to synchronize * two <code>Clocks</code> that share the same <code>TimeBase</code>. * When the <i>time-base start-time</i> and rate of each clock are set to the same values and * each <code>Clock</code> is set with the appropriate <i>media start-time</i>, * the two <code>Clocks</code> will run in sync. * <p> * * When <code>syncStart</code> is called with a * new <i>time-base start-time</i>, * the synchronization with the <i>media time</i> doesn't occur * until the <code>TimeBase</code> * reaches the <i>time-base start-time</i>. * The <code>getMediaTime</code> method returns * the untransformed <i>media time</i> until the <code>TimeBase</code> * reaches the <i>time-base start-time</i>. * <p> * The <CODE>getSyncTime</CODE> method behaves slightly differently. * Once <CODE>syncStart</CODE> is invoked, <CODE>getSyncTime</CODE> * always reports the transformed <i>time-base time</i>, * whether or not the <i>time-base start-time</i> has been reached. * You can use <code>getSyncTime</code> to determine how much time remains * before the <i>time-base start-time</i> is reached. * When the <i>time-base start-time</i> is reached, * both * <CODE>getMediaTime</CODE> and <CODE>getSyncTime</CODE> * return the same value. * <p> * * Objects that implement * the <code>Clock</code> interface can provide more convenient start * methods than <CODE>syncStart</CODE>. * For example, <code>Player</code> defines <code>start</code>, * which should be used instead of <code>syncStart</code> * to start a <code>Player</code>. * * <h3>Stopping a Clock</h3> * * A <i>Stopped</i> <code>Clock</code> is no longer synchronized to * its <code>TimeBase</code>. When a <code>Clock</code> is <i>Stopped</i>, * its <i>media time</i> no longer moves in rate-adjusted synchronization with * the <i>time-base time</i> provided by its <code>TimeBase</code>. * <p> * * There are two ways to explicitly stop a <code>Clock</code>: you can invoke * <code>stop</code> or set a <i>media stop-time</i>. * When <code>stop</code> is invoked, synchronization with the * <code>TimeBase</code> immediately stops. * When a <i>media stop-time</i> is set, * synchronization stops when the <i>media stop-time</i> passes. * <p> * * A <CODE>Clock's</CODE> rate affects how its <i>media stop-time</i> * is interpreted. * If its rate is positive, the <code>Clock</code> * stops when the <i>media time</i> becomes * greater than or equal to the stop time. * If its rate is negative, the <code>Clock</code> stops * when the <i>media time</i> becomes * less than or equal to the stop time. * <p> * * If the stop-time is set to a value that the <code>Clock</code> * has already passed, the <code>Clock</code> immediately stops. * <p> * * Once a stop-time is set, it remains in effect until it is changed * or cleared. * To clear a stop-time, call <code>setStopTime</code> * with <code>Clock.RESET</code>. * A <CODE>Clock's</CODE> stop-time is cleared automatically when it stops. * <p> * * If no stop-time is ever set or if the stop-time is cleared, * the only way to stop the <code>Clock</code> is * to call the <code>stop</code> method. * <p> * * <h2>Clock State</h2> * * Conceptually, a <code>Clock</code> is * always in one of two states: <i>Started</i> or <i>Stopped</i>. * A <code>Clock</code> enters the <i>Started</i> state after * <code>syncStart</code> has been called and the <CODE>Clock</CODE> * is mapped to its <code>TimeBase</code>. * A <code>Clock</code> returns to the <i>Stopped</i> state immediately * when the <code>stop</code> method is called or the * <i>media time</i> passes the stop time. * <p> * * Certain methods can only be invoked when the <code>Clock</code> is in a * particular state. * If the <code>Clock</code> is in the wrong state when one of these methods * is called, an error or exception is thrown. * * <h3>Methods Restricted to <i>Started</i> Clocks</h3> * * The <code>mapToTimeBase</code> method can only be called on a * <code>Clock</code> in the <i>Started</i> state. * If it is invoked on a <i>Stopped</i> <code>Clock</code>, * a <code>ClockStoppedException</code> is thrown. * This is because the <code>Clock</code> is not synchronized to * a <code>TimeBase</code> when it is <i>Stopped</i>. * * <h3>Methods Restricted to <i>Stopped</i> Clocks</h3> * * The following methods can only be called on a * <code>Clock</code> in the <i>Stopped</i> state. * If invoked on a <i>Started</i>  * <code>Clock</code>, these methods throw a <code>ClockStartedError</code>. * <ul> * <li> <code>syncStart</code> * <li> <code>setTimeBase</code> * <li> <code>setMediaTime</code> * <li> <code>setRate</code> * </ul> * * Resetting the rate, the <i>media time</i>, the time base, or the * <i>time-base start-time</i> implies a complete remapping * between the <code>Clock</code> and its * <code>TimeBase</code> and is not allowed on * a <i>Started</i> <code>Clock</code>. * * <h3>Methods with Additional Restrictions</h3> * * A race condition occurs if a new <i>media stop-time</i> is set * when a <code>Clock</code> is already approaching a previously * set <i>media stop-time</i>. * In this situation, it impossible to guarantee when the <code>Clock</code> * will stop. To prevent this race condition, <code>setStopTime</code> can * only be set once on a <i>Started</i> <code>Clock</code>. * A <code>StopTimeSetError</code> is thrown if <code>setStopTime</code> * is called and the <i>media stop-time</i> has already been set. * <p> * * There are no restrictions on calling <code>setStopTime</code> on a * <i>Stopped</i> <code>Clock</code>; the stop time can always be * reset if the <code>Clock</code> is <i>Stopped</i>. * * @see TimeBase * @see Player * @version 1.3, 02/08/21 */ public interface Clock { /** * Returned by <CODE>getStopTime</CODE> if the stop-time is unset. */ static public final Time RESET = new Time(Long.MAX_VALUE); /** * Sets the <code>TimeBase</code> for this <code>Clock</code>. * This method can only be called on a * <i>Stopped</i> <code>Clock</code>. * A <code>ClockStartedError</code> is thrown if * <code>setTimeBase</code> is called on a <i>Started</i>  * <code>Clock</code>. * * <p> * A <code>Clock</code> has a default <code>TimeBase</code> that * is determined by the implementation. * To reset a <code>Clock</code> to its default * <code>TimeBase</code>, call <code>setTimeBase(null)</code>. * @param master The new <CODE>TimeBase</CODE> or <CODE>null</CODE> to reset the <code>Clock</code> * to its default <code>TimeBase</code>. * @exception IncompatibleTimeBaseException Thrown if * the <code>Clock</code> can't use the specified <code>TimeBase</code>. */ public void setTimeBase(TimeBase master) throws IncompatibleTimeBaseException; /** * Synchronizes the current <i>media time</i> to the specified * <I>time-base time</I> and start the <code>Clock</code>. * The <code>syncStart</code> method sets the <i>time-base start-time</i>, * and puts the <code>Clock</code> in the <i>Started</i> state. * This method can only be called on a * <i>Stopped</i> <code>Clock</code>. * A <code>ClockStartedError</code> is thrown if * <code>setTimeBase</code> is called on a <i>Started</i>  * <code>Clock</code>. * * @param at The <i>time-base time</i> to equate with the * current <i>media time</i>. */ public void syncStart(Time at); /** * Stops the <code>Clock</code>. * Calling <code>stop</code> releases the <code>Clock</code> from * synchronization with the <code>TimeBase</code>. * After this request is issued, the <code>Clock</code> is in the * <i>Stopped</i> state. * If <code>stop</code> is called on * a <i>Stopped</i> <code>Clock</code>, the request is ignored. * */ public void stop(); /** * * Sets the <i>media time</i> at which you want the <code>Clock</code> * to stop. * The <code>Clock</code> will stop when its <i>media time</i> * passes the stop-time. * To clear the stop time, set it to: <code>Clock.RESET</code>. * <p> * * You can always call <code>setStopTime</code> on a <i>Stopped</i>  * <code>Clock</code>. * <p> * * On a <i>Started</i> <code>Clock</code>, the stop-time can only * be set <I>once</I>. * * A <code>StopTimeSetError</code> is thrown if <code>setStopTime</code> * is called and the <i>media stop-time</i> has already been set. * * @param stopTime The time at which you want the * <code>Clock</code> to stop, in <i>media time</i>. */ public void setStopTime(Time stopTime); /** * Gets the last value successfully set by <CODE>setStopTime</CODE>. * * Returns the constant <CODE>Clock.RESET</CODE> if no stop time is set. * (<CODE>Clock.RESET</CODE> is the default stop time.) * * @return The current stop time. */ public Time getStopTime(); /** * Sets the <code>Clock's</code> <i>media time</i>. * This method can only be called on * a <i>Stopped</i> <code>Clock</code>. * A <code>ClockStartedError</code> is thrown if * <code>setMediaTime</code> is called on a <i>Started</i>  * <code>Clock</code>. * * @param now The new media time. */ public void setMediaTime(Time now); /** * Gets this <code>Clock's</code> current <i>media time</i>. * A <i>Started</i> <code>Clock's</code> <i>media time</i> * is based on its <code>TimeBase</code> * and rate, as described in <a href="#start"><I>Starting a Clock</I></a>. * * @return The current <i>media time</i>. */ public Time getMediaTime(); /** * Gets this <code>Clock's</code> current <i>media time</i> * in nanoseconds. * * @return The current <i>media time</i> in nanoseconds. */ public long getMediaNanoseconds(); /** * Gets the current <i>media time</i> or the time until this * <code>Clock</code> will synchronize to its <code>TimeBase</code>. * The <code>getSyncTime</code> method is used by <code>Players</code> and * advanced applet writers to synchronize <code>Clocks</code>. * <p> * * Like <code>getMediaTime</code>, this method returns * the <code>Clock's</code> current <i>media time</i>, * which is based on its <code>TimeBase</code> and rate. * * However, when <code>syncStart</code> is used to start * the <code>Clock</code>, <code>getSyncTime</code> performs a countdown * to the time-base start-time, returning the time remaining until * the <i>time-base start-time</i>. * Once the <code>TimeBase</code> reaches the * <i>time-base start-time</i>, <code>getSyncTime</code> * and <code>getMediaTime</code> will return the same value.<p> * */ public Time getSyncTime(); /** * Gets the <code>TimeBase</code> that this <code>Clock</code> is using. */ public TimeBase getTimeBase(); /** * Gets the <code>TimeBase</code> time corresponding to the specified <i>media time</i>. * * @exception ClockStoppedException Thrown if <CODE>mapToTimeBase</CODE> is called on a <i>Stopped</i>  * <code>Clock</code>. * * @param t The <i>media time</i> to map from. * * @return The <I>time-base time</I> in <I>media-time</I> coordinates. */ public Time mapToTimeBase(Time t) throws ClockStoppedException; /** * Gets the current temporal scale factor. * The scale factor defines the relationship * between the <code>Clock's</code> <i>media time</i> * and its <code>TimeBase</code>.<p> * * For example, a rate of 2.0 indicates that <i>media time</i> * will pass twice as fast as the <code>TimeBase</code> time once * the <code>Clock</code> * starts. Similarly, a negative rate indicates that * the <code>Clock</code> runs in the opposite direction of its <code>TimeBase</code>. * All <code>Clocks</code> are * guaranteed to support a rate of 1.0, the default rate. <code>Clocks</code> are not required * to support any other rate.<p> */ public float getRate(); /** * Sets the temporal scale factor. * The argument <i>suggests</i> the scale factor to use.<p> * * The <code>setRate</code> method returns the actual rate set by the * <code>Clock</code>. <code>Clocks</code> should set their rate as close to * the requested * value as possible, but are not required to set the rate to the exact * value of any argument other than 1.0. A <code>Clock</code> is only guaranteed to set * its rate exactly to 1.0. * <p> * * You can only call this method on a <i>Stopped</i> <code>Clock</code>. A * <code>ClockStartedError</code> is thrown if <code>setRate</code> is called on a <i>Started</i> <code>Clock</code>.<p> * * @param factor The temporal scale factor (rate) to set. * @return The actual rate set. */ public float setRate(float factor); }