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 :
-
getTimeBase
-
setTimeBase
-
setMediaTime
-
setRate
-
setStopTime
-
getStartLatency
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 .
|