Fields Summary |
---|
private static int | pcountglobal player id |
private static Object | idLocklock object |
public int | statethe state of this player |
int | loopCountSetthe loopCount of this player |
int | loopCount |
boolean | EOMthe flag to indicate whether the Player is currently paused at EOM.
If true, the Player will seek back to the beginning when
restarted. |
boolean | loopAfterEOMthe flag to indicate looping after EOM. |
Vector | listenersthis player's playerlisteners |
boolean | listenersModifiedflag shows that "listeners" have been modified while
player is executing callbacks from "listeners". |
PlayerEventQueue | eventQueueAsynchronous event mechanism. |
Object | evtLockevent queue lock obj |
protected int | pIDplayer ID of this player |
private static Hashtable | mplayershastable to map playerID to instances |
private static Hashtable | pstatestable of player states |
private static Hashtable | mtimestable of media times |
protected static final String | pkgNameControl package name |
protected static final String | fpcNameDescription of the Field |
protected static final String | guiNameDescription of the Field |
protected static final String | mdcNameDescription of the Field |
protected static final String | micNameDescription of the Field |
protected static final String | picNameDescription of the Field |
protected static final String | racNameDescription of the Field |
protected static final String | recNameDescription of the Field |
protected static final String | stcNameDescription of the Field |
protected static final String | tecNameDescription of the Field |
protected static final String | tocNameDescription of the Field |
protected static final String | vicNameDescription of the Field |
protected static final String | vocNameDescription of the Field |
protected static final String | rtspNameThis one is not among public JSR135 controls,
seems that this is used only for RTSP PLayer.
But its participation in "search-by-name" slows down
all players that use this array for "getControls()". |
private static final String[] | allCtrlsAn array containing all available controls in Players
extending BasicPlayer.
A player can overwrite this array in order to change the list. |
private static final int[] | allPermissionsAn array containing all needed permissions in Players
extending BasicPlayer.
A player can overwrite this array in order to change the list.
By default it is empty. |
private boolean | isTrustedis set by checkPermissions() to bypass further checks |
private String[] | control_namesarray of controls for a given player |
private int[] | permissionsarray of permissions for a given player |
int | eventQueueSizethe default size of the event queue
can be overridden by descendants |
private boolean | closedDeliveredflag to prevent delivering events after the CLOSED event |
private static MIDletPauseListener | pauseListenerlistener for media events while the midlet is in paused state. |
private static boolean | vmPaused |
InputStream | source |
public static final int | AUDIO_NONE |
public static final int | AUDIO_PCM |
public static final int | AUDIO_MIDI |
Methods Summary |
---|
public void | addPlayerListener(PlayerListener playerListener)
chkClosed(false);
if (playerListener != null) {
/*
* Excplicit "sync" is needed to raise "modified" flag.
* Implicit "sync" is already inside addElemet() method,
* so second sync from the same thread will do nothing ...
*/
synchronized (listeners) {
listenersModified = true;
listeners.addElement(playerListener);
}
}
|
protected final void | checkPermissions()Checks if user application has all permissions needed to access player
/*
if (isTrusted) return;
//TBD: check locator-specific permissions ?
for (int i = 0; i < permissions.length; ++i)
PermissionAccessor.checkPermissions(permissions[i]);
isTrusted = true;
*/
|
protected final void | chkClosed(boolean unrealized)Check to see if the Player is closed. If the
unrealized boolean flag is true, check also to
see if the Player is UNREALIZED.
/*
* This method is indended to be called from synchronized methods
* (that change player's state), but in fact
* it is invoked from unsynchronized methods too,
* so, as a temporary solution,
* it shall eliminate access to player's state:
* it must get the state only once and then work with a local variable.
*/
int theState = this.state;
if (theState == CLOSED || (unrealized && theState == UNREALIZED)) {
throw new IllegalStateException("Can't invoke the method at the " +
(theState == CLOSED ? "closed" : "unrealized") +
" state ");
}
|
public synchronized void | close()
//System.out.println("DEBUG: about to BP.close() for player=" + this);
if (state == CLOSED) {
return;
}
deallocate();
doClose();
state = CLOSED;
sendEvent(PlayerListener.CLOSED, null);
mplayers.remove(new Integer(pID));
|
public synchronized void | deallocate()
//System.out.println("DEBUG: about to BP.deallocate() for player=" + this);
chkClosed(false);
loopAfterEOM = false;
if (state < PREFETCHED) {
return;
}
if (state == STARTED) {
try {
stop();
} catch (MediaException e) {
// Not much we can do here.
// e.printStackTrace();
}
}
doDeallocate();
EOM = true;
state = REALIZED;
|
protected abstract void | doClose()Subclasses need to implement this to close
the Player .
|
protected abstract void | doDeallocate()Subclasses need to implement this to deallocate
the Player .
|
synchronized void | doFinishLoopIteration()
//System.out.println("DEBUG: about to BP.doFinishLoopIteration() for player=" + this);
EOM = true;
loopAfterEOM = false;
if (state > Player.PREFETCHED) {
state = Player.PREFETCHED;
if (loopCount > 1 || loopCount == -1) {
loopAfterEOM = true;
}
}
//System.out.println("DEBUG: finished BP.doFinishLoopIteration() for player=" + this);
|
protected abstract Control | doGetControl(java.lang.String type)The worker method to actually obtain the control.
|
protected abstract long | doGetDuration()Subclasses need to implement this to get the duration
of the Player .
|
protected abstract long | doGetMediaTime()Subclasses need to implement this to get the media time
of the Player
|
synchronized void | doNextLoopIteration()Description of the Method
//System.out.println("DEBUG: about to BP.doNextLoopIteration() for player=" + this);
if (loopAfterEOM) {
// If a loop count is set, we'll loop back to the beginning.
if ((loopCount > 1) || (loopCount == -1)) {
try {
if (setMediaTime(0) == 0) {
if (loopCount > 1) {
loopCount--;
}
start();
} else {
loopCount = 1;
}
} catch (MediaException ex) {
loopCount = 1;
}
} else if (loopCountSet > 1) {
loopCount = loopCountSet;
}
loopAfterEOM = false;
}
//System.out.println("DEBUG: finished BP.doNextLoopIteration() for player=" + this);
|
protected void | doPostStart()Subclasses can override this method to do the actual starting
of worker threads.
|
protected abstract void | doPrefetch()Subclasses need to implement this to prefetch
the Player .
|
protected abstract void | doRealize()Subclasses need to implement this to realize
the Player .
|
public int | doSetLevel(int ll)Implementation method for VolumeControl
return ll;
|
protected void | doSetLoopCount(int count)Description of the Method
|
protected abstract long | doSetMediaTime(long now)Subclasses need to implement this to set the media time
of the Player .
|
protected abstract boolean | doStart()Subclasses need to implement this start
the Player .
|
protected abstract void | doStop()Subclasses need to implement this to realize
the Player .
|
public static com.sun.mmedia.ABBBasicPlayer | get(int pid)For global PlayerID management
return (ABBBasicPlayer) (mplayers.get(new Integer(pid)));
|
public int | getAudioType()
return AUDIO_NONE;
|
public java.lang.String | getContentType()
chkClosed(true);
return "";
|
public final Control | getControl(java.lang.String type)Gets 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.
chkClosed(true);
if (type == null) {
throw new IllegalArgumentException();
}
// Prepend the package name if the type given does not
// have the package prefix.
if (type.indexOf('.") < 0) {
// for non-fully qualified control names,
// look up the package in the allCtrls array
for (int i = 0; i < allCtrls.length; i++) {
if (allCtrls[i].equals(type)) {
// standard controls are specified
// without package name in allCtrls
return doGetControl(pkgName + type);
} else if (allCtrls[i].endsWith(type)) {
// non-standard controls are with
// full package name in allCtrls
return doGetControl(allCtrls[i]);
}
}
}
return doGetControl(type);
|
public final Control[] | getControls()Gets the controls attribute of the BasicPlayer object
chkClosed(true);
Vector v = new Vector(3);
// average maximum number of controls
for (int i = 0; i < control_names.length; i++) {
Object c = getControl(control_names[i]);
if ((c != null) && !v.contains(c)) {
v.addElement(c);
}
}
Control[] ret = new Control[v.size()];
v.copyInto(ret);
return ret;
|
public long | getDuration()
//System.out.println("DEBUG: about to BP.getDuration() for player=" + this);
chkClosed(false);
return doGetDuration();
|
public long | getMediaTime()
//System.out.println("DEBUG: about to BP.getMediaTime() for player=" + this);
chkClosed(false);
return doGetMediaTime();
|
public java.lang.Object | getOutput() return null;
|
public int | getState()
return state;
|
private void | init()
synchronized (idLock) {
pcount = (pcount + 1) % 32767;
pID = pcount;
}
mplayers.put(new Integer(pID), this);
|
public boolean | initFromURL(java.lang.String encodings)Initializes Player by Media Encodings obtained from URI and parsed.
To be called by Manager when new player (from URI) is being created.
return true;
|
final void | notifyListeners(java.lang.String message, java.lang.Object obj)
Object copy[];
synchronized (listeners) {
copy = new Object[listeners.size()];
listeners.copyInto(copy);
listenersModified = false;
}
/*
* TBD: raise a flag to show that we are in callbacks
* to detect re-entrance ...
* (syncState object can also be used,
* however it protects state changes too)
*/
for (int i = 0; i < copy.length; i++) {
PlayerListener listener = (PlayerListener)copy[i];
listener.playerUpdate(this, message, obj);
}
/*
* TBD: need to check for "listenersModified == true",
* this means that one of callbacks updated listeners ->
* need some actions ...
*/
|
public static void | notifyPauseListener(java.lang.String msg)
if (vmPaused && pauseListener != null) {
pauseListener.reportActivity(msg);
}
|
public static void | pauseAll()Pauses and deallocates all media players.
After this call all players are either in realized
or unrealized state.
Resources are being released during deallocation.
//System.out.println("DEBUG: about to BP.pauseAll()");
if (mplayers == null) {
return;
}
for (Enumeration e = mplayers.elements(); e.hasMoreElements();) {
ABBBasicPlayer p = (ABBBasicPlayer) e.nextElement();
int state = p.getState();
long time = p.getMediaTime();
// save the player's state
pstates.put(p, new Integer(state));
// save the player's media time
mtimes.put(p, new Long(time));
// deallocate the player
//
// this will implicitly stop all players
// and release scarce resources such as
// the audio device
p.deallocate();
}
|
public static void | pauseStateEntered(MIDletPauseListener listener, boolean paused)Informs the BasicPlayer that the VM has been paused if
paused is set to true - or resumed if paused is set to false
//System.out.println("DEBUG: about to BP.pauseStateEntered(" + listener + "," + paused + ")");
// if the listeners don't match then simply return
if (listener != pauseListener) return;
vmPaused = paused;
if (vmPaused) {
for (Enumeration e = mplayers.elements(); e.hasMoreElements();) {
ABBBasicPlayer p = (ABBBasicPlayer)e.nextElement();
if (p.getState() == STARTED) {
notifyPauseListener("Player");
}
}
/*pauseAll();
} else {
resumeAll();*/
}
|
public synchronized void | prefetch()
//System.out.println("DEBUG: about to BP.prefetch() for player=" + this);
chkClosed(false);
if (state >= PREFETCHED) {
return;
}
if (state < REALIZED) {
realize();
} else {
//if realize has been called the permission will be checked from there
checkPermissions();
}
doPrefetch();
state = PREFETCHED;
|
public synchronized void | realize()
//System.out.println("DEBUG: about to BP.realize() for player=" + this);
chkClosed(false);
if (state >= REALIZED) {
return;
}
doRealize();
state = REALIZED;
|
public void | removePlayerListener(PlayerListener playerListener)
chkClosed(false);
if (playerListener != null) {
/*
* Excplicit "sync" is needed to raise "modified" flag.
* Implicit "sync" is already inside removeElemet() method,
* so second sync from the same thread will do nothing ...
*/
synchronized (listeners) {
listenersModified = true;
listeners.removeElement(playerListener);
}
}
|
public static void | resumeAll()Resumes all media players' activities.
Players that were in STARTED state when pause
was called will resume playing at the media time
they were stopped and deallocated.
//System.out.println("DEBUG: about to BP.resumeAll()");
if (mplayers == null || pstates.size() == 0) {
return;
}
for (Enumeration e = mplayers.elements(); e.hasMoreElements();) {
ABBBasicPlayer p = (ABBBasicPlayer) e.nextElement();
int state = ((Integer) pstates.get(p)).intValue();
long time = ((Long) mtimes.get(p)).longValue();
switch (state) {
case Player.PREFETCHED:
try {
//System.out.println("DEBUG: BP.resumeAll() for PREFETCHED player=" + p);
p.prefetch();
p.setMediaTime(time);
} catch (MediaException ex) {
}
break;
case Player.STARTED:
try {
//System.out.println("DEBUG: BP.resumeAll() for STARTED player=" + p);
p.realize();
p.prefetch();
p.setMediaTime(time);
p.start();
} catch (MediaException ex) {
}
break;
}
}
// clear player states and media times
pstates.clear();
mtimes.clear();
|
public void | sendEvent(java.lang.String evtName, java.lang.Object evtData)Description of the Method
//System.out.println("DEBUG: about to BP.sendEvent(" + evtName + "," + evtData +") for player=" + this);
// There's always one listener for EOM - itself (for loop procesing).
// "Deliver" the CLOSED/ERROR events
// so that the eventQueue thread may terminate
if (listeners.size() == 0 &&
evtName != PlayerListener.END_OF_MEDIA &&
evtName != PlayerListener.CLOSED &&
evtName != PlayerListener.ERROR) {
return;
}
// Safeguard against sending events after CLOSED event to avoid
// deadlock in event delivery thread.
if (closedDelivered) {
return;
}
// Deliver the event to the listeners.
synchronized (evtLock) {
if (eventQueue == null) {
eventQueue = new PlayerEventQueue(this);
}
// TBD: attempt to ensure "eventQueue" existence
// in eventQueue.sentEvent() call ...
eventQueue.sendEvent(evtName, evtData);
}
if (evtName == PlayerListener.CLOSED ||
evtName == PlayerListener.ERROR) {
closedDelivered = true;
}
|
public synchronized void | setLoopCount(int count)
//System.out.println("DEBUG: about to BP.setLoopCount(" + count + ") for player=" + this);
chkClosed(false);
if (state == STARTED) {
throw new IllegalStateException("setLoopCount");
}
if (count == 0 || count < -1) {
throw new IllegalArgumentException("setLoopCount");
}
loopCountSet = count;
loopCount = count;
doSetLoopCount(count);
|
public static void | setMIDletPauseListener(MIDletPauseListener listener)Sets the listener for media activity notifications.
This interface can only be set once and shall only be used
by MIDletState.
//System.out.println("DEBUG: about to BP.setMIDletPauseListener(" + listener + ")");
// Only set the listener once!
// If the listener is aleady set then return witout waring.
if (pauseListener == null) {
pauseListener = listener;
}
|
public synchronized long | setMediaTime(long now)
//System.out.println("DEBUG: about to BP.setMediaTime(" + now + ") for player=" + this);
chkClosed(true);
long theDur = doGetDuration();
if ((theDur != TIME_UNKNOWN) && (now > theDur)) {
now = theDur;
}
long rtn = doSetMediaTime(now);
EOM = false;
//System.out.println("DEBUG: finished BP.setMediaTime(" + now + ")=" + rtn + " for player=" + this);
return rtn;
|
public void | setOutput(java.lang.Object output)
|
public void | setSource(java.io.InputStream source)
this.source = source;
|
public synchronized void | start()
//System.out.println("DEBUG: about to BP.start() for player=" + this + " at time=" + getMediaTime());
chkClosed(false);
if (state >= STARTED) {
return;
}
if (state < PREFETCHED) {
prefetch();
} else {
//If prefetch has been called the permission will be checked from there
if(!EOM && !loopAfterEOM) {
checkPermissions();
}
}
// If it's at the EOM, it will automatically
// loop back to the beginning.
if (EOM)
try {
setMediaTime(0);
} catch (MediaException me) {
// Ignore, if setting media time is not supported
}
if (!doStart()) {
throw new MediaException("start");
}
state = STARTED;
sendEvent(PlayerListener.STARTED, new Long(getMediaTime()));
// Finish any pending startup stuff in subclass
// Typically used to start any threads that might potentially
// generate events before the STARTED event is delivered
doPostStart();
//System.out.println("DEBUG: finished BP.start() for player=" + this);
|
public synchronized void | stop()
//System.out.println("DEBUG: about to BP.stop() for player=" + this + " at time=" + getMediaTime());
chkClosed(false);
loopAfterEOM = false;
if (state < STARTED) {
return;
}
doStop();
state = PREFETCHED;
sendEvent(PlayerListener.STOPPED, new Long(getMediaTime()));
//System.out.println("DEBUG: finished BP.stop() for player=" + this);
|