javax.media
Interface Controller

All Known Subinterfaces:
Player, Processor

public abstract interface Controller
extends Clock, Duration

The Controller interface, which extends Clock, provides resource-allocation state information, event generation, and a mechanism for obtaining objects that provide additional control over a Controller.

Controller Life Cycle

As a Clock, a Controller is always either Started or Stopped. However, Controller subdivides Clock's Stopped state into five resource-allocation phases: Unrealized, Realizing, Realized, Prefetching, and Prefetched.

The purpose of these life-cycle states is to provide programmatic control over potentially time-consuming operations. For example, when a Controller is first constructed, it's in the Unrealized state. While Realizing, the Controller performs the communication necessary to locate all of the resources it needs to function (such as communicating with a server, other controllers, or a file system). The realize method allows an application to initiate this potentially time-consuming process (Realizing) at an appropriate time. When a Controller is Realizing or Prefetching, it will eventually transition to another state, such as Realized, Prefetched, or even Unrealized.

Because a Controller is often in one state and on its way to another, its destination or target state is an integral part of the Controller life cycle. You can query a Controller to determine both its current state and its target state.

A Controller typically moves from the Unrealized state through Realizing to the Realized state, then through Prefetching to the Prefetched state, and finally on to the Started state. When a Controller finishes because the end of the media stream is reached, its stop time is reached, or the stop method is invoked, the Controller moves from the Started state back to Prefetched or possibly back to Realized, and is ready to repeat the cycle.

To use a Controller, you must set up parameters to manage its movement through these life-cycle states and then move it through the states using the Controller state transition methods. To keep track of the Controller's current state, you monitor the state transition events that it posts when changing states.

State Transition Methods

A Controller has five methods that are used to induce life cycle state changes: realize, prefetch, deallocate, syncStart, and stop. To transition a Controller to the Realized, Prefetched, or Started state, you use the corresponding method: realize, prefetch, or syncStart. The deallocate and stop methods can change a requested state transition or trigger a state change.

The forward transition methods (realize, prefetch, and syncStart) are executed asynchronously and return immediately. When the requested operation is complete, the Controller posts a ControllerEvent indicating that the target state has been reached, stop or deallocate has been invoked, or that an error has occurred.

The deallocate and stop methods can change the target state and induce a transition back to a previous state. For example, calling deallocate on a Controller in the Prefetching state will move it back to the Realized state. These methods are synchronous.

State Transition Events

A Controller often moves between states in an asynchronous manner. To facilitate the tracking of a Controller's state, every time its state or target state changes, the Controller is required to post a TransitionEvent that describes its previous state, current state, and new target state. By monitoring the Controller event stream, you can determine exactly what a Controller is doing at any point in time.

When one of the asynchronous forward state transition methods completes, the Controller posts the appropriate TransitionEvent or a ControllerErrorEvent indicating that the Controller is no longer usable. For more information about ControllerEvents, see the Controller Events section.

To facilitate simple asynchronous method protocols, a Controller always posts a method completion event when one of the asynchronous forward state transition methods is invoked, even if no state or target state change occurs. For example, if realize is called on a Prefetching Controller, a RealizeCompleteEvent is immediately posted, even though the Controller remains in the Prefetching state and the target state is still Prefetched. The method completion events always report the Controller's previous, current, and target state at the time the event was posted.

Controller States

This section describes the semantics of each of the Controller states.

Unrealized State

A newly instanced Controller starts in the Unrealized state. An Unrealized Controller knows very little about its internals and does not have enough information to acquire all of the resources it needs to function. In particular, an Unrealized Controller does not know enough to properly construct a Clock. Therefore, it is illegal to call the following methods on an Unrealized Controller: A NotRealizedError is thrown if any of these methods are called on an Unrealized Controller.

Realizing and Realized States

A Controller is Realized when it has obtained all of the information necessary for it to acquire the resources it needs to function. A Realizing Controller is in the process of identifying the resources that it needs to acquire. Realizing can be a resource-consuming and time-consuming process. A Realizing Controller might have to communicate with a server, read a file, or interact with a set of objects.

Although a Realized Controller does not have to acquire any resources, a Realized Controller 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 or MPEG decoding hardware.

Normally, a Controller moves from the Unrealized state through Realizing and on to the Realized state. After realize has been invoked on a Controller, the only way it can return to the Unrealized state is if deallocate is invoked before Realizing is completed. Once a Controller reaches the Realized state, it never returns to the Unrealized state. It remains in one of four states: Realized, Prefetching, Prefetched, or Started.

Realize Method

The realize method executes asynchronously and completion is signaled by a RealizeCompleteEvent or a ControllerErrorEvent.

Prefetching and Prefetched States

Once Realized, a Controller might still need to perform a number of time-consuming tasks before it is ready to be started. For example, it might need to acquire scarce hardware resources, fill buffers with media data, or perform other start-up processing. While performing these tasks, the Controller is in the Prefetching state. When finished, it moves into the Prefetched state. Over a Controller's lifetime, Prefetching might have to recur when certain methods are invoked. For example, calling setMediaTime might cause a Player to be Prefetched again before it is Started.

Once a Controller is Prefetched, it is capable of starting as quickly as is possible for that Controller. Prefetching reduces the startup latency of a Controller to the minimum possible value. (The startup latency is the value returned by getStartLatency.)

Typically, a Controller moves from the Realized state through Prefetching and on to the Prefetched state. Once Prefetched, a Controller remains Prefetched unless deallocate, syncStart or a method such as setMediaTime, which changes its state and increases its startup latency, is invoked.

When a Started Controller stops, it returns to the Prefetched or Realized state.

Prefetch Method

The prefetch method is asynchronous and its completion is signaled by a PrefetchCompleteEvent or a ControllerErrorEvent. As a convenience, if prefetch is invoked before a Controller has reached the Realized state, an implicit realize is invoked by changing the target state to Prefetched. Both a RealizeCompleteEvent and a PrefetchCompleteEvent are posted by the Controller as it transitions to the Prefetched state.

If a Controller is Prefetching and cannot obtain all of the resources it needs to start, it posts a ResourceUnavailableEvent instead of a PrefetchCompleteEvent. This is a catastrophic error condition from which the Controller cannot recover.

Started State

Once Prefetched, a Controller can enter the Started state. A Started Controller's Clock is running and is processing data. A Controller returns to the Prefetched or Realized state when it stops because it has either reached its stop time, reached the end of the media, or because the stop method was invoked.

When the Controller moves from the Prefetched to the Started state, it posts a StartEvent. When it moves from the Started state to a stopped state, it posts a StopEvent.

A Controller is a Clock; therefore, syncStart, setTimeBase, setMediaTime, and setRate are illegal when the Controller is in the Started state.

syncStart

The only way to start a Controller is to call syncStart.

It is illegal to call syncStart unless the Controller is in the Prefetched state. If syncStart is called before the Controller is Prefetched, a NotPrefetchedError is thrown. Player defines a start method that relaxes this requirement.

Freeing the Resources Used by a Controller

Deallocate is used to stop a Controller's resource consumption. For example, when Applet.stop is called, deallocate should be called to free the resources that were used by the Controller. Deallocate stops any resource-consuming activity and releases any exclusive-use resources that the Controller has acquired. Deallocate executes synchronously; when deallocate returns, the resources have been released.

If the Controller is Unrealized or Realizing, calling deallocate returns it to the Unrealized state. Otherwise, calling deallocate returns a Controller to the Realized state. Regardless of the state that a Controller is in, deallocate must relinquish any exclusive-use system resources that it holds; the only way to guarantee that a Controller is not holding resources is to call the deallocate method.

It is illegal to call deallocate on a Started Controller. You must stop the Controller before it can relinquish its resources.

When deallocate is called, a Controller posts a special StopEvent, DeallocateEvent.

Controller Events

Controller events asynchronously deliver information about Controller state changes. There are four kinds of notifications: life cycle transition, method acknowledgement, state notification, and error notification.

To receive events, an object must implement the ControllerListener interface and use the addControllerListener method to register its interest in a Controller's events. All Controller events are posted to each registered listener.

The Controller event mechanism is extensible and some Controllers define events other than the ones described here. For example, the DurationUpdateEvents posted by a Player are ControllerEvents.

TransitionEvent
TransitionEvents are posted when a Controller's current or target state changes. TransitionEvent is subclassed to provide a small set of events that are posted for particular kinds of transitions that merit special interest. The class name of the event indicates either the reason that the event was posted (such as EndOfMediaEvent), or the particular transition representedby the event (such as PrefetchCompleteEvent).

In addition to being posted for state transitions, the method acknowledgement events RealizeCompleteEvent, PrefetchCompleteEvent, StartEvent, DeallocateEvent, and StopByRequestEvent are always posted to signify method completion even if no transition has taken place.

RealizeCompleteEvent
Posted when a Controller moves from the Realizing to the Realized state, or when the realize method is invoked and the Controller is already Realized.
PrefetchCompleteEvent
Posted when a Controller moves from the Prefetching to the Prefetched state, or when the prefetch method is invoked and the Controller is already Prefetched.
StartEvent
Posted when a Controller moves from the Prefetched to the Started state.

StopEvent
Posted when a Controller moves backwards, for example, when moving from Prefetched to Realized or from Started to Prefetched. The reason that a stop event occurs is often important; this information is provided through several subclasses of StopEvent.
StopAtTimeEvent
Posted when a Controller changes state because it has reached its stop time.
StopByRequestEvent
Posted when a Controller changes state because stop is invoked. This event is also posted as an acknowledgement to stop requests.
DeallocateEvent
Posted when the deallocate method is invoked, indicating a possible state change and the loss of exclusive-use resources. The current state is either Unrealized or Realized. This event doesn't always indicate a state change. For example, it is posted even if deallocate is called on a Realized  Controller.
EndOfMediaEvent
Posted when a Controller has reached the end of the media.
ControllerClosedEvent
When a Controller closes it is no longer usable, and it will post a ControllerClosedEvent. Once this has happened, method calls on the Controller have undefined behavior. A Controller will close for one of two reasons; either the close method was invoked on the Controller, or an error has occurred. If a Controller is closed because the close method was invoked, it posts a ControllerClosedEvent. If an error occurs it posts one of the ControllerErrorEvents.
ControllerErrorEvent
This is the super class of all of the error events that can be posted by a Controller. While this event is rarely posted, you should watch for it when processing other error events--this is how you can detect implementation-specific error events.

When a ControllerErrorEvent is posted, it indicates a catastrophic error from which the Controller cannot recover. There is no recovery mechanism for a Controller once one of these events has been posted.

ResourceUnavailableEvent
This error event is posted during Prefetching or Realizing to indicate that the operation failed because a required resource was unavailable.
DataLostErrorEvent
This error event is posted when a Controller has lost data.
InternalErrorEvent
This error event is posted when something goes wrong with the Controller for an implementation-specific reason. This usually indicates that there is a problem with the implementation.
Status Change Events
A small number of status changes occur in a Controller where notification of the change is useful, particularly for updating user interface components. Notification of these changes is provided through three ControllerEvents:
RateChangeEvent
Posted when the rate of a Controller changes.
StopTimeChangeEvent
Posted when the stop time of a Controller changes.
MediaTimeSetEvent
Posted when the media time has been set using the setMediaTime method. This event is not periodically posted when media time changes due to normal Controller processing and Clock operation.

Controls

A Control is an object that provides a way to affect some aspect of a Controller's operation in a specific way. The Control interface provides access to a GUI Component that is specific to the particular Control. For example, the GainControl interface provides a way to display a GUI control that allows the user to change the volume.

A Controller makes available a collection of Controls that influence the Controller's behavior. To access these Controls, use the getControls method, which returns an array of supported Controls. If you know the full class or interface name of the desired Control, you can use getControl.

Since an application using a Controller might not know how to use all of the Controls supported by a Controller, it can make the functionality available to a user by providing access to the Component for the Control.

See Also:
Player, Control, ControllerListener, ControllerEvent, TransitionEvent, RealizeCompleteEvent, PrefetchCompleteEvent, StartEvent, StopEvent, EndOfMediaEvent, ControllerErrorEvent, DataLostErrorEvent, ResourceUnavailableEvent, InternalErrorEvent, RateChangeEvent, MediaTimeSetEvent, ClockStartedError, NotRealizedError

Field Summary
static Time LATENCY_UNKNOWN
          Returned by getStartLatency.
static int Prefetched
          Returned by getState.
static int Prefetching
          Returned by getState.
static int Realized
          Returned by getState.
static int Realizing
          Returned by getState.
static int Started
          Returned by getState.
static int Unrealized
          Returned by getState.
 
Fields inherited from class javax.media.Clock
RESET
 
Fields inherited from class javax.media.Duration
DURATION_UNBOUNDED, DURATION_UNKNOWN
 
Method Summary
 void addControllerListener(ControllerListener listener)
          Specify a ControllerListener to which this Controller will send events.
 void close()
          Release all resources and cease all activity.
 void deallocate()
          Abort the current operation and cease any activity that consumes system resources.
 Control getControl(java.lang.String forName)
          Get the Control that supports the specified class or interface.
 Control[] getControls()
          Get a list of the Control objects supported by this Controller.
 Time getStartLatency()
          Get the Controller's start latency in nanoseconds.
 int getState()
          Get the current state of this Controller.
 int getTargetState()
          Get the current target state of this Controller.
 void prefetch()
          Process as much data as necessary to reduce the Controller's start latency to the shortest possible time.
 void realize()
          Construct the media dependent portions of the Controller.
 void removeControllerListener(ControllerListener listener)
          Remove the specified listener from this Controller's listener list.
 
Methods inherited from interface javax.media.Clock
getMediaNanoseconds, getMediaTime, getRate, getStopTime, getSyncTime, getTimeBase, mapToTimeBase, setMediaTime, setRate, setStopTime, setTimeBase, stop, syncStart
 
Methods inherited from interface javax.media.Duration
getDuration
 

Field Detail

LATENCY_UNKNOWN

public static final Time LATENCY_UNKNOWN
Returned by getStartLatency.

Unrealized

public static final int Unrealized
Returned by getState.

Realizing

public static final int Realizing
Returned by getState.

Realized

public static final int Realized
Returned by getState.

Prefetching

public static final int Prefetching
Returned by getState.

Prefetched

public static final int Prefetched
Returned by getState.

Started

public static final int Started
Returned by getState.
Method Detail

getState

public int getState()
Get the current state of this Controller. The state is an integer constant as defined above.

Note: A race condition can occur between the return of this method and the execution of a state changing method.

Returns:
The Controller's current state.

getTargetState

public int getTargetState()
Get the current target state of this Controller. The state is an integer constant as defined above.

Note: A race condition can occur between the return of this method and the execution of a state changing method.

Returns:
The Controller's current target state.

realize

public void realize()
Construct the media dependent portions of the Controller. This may include examining media data and might take some time to complete.

The realize method puts the Controller into the Realizing state and returns immediately. When realize is complete and the Controller is in the Realized state, the Controller posts a RealizeCompleteEvent.


prefetch

public void prefetch()
Process as much data as necessary to reduce the Controller's start latency to the shortest possible time. This typically involves examining media data and takes some time to complete.

The prefetch method puts the Controller into the Prefetching state and returns immediately. When Prefetching is complete and the Controller is in the Prefetched state, the Controller posts a PrefetchCompleteEvent.


deallocate

public void deallocate()
Abort the current operation and cease any activity that consumes system resources. If a Controller is not yet Realized, it returns to the Unrealized state. Otherwise, the Controller returns to the Realized state.

It is illegal to call deallocate on a Started Controller. A ClockStartedError is thrown if deallocate is called and the Controller is in the Started state.


close

public void close()
Release all resources and cease all activity. The close method indicates that the Controller will no longer be used and can shut itself down. A ControllerClosedEvent is posted. Methods invoked on a closed Controller might throw errors.

getStartLatency

public Time getStartLatency()
Get the Controller's start latency in nanoseconds. The start latency represents a worst-case estimate of the amount of time it will take to present the first frame of data.

This method is useful for determining how far in advance the syncStart method must be invoked to ensure that media will be rendered at the specified start time.

For a Controller that has a variable start latency, the value returned represents the maximum possible start latency. If you call getStartLatency on a Controller that isn't Prefetched and getStartLatency returns LATENCY_UNKNOWN, calling prefetch and then calling getStartLatency again after the Controller posts a PrefetchCompleteEvent might return a more accurate estimate. If getStartLatency still returns LATENCY_UNKNOWN, the start latency is indeterminate and you might not be able to use syncStart to synchronize the Controller with other Controllers.

Note: In most cases, the value returned by getStartLatency will change once the Controller is Prefetched.

Returns:
The time it will take before the first frame of media can be presented.

getControls

public Control[] getControls()
Get a list of the Control objects supported by this Controller. If there are no controls, an array of length zero is returned.
Returns:
A list of Controller Controls.

getControl

public Control getControl(java.lang.String forName)
Get the Control that supports the specified class or interface. The full class or interface name should be specified. Null is returned if the Control is not supported.
Returns:
Control for the class or interface name.

addControllerListener

public void addControllerListener(ControllerListener listener)
Specify a ControllerListener to which this Controller will send events. A Controller can have multiple ControllerListeners.
Parameters:
listener - The listener to which the Controller will post events.

removeControllerListener

public void removeControllerListener(ControllerListener listener)
Remove the specified listener from this Controller's listener list.
Parameters:
listener - The listener that has been receiving events from this Controller.