/* * * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */ package javax.microedition.media; import javax.microedition.media.protocol.DataSource; import java.io.IOException; /** * <code>Player</code> controls the rendering of time based media data. * It provides the methods to manage the <code>Player</code>'s life * cycle, controls the playback progress, obtains the presentation * components, controls and provides the means to synchronize * with other <code>Players</code>. * * <h2>Simple Playback</h2> * * <blockquote> * A <code>Player</code> can be created from one of the * <code>Manager</code>'s <code>createPlayer</code> methods. * After the <code>Player</code> is created, * calling <code>start</code> will start the playback as soon as possible. * The method will return when the * playback is started. The playback will continue in the background * and will stop automatically when the end of media is reached. * <p> * <a href="#example">Simple playback example</a> illustrates this. * </blockquote> * * <h2>Player Life Cycle</h2> * * <blockquote> * A <code>Player</code> has five states: * <a href="#unrealizedState"><i>UNREALIZED</i></a>, * <a href="#realizedState"><i>REALIZED</i></a>, * <a href="#prefetchedState"><i>PREFETCHED</i></a>, * <a href="#startedState"><i>STARTED</i></a>, * <a href="#closedState"><i>CLOSED</i></a>. * <p> * * The purpose of these life-cycle states is to provide * programmatic control over potentially time-consuming operations. * For example, when a <code>Player</code> is first constructed, it's in * the <i>UNREALIZED</i> state. * Transitioned from <I>UNREALIZED</I> to <I>REALIZED</I>, the * <code>Player</code> * performs the communication necessary to locate all of the resources * it needs to function (such as communicating with a server * or a file system). * The <code>realize</code> method allows an application to initiate this * potentially time-consuming process at an * appropriate time. * <p> * * Typically, a <code>Player</code> moves from the <i>UNREALIZED</i> state * to the <i>REALIZED</i> state, then to the <i>PREFETCHED</i> state, * and finally on to the <i>STARTED</i> state. * <p> * * A <code>Player</code> stops when it reaches the * end of media; when * its stop time is reached; * or when the <code>stop</code> method is invoked. * When that happens, the <code>Player</code> moves from the * <i>STARTED</i> state * back to the <i>PREFETCHED</i> state. * It is then ready to repeat the cycle. * <p> * * To use a <code>Player</code>, you must set up parameters to * manage its movement through these life-cycle states and then * move it through the states using the <code>Player</code>'s * state transition methods. * * </blockquote> * <p> * * <h2>Player States</h2> * * <blockquote> * This section describes the semantics of each of the <code>Player</code> * states. * * <a name="unrealizedState"></a> * <h3>UNREALIZED State</h3> * <blockquote> * A <code>Player</code> starts in * the <i>UNREALIZED</i> state. * An unrealized <code>Player</code> * does not have enough information to acquire all the resources it needs * to function. * <p> * The following methods must not be used * when the <code>Player</code> is in * the <i>UNREALIZED</i> state. * <ul> * <li> <CODE>getContentType</CODE> * <li> <CODE>setTimeBase</CODE> * <li> <CODE>getTimeBase</CODE> * <li> <CODE>setMediaTime</CODE> * <li> <CODE>getControls</CODE> * <li> <CODE>getControl</CODE> * </ul> * * An <code>IllegalStateException</code> will be thrown. * <p> * The <a href="#realize()"><code>realize</code></a> method transitions * the <code>Player</code> from the <i>UNREALIZED</i> state to the * <i>REALIZED</i> state. * </blockquote> * * <a name="realizedState"></a> * <h3>REALIZED State</h3> * * <blockquote> * A <code>Player</code> is in the <i>REALIZED</i> state when it * has obtained * the information required to acquire the media resources. * Realizing a <code>Player</code> can be a resource and * time consuming process. * The <code>Player</code> may have to communicate with * a server, read a file, or interact with a set of objects. * <p> * * Although a realized <code>Player</code> does not have * to acquire any resources, it * is likely to have acquired all of the resources it needs except * those that imply exclusive use of a * scarce system resource, such as an audio device. * <p> * * Normally, a <code>Player</code> moves from the <i>UNREALIZED</i> state * to the <i>REALIZED</i> state. * After <a href="#realize()"><code>realize</code></a> has been * invoked on a <code>Player</code>, * the only way it can return * to the <i>UNREALIZED</i> state is if * <a href="#deallocate()"><code>deallocate</code></a> is * invoked before <code>realize</code> is completed. * Once a <code>Player</code> reaches the <i>REALIZED</i> state, it * never returns to the <i>UNREALIZED</i> state. It remains in one of four * states: <i>REALIZED</i>, <i>PREFETCHED</i>, <i>STARTED</i> or * <i>CLOSED</i>. * </blockquote> * * <a name="prefetchedState"></a> * <h3>PREFETCHED State</h3> * * <blockquote> * Once realized, a <code>Player</code> may still need to * perform a number of time-consuming tasks before it is ready to be started. * For example, it may need to acquire scarce or exclusive resources, * fill buffers with media data, or perform other start-up processing. * Calling * <a href="#prefetch()"><code>prefetch</code></a> * on the <code>Player</code> carries * out these tasks. * <p> * * Once a <code>Player</code> is in the <i>PREFETCHED</i> state, it may * be started. * Prefetching reduces the startup latency of a <code>Player</code> * to the minimum possible value. * <p> * * When a started <code>Player</code> stops, * it returns * to the <i>PREFETCHED</i> state. * </blockquote> * <p> * * <a name="startedState"></a> * <h3>STARTED State</h3> * * <blockquote> * Once prefetched, a <code>Player</code> can enter the * <i>STARTED</i> state by calling the * <a href="#start()"><code>start</code></a> method. * A <I>STARTED</I> <CODE>Player</CODE>  * means the <code>Player</code> is running and processing data. * A <code>Player</code> returns to the <i>PREFETCHED</i> * state when it stops, because the * <a href="#stop()"><code>stop</code></a> method was invoked, * it has reached the end of the media, or its stop time. * <p> * * When the <code>Player</code> moves from the <i>PREFETCHED</i> * to the <i>STARTED</i> state, it posts a <code>STARTED</code> event. * When it moves from the <i>STARTED</i> state to the * <i>PREFETCHED</i> state, * it posts a <code>STOPPED</code>, <code>END_OF_MEDIA</code> or * <code>STOPPED_AT_TIME</code> event depending on the reason it * stopped. * <p> * * The following methods must not be used * when the <code>Player</code> is in the <i>STARTED</i> state: * <ul> * <li> <CODE>setTimeBase</CODE> * <li> <CODE>setLoopCount</CODE> * </ul> * * An <code>IllegalStateException</code> will be thrown. * * </blockquote> * * <a name="closedState"></a> * <h3>CLOSED state</h3> * * <blockquote> * Calling <code>close</code> on the <code>Player</code> * puts it in the <i>CLOSED</i> state. In the <i>CLOSED</i> * state, the <code>Player</code> has * released most of its resources and must not * be used again. * </blockquote> * * The <code>Player</code>'s five states and the state transition * methods are summarized in the following diagram: * <p> * <blockquote> * <img src="states.gif" width="492" height="183"> * </blockquote> * * </blockquote> * <p> * * <a name="CE"> * <h2>Player Events</h2></a> * * <blockquote> * <code>Player</code> events asynchronously deliver * information about the <code>Player</code>'s state changes * and other relevant information from the <code>Player</code>'s * <code>Control</code>s. * <p> * * To receive events, an object must implement the * <code>PlayerListener</code> interface and use the * <code>addPlayerListener</code> method to register its * interest in a <code>Player</code>'s events. * All <code>Player</code> events are posted to each * registered listener. * <p> * * The events are guaranteed to be delivered in the order * that the actions representing the events occur. * For example, if a <code>Player</code> * stops shortly after it starts because it is playing back * a very short media file, the <code>STARTED</code> event * must always * preceed the <code>END_OF_MEDIA</code> event. * <p> * * An <code>ERROR</code> event may be sent any time * an irrecoverable error has occured. When that happens, the * <code>Player</code> is in the <i>CLOSED</i> state. * <p> * * The <code>Player</code> event mechanism is extensible and * some <code>Players</code> define events other than * the ones described here. For a list of pre-defined player * events, check the <code>PlayerListener</code> interface. * </blockquote> * * <h3>Managing the Resources Used by a Player</h3> * * <blockquote> * The <a href="#prefetch()"><code>prefetch</code></a> * method is used to acquire scarce or exclusive resources * such as the audio device. * Conversely, the <a href="#deallocate()"><code>deallocate</code></a> * method is used to release the scarce or exclusive * resources. By using these two methods, an application can * programmatically manage the <code>Player</code>'s resources. * <p> * For example, in an implementation with an exclusive audio device, to * alternate the audio playback of multiple <code>Player</code>s, * an application can selectively deallocate and prefetch individual * <code>Player</code>s. * * </blockquote> * <p> * * <h2>Player's TimeBase</h2> * * <blockquote> * The <code>TimeBase</code> of a <code>Player</code> provides the * basic measure of time for the <code>Player</code> to synchronize * its media playback. Each <code>Player</code> must provide one * default <code>TimeBase</code>. The <code>getTimeBase</code> * method can be used to retrieve that. * <p> * * Setting a different <code>TimeBase</code> on a * <code>Player</code> instructs the <code>Player</code> to synchronize * its playback rate according to the given <code>TimeBase</code>. * <p> * * Two <code>Player</code>s can be synchronized by getting the * <code>TimeBase</code> from one <code>Player</code> and setting * that on the second <code>Player</code>. * <p> * * However, not all <code>Player</code>s support using a different * <code>TimeBase</code> other than its own. In such cases, * a <code>MediaException</code> will be thrown when * <code>setTimeBase</code> is called. * </blockquote> * <p> * * <a name="controls"></a> * <h2>Player's Controls</h2> * <blockquote> * <code>Player</code> implements <code>Controllable</code> which * provides extra controls via some type-specific <code>Control</code> * interfaces. <code>getControl</code> and <code>getControls</code> * cannot be called when the <code>Player</code> is in the * <i>UNREALIZED</i> or <i>CLOSED</i> state. * An <code>IllegalStateException</code> will be thrown. * </blockquote> * <p> * * <a name="example"></a> * <h2>Simple Playback Example</h2> * * <blockquote> * <pre> * try { * Player p = Manager.createPlayer("http://abc.mpg"); * p.realize(); * VideoControl vc; * if ((vc = (VideoControl)p.getControl("VideoControl")) != null) * add((Component)vc.initDisplayMode(vc.USE_GUI_PRIMITIVE, null)); * p.start(); * } catch (MediaException pe) { * } catch (IOException ioe) { * } * </pre> * </blockquote> * */ public interface Player extends Controllable { /** * The state of the <code>Player</code> indicating that it has * not acquired the required information and resources to function. * <p> * Value 100 is assigned to <code>UNREALIZED</code>. */ int UNREALIZED = 100; /** * The state of the <code>Player</code> indicating that it has * acquired the required information but not the resources to function. * <p> * Value 200 is assigned to <code>REALIZED</code>. */ int REALIZED = 200; /** * The state of the <code>Player</code> indicating that it has * acquired all the resources to begin playing. * <p> * Value 300 is assigned to <code>PREFETCHED</code>. */ int PREFETCHED = 300; /** * The state of the <code>Player</code> indicating that the * <code>Player</code> has already started. * <p> * Value 400 is assigned to <code>STARTED</code>. */ int STARTED = 400; /** * The state of the <code>Player</code> indicating that the * <code>Player</code> is closed. * <p> * Value 0 is assigned to <code>CLOSED</code>. */ int CLOSED = 0; /** * The returned value indicating that the requested time is unknown. * <p> * Value -1 is assigned to <code>TIME_UNKNOWN</code>. */ long TIME_UNKNOWN = -1; /** * Constructs portions of the <code>Player</code> without * acquiring the scarce and exclusive resources. * This may include examining media data and may * take some time to complete. * <p> * When <code>realize</code> completes successfully, * the <code>Player</code> is in the * <i>REALIZED</i> state. * <p> * If <code>realize</code> is called when the <code>Player</code> is in * the <i>REALIZED</i>, <i>PREFETCHTED</i> or <i>STARTED</i> state, * the request will be ignored. * * @exception IllegalStateException Thrown if the <code>Player</code> * is in the <i>CLOSED</i> state. * @exception MediaException Thrown if the <code>Player</code> cannot * be realized. * @exception SecurityException Thrown if the caller does not * have security permission to realize the <code>Player</code>. * */ void realize() throws MediaException; /** * Acquires the scarce and exclusive resources * and processes as much data as necessary * to reduce the start latency. * <p> * When <code>prefetch</code> completes successfully, * the <code>Player</code> is in * the <i>PREFETCHED</i> state. * <p> * If <code>prefetch</code> is called when the <code>Player</code> * is in the <i>UNREALIZED</i> state, * it will implicitly call <code>realize</code>. * <p> * If <code>prefetch</code> is called when the <code>Player</code> * is already in the <i>PREFETCHED</i> state, the <code>Player</code> * may still process data necessary to reduce the start * latency. This is to guarantee that start latency can * be maintained at a minimum. * <p> * If <code>prefetch</code> is called when the <code>Player</code> * is in the <i>STARTED</i> state, * the request will be ignored. * <p> * If the <code>Player</code> cannot obtain all * of the resources it needs, it throws a <code>MediaException</code>. * When that happens, the <code>Player</code> will not be able to * start. However, <code>prefetch</code> may be called again when * the needed resource is later released perhaps by another * <code>Player</code> or application. * * @exception IllegalStateException Thrown if the <code>Player</code> * is in the <i>CLOSED</i> state. * @exception MediaException Thrown if the <code>Player</code> cannot * be prefetched. * @exception SecurityException Thrown if the caller does not * have security permission to prefetch the <code>Player</code>. * */ void prefetch() throws MediaException; /** * Starts the <code>Player</code> as soon as possible. * If the <code>Player</code> was previously stopped * by calling <code>stop</code> or reaching a preset * stop time, it will resume playback * from where it was previously stopped. If the * <code>Player</code> has reached the end of media, * calling <code>start</code> will automatically * start the playback from the start of the media. * <p> * When <code>start</code> returns successfully, * the <code>Player</code> must have been started and * a <code>STARTED</code> event will * be delivered to the registered <code>PlayerListener</code>s. * However, the <code>Player</code> is not guaranteed to be in * the <i>STARTED</i> state. The <code>Player</code> may have * already stopped (in the <i>PREFETCHED</i> state) because * the media has 0 or a very short duration. * <p> * If <code>start</code> is called when the <code>Player</code> * is in the <i>UNREALIZED</i> or <i>REALIZED</i> state, * it will implicitly call <code>prefetch</code>. * <p> * If <code>start</code> is called when the <code>Player</code> * is in the <i>STARTED</i> state, * the request will be ignored. * * @exception IllegalStateException Thrown if the <code>Player</code> * is in the <i>CLOSED</i> state. * @exception MediaException Thrown if the <code>Player</code> cannot * be started. * @exception SecurityException Thrown if the caller does not * have security permission to start the <code>Player</code>. */ void start() throws MediaException; /** * Stops the <code>Player</code>. It will pause the playback at * the current media time. * <p> * When <code>stop</code> returns, the <code>Player</code> is in the * <i>PREFETCHED</i> state. * A <code>STOPPED</code> event will be delivered to the registered * <code>PlayerListener</code>s. * <p> * If <code>stop</code> is called on * a stopped <code>Player</code>, the request is ignored. * * @exception IllegalStateException Thrown if the <code>Player</code> * is in the <i>CLOSED</i> state. * @exception MediaException Thrown if the <code>Player</code> * cannot be stopped. */ void stop() throws MediaException; /** * Release the scarce or exclusive * resources like the audio device acquired by the <code>Player</code>. * <p> * When <code>deallocate</code> returns, the <code>Player</code> * is in the <i>UNREALIZED</i> or <i>REALIZED</i> state. * <p> * If the <code>Player</code> is blocked at * the <code>realize</code> call while realizing, calling * <code>deallocate</code> unblocks the <code>realize</code> call and * returns the <code>Player</code> to the <i>UNREALIZED</i> state. * Otherwise, calling <code>deallocate</code> returns the * <code>Player</code> to the <i>REALIZED</i> state. * <p> * If <code>deallocate</code> is called when the <code>Player</code> * is in the <i>UNREALIZED</i> or <i>REALIZED</i> * state, the request is ignored. * <p> * If the <code>Player</code> is <code>STARTED</code> * when <code>deallocate</code> is called, <code>deallocate</code> * will implicitly call <code>stop</code> on the <code>Player</code>. * * @exception IllegalStateException Thrown if the <code>Player</code> * is in the <i>CLOSED</i> state. */ void deallocate(); /** * Close the <code>Player</code> and release its resources. * <p> * When the method returns, the <code>Player</code> is in the * <i>CLOSED</i> state and can no longer be used. * A <code>CLOSED</code> event will be delivered to the registered * <code>PlayerListener</code>s. * <p> * If <code>close</code> is called on a closed <code>Player</code> * the request is ignored. */ void close(); /** * Sets the <code>TimeBase</code> for this <code>Player</code>. * <p> * A <code>Player</code> has a default <code>TimeBase</code> that * is determined by the implementation. * To reset a <code>Player</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>Player</code> * to its default <code>TimeBase</code>. * @exception IllegalStateException Thrown if the <code>Player</code> * is in the <i>UNREALIZED</i>, <i>STARTED</i> or <i>CLOSED</i> state. * @exception MediaException Thrown if * the specified <code>TimeBase</code> cannot be set on the * <code>Player</code>. * @see #getTimeBase */ void setTimeBase(TimeBase master) throws MediaException; /** * Gets the <code>TimeBase</code> that this <code>Player</code> is using. * @return The <code>TimeBase</code> that this <code>Player</code> is using. * @see #setTimeBase * * @exception IllegalStateException Thrown if the <code>Player</code> * is in the <i>UNREALIZED</i> or <i>CLOSED</i> state. */ TimeBase getTimeBase(); /** * Sets the <code>Player</code>'s <i>media time</i>. * <p> * For some media types, setting the media time may not be very * accurate. The returned value will indicate the * actual media time set. * <p> * Setting the media time to negative values will effectively * set the media time to zero. Setting the media time to * beyond the duration of the media will set the time to * the end of media. * <p> * There are some media types that cannot support the setting * of media time. Calling <code>setMediaTime</code> will throw * a <code>MediaException</code> in those cases. * * @param now The new media time in microseconds. * @return The actual media time set in microseconds. * @exception IllegalStateException Thrown if the <code>Player</code> * is in the <i>UNREALIZED</i> or <i>CLOSED</i> state. * @exception MediaException Thrown if the media time * cannot be set. * @see #getMediaTime */ long setMediaTime(long now) throws MediaException; /** * Gets this <code>Player</code>'s current <i>media time</i>. * <p> * <code>getMediaTime</code> may return <code>TIME_UNKNOWN</code> to * indicate that the media time cannot be determined. * However, once <code>getMediaTime</code> returns a known time * (time not equals to <code>TIME_UNKNOWN</code>), subsequent calls * to <code>getMediaTime</code> must not return * <code>TIME_UNKNOWN</code>. * * @return The current <i>media time</i> in microseconds or * <code>TIME_UNKNOWN</code>. * @exception IllegalStateException Thrown if the <code>Player</code> * is in the <i>CLOSED</i> state. * @see #setMediaTime */ long getMediaTime(); /** * Gets the current state of this <code>Player</code>. * The possible states are: <i>UNREALIZED</i>, * <i>REALIZED</i>, <i>PREFETCHED</i>, <i>STARTED</i>, <i>CLOSED</i>. * * @return The <code>Player</code>'s current state. */ int getState(); /** * Get the duration of the media. * The value returned is the media's duration * when played at the default rate. * <br> * If the duration cannot be determined (for example, the * <code>Player</code> is presenting live * media) <CODE>getDuration</CODE> returns <CODE>TIME_UNKNOWN</CODE>. * * @return The duration in microseconds or <code>TIME_UNKNOWN</code>. * @exception IllegalStateException Thrown if the <code>Player</code> * is in the <i>CLOSED</i> state. */ long getDuration(); /** * Get the content type of the media that's * being played back by this <code>Player</code>. * <p> * See <a href="Manager.html#content-type">content type</a> * for the syntax of the content type returned. * * @return The content type being played back by this * <code>Player</code>. * @exception IllegalStateException Thrown if the <code>Player</code> * is in the <i>UNREALIZED</i> or <i>CLOSED</i> state. */ String getContentType(); /** * Set the number of times the <code>Player</code> will loop * and play the content. * <p> * By default, the loop count is one. That is, once started, * the <code>Player</code> will start playing from the current * media time to the end of media once. * <p> * If the loop count is set to N where N is bigger than one, * starting the <code>Player</code> will start playing the * content from the current media time to the end of media. * It will then loop back to the beginning of the content * (media time zero) and play till the end of the media. * The number of times it will loop to the beginning and * play to the end of media will be N-1. * <p> * Setting the loop count to 0 is invalid. An * <code>IllegalArgumentException</code> will be thrown. * <p> * Setting the loop count to -1 will loop and play the content * indefinitely. * <p> * If the <code>Player</code> is stopped before the preset loop * count is reached either because <code>stop</code> is called or * a preset stop time (set with the <code>StopTimeControl</code>) * is reached, calling <code>start</code> again will * resume the looping playback from where it was stopped until it * fully reaches the preset loop count. * <p> * An <i>END_OF_MEDIA</i> event will be posted * every time the <code>Player</code> reaches the end of media. * If the <code>Player</code> loops back to the beginning and * starts playing again because it has not completed the loop * count, a <i>STARTED</i> event will be posted. * * @param count indicates the number of times the content will be * played. 1 is the default. 0 is invalid. -1 indicates looping * indefintely. * @exception IllegalArgumentException Thrown if the given * count is invalid. * @exception IllegalStateException Thrown if the * <code>Player</code> is in the <i>STARTED</i> * or <i>CLOSED</i> state. */ void setLoopCount(int count); /** * Add a player listener for this player. * * @param playerListener the listener to add. * If <code>null</code> is used, the request will be ignored. * @exception IllegalStateException Thrown if the <code>Player</code> * is in the <i>CLOSED</i> state. * @see #removePlayerListener */ void addPlayerListener(PlayerListener playerListener); /** * Remove a player listener for this player. * * @param playerListener the listener to remove. * If <code>null</code> is used or the given * <code>playerListener</code> is not a listener for this * <code>Player</code>, the request will be ignored. * @exception IllegalStateException Thrown if the <code>Player</code> * is in the <i>CLOSED</i> state. * @see #addPlayerListener */ void removePlayerListener(PlayerListener playerListener); }