FileDocCategorySizeDatePackage
BasicPlayer.javaAPI DocJ2ME MIDP 2.029622Thu Nov 07 12:02:26 GMT 2002com.sun.mmedia

BasicPlayer

public abstract class BasicPlayer extends Object implements Player, VolumeControl
BasicPlayer provides basic implementation for the Player methods. Many of the methods call do<method> to do the actual work that can be overridden by subclasses.

Fields Summary
private static int
pcount
global player id
private static Hashtable
mplayers
hastable to map playerID to instances
private static Object
idLock
lock object
private String
locator
the locator of this player
int
state
the state of this player
int
loopCountSet
the loopCount of this player
int
loopCount
boolean
EOM
the flag to indicate whether the Player is currently paused at EOM. If true, the Player will seek back to the beginning when restarted.
boolean
loopAfterEOM
the flag to indicate looping after EOM.
Vector
listeners
this player's playerlisteners
EvtQ
evtQ
Asynchronous event mechanism.
Object
evtLock
event queue lock obj
protected int
pID
player ID of this player
private int
level
volume level
private boolean
mute
mute state
protected InputStream
stream
the source input stream of this player
long
location
the current position in source stream
Constructors Summary
public BasicPlayer()
the default constructor


            
      
	synchronized (idLock) {
	    pcount = (pcount+1) % 32767;
	    pID = pcount;
	}
	mplayers.put(new Integer(pID), this);
    
Methods Summary
public voidaddPlayerListener(PlayerListener playerListener)
Add a player listener for this player.

param
playerListener the listener to add. If null is used, the request will be ignored.
exception
IllegalStateException Thrown if the Player is in the CLOSED state.
see
#removePlayerListener

	chkClosed(false);
	if (playerListener != null)
	    listeners.addElement(playerListener);
    
protected voidchkClosed(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.

param
unrealized the flag whether to check the unrealized state.

	if (state == CLOSED || (unrealized && state == UNREALIZED)) { 
	    throw new IllegalStateException("The Player is " +
			(state == CLOSED ? "closed" : "unrealized"));
	}
    
public synchronized voidclose()
Close the Player and release its resources.

When the method returns, the Player is in the CLOSED state and can no longer be used. A CLOSED event will be delivered to the registered PlayerListeners.

If close is called on a closed Player the request is ignored.

	if (state == CLOSED)
	    return;
	
	deallocate();
	doClose();

	state = CLOSED;
	try {
	    if (stream != null)
		stream.close();
	} catch (IOException e) { }
	sendEvent(PlayerListener.CLOSED, null);
	mplayers.remove(new Integer(pID));
    
public synchronized voiddeallocate()
Release the scarce or exclusive resources like the audio device acquired by the Player.

When deallocate returns, the Player is in the UNREALIZED or REALIZED state.

If the Player is blocked at the realize call while realizing, calling deallocate unblocks the realize call and returns the Player to the UNREALIZED state. Otherwise, calling deallocate returns the Player to the REALIZED state.

If deallocate is called when the Player is in the UNREALIZED or REALIZED state, the request is ignored.

If the Player is STARTED when deallocate is called, deallocate will implicitly call stop on the Player.

exception
IllegalStateException Thrown if the Player is in the CLOSED state.

	chkClosed(false);

	loopAfterEOM = false;
	
	if (state < PREFETCHED)
	    return;

	if (state == STARTED)
	    stop();

	doDeallocate();
	state = REALIZED;
    
protected abstract voiddoClose()
the worker method to close the player

protected abstract voiddoDeallocate()
the worker method to deallocate the player

protected abstract ControldoGetControl(java.lang.String type)
The worker method to actually obtain the control.

param
type the class name of the Control.
return
Control for the class or interface name.

protected abstract longdoGetDuration()
The actual worker method to retrieve the duration.

return
A long object representing the duration or TIME_UNKNWON.

protected abstract longdoGetMediaTime()
The actual worker method to gets this player's current media time in microseconds.

return
The current media time in microseconds.

synchronized voiddoLoop()
the worker method to deliver EOM event


	// 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;
    
protected abstract voiddoPrefetch()
the worker method to prefetch the player

protected abstract voiddoRealize()
The worker method to realize the player.

protected abstract intdoSetLevel(int vol)
The worker method to actually obtain the control.

param
vol the volume level to be set.
return
the actual level has been set.

protected abstract longdoSetMediaTime(long now)
The worker method to actually set player's media time.

param
now The new media time in microseconds.
return
The actual media time set in microseconds.
exception
MediaException Thrown if an error occurs while setting the media time.

protected abstract booleandoStart()
The worker method to actually start the player

return
Whether the player is successfully started

protected abstract voiddoStop()
the worker method to stop the player

public static com.sun.mmedia.BasicPlayerget(int pid)
Obtain a BasicPlayer instance based on the global id.

param
pid the given global id.
return
the instance of BasicPlayer associated with given global id

	return (BasicPlayer)(mplayers.get(new Integer(pid)));
    
public ControlgetControl(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.

param
type the class name of the Control.
return
Control for the class or interface name.

	chkClosed(true);

	// Prepend the package name if the type given does not
	// have the package prefix.
	if (type.indexOf('.") < 0)
	    return doGetControl("javax.microedition.media.control." + type);
	
	return doGetControl(type);
    
public Control[]getControls()
Obtain the collection of Controls from this player.

return
the collection of Control objects.

	chkClosed(true);
	return new Control[] { this };
    
public longgetDuration()
Get the duration of the media. The value returned is the media's duration when played at the default rate.
If the duration cannot be determined (for example, the Player is presenting live media) getDuration returns TIME_UNKNOWN.

return
The duration in microseconds or TIME_UNKNOWN.
exception
IllegalStateException Thrown if the Player is in the CLOSED state.

	chkClosed(false);
	return doGetDuration();
    
public intgetLevel()
Get the current volume set for this player.

return
The volume in the level scale (0-100).

	return level;
    
public longgetMediaTime()
Gets this Player's current media time. If the media time cannot be determined, getMediaTime returns TIME_UNKNOWN.

return
The current media time in microseconds or TIME_UNKNOWN.
exception
IllegalStateException Thrown if the Player is in the CLOSED state.
see
#setMediaTime

	chkClosed(false);
	return doGetMediaTime();
    
public intgetState()
Gets the current state of this Player. The possible states are: UNREALIZED, REALIZED, PREFETCHED, STARTED, CLOSED.

return
The Player's current state.

	/**
	 * A race condition can occur between
	 * the return of this method and the execution of
	 * a state changing method.
	 */
	return state;
    
protected longgetStrmLoc()
Get the current position of the source stream

return
the current position.

	return location;
    
public booleanisMuted()
Check if this player is muted.

return
The mute state.

	return mute;
    
private voidopenConnection()
establish the connection with the source.

	try {
	    HttpConnection httpCon = (HttpConnection)Connector.open(locator);
	    int rescode = httpCon.getResponseCode();
	    // both 4XX and 5XX are error codes
	    if (rescode >= 400) {
		httpCon.close();
		throw new IOException("bad url");
	    } else {
		stream = httpCon.openInputStream();
		String ctype = httpCon.getType();
		boolean supportedCT = false;
		if (locator.endsWith(".wav")) {
		    supportedCT = true;
		} else if (ctype != null && 
			   ctype.toLowerCase().equals("audio/x-wav")) {
		    supportedCT = true;
		}
		    
		httpCon.close();

		if (!supportedCT) {
		    stream.close();
		    stream =  null;
		    throw new MediaException("unsupported media type");
		}
	    }
	} catch (IOException ioex) {
	    throw ioex;
	} catch (MediaException mex) {
	    throw mex;
	} catch (Exception ex) {
	    new IOException(ex.getMessage() + " failed to connect");
	}

	location = 0;
    
public synchronized voidprefetch()
Acquires the scarce and exclusive resources and processes as much data as necessary to reduce the start latency.

When prefetch completes successfully, the Player is in the PREFETCHED state.

If prefetch is called when the Player is in the UNREALIZED state, it will implicitly call realize.

If prefetch is called when the Player is already in the PREFETCHED state, the Player may still process data necessary to reduce the start latency. This is to guarantee that start latency can be maintained at a minimum.

If prefetch is called when the Player is in the STARTED state, the request will be ignored.

If the Player cannot obtain all of the resources it needs, it throws a MediaException. When that happens, the Player will not be able to start. However, prefetch may be called again when the needed resource is later released perhaps by another Player or application.

exception
IllegalStateException Thrown if the Player is in the CLOSED state.
exception
MediaException Thrown if the Player cannot be prefetched.
exception
SecurityException Thrown if the caller does not have security permission to prefetch the Player.

	chkClosed(false);

	if (state >= PREFETCHED)
	    return;

	if (state < REALIZED)
	    realize();
		
	doPrefetch();

	state = PREFETCHED;
    
protected intreadStrm(byte[] buffer, int offset, int length)
Read a data buffer from source stream.

param
buffer the byte array to hold the read data
param
offset the offset of byte array.
param
length the maximum bytes to be read
return
the actual number of bytes have been read

	int len = stream.read(buffer, offset, length);
	if (len > 0)
	    location += len;
	return len;
    
public synchronized voidrealize()
Constructs portions of the Player without acquiring the scarce and exclusive resources. This may include examining media data and may take some time to complete.

When realize completes successfully, the Player is in the REALIZED state.

If realize is called when the Player is in the REALIZED, PREFETCHTED or STARTED state, the request will be ignored.

exception
IllegalStateException Thrown if the Player is in the CLOSED state.
exception
MediaException Thrown if the Player cannot be realized.
exception
SecurityException Thrown if the caller does not have security permission to realize the Player.

	chkClosed(false);

	if (state >= REALIZED)
	    return;

	doRealize();
	state = REALIZED;
    
public voidremovePlayerListener(PlayerListener playerListener)
Remove a player listener for this player.

param
playerListener the listener to remove. If null is used or the given playerListener is not a listener for this Player, the request will be ignored.
exception
IllegalStateException Thrown if the Player is in the CLOSED state.
see
#addPlayerListener

	chkClosed(false);
	listeners.removeElement(playerListener);
    
private voidreopenStrm()
Re-open the source stream.

exception
if an error occurs.

	try {
	    stream.reset();
	    return;
	} catch (IOException ex) {
	    if (locator == null)
		throw ex;
	}

	try {
	    stream.close();
	    stream = null;
	} catch (IOException e) {}

	
	openConnection();
    
protected longseekStrm(long where)
In source stream, seek to a particular position

param
where the position intended to seek to.
return
the actual position seeked to.
exception
an error occurs during the seeking

	if (stream == null)
	    return location;
	long skipped, oldLocation = location;
	if (where < oldLocation) { // seek backward
	    reopenStrm();
	    location = 0;
	    skipped = stream.skip(where);
	} else  {
	    skipped = stream.skip((where - oldLocation));
	}

	if (skipped > 0)
	    location += skipped;

	return location;
    
public voidsendEvent(java.lang.String evt, java.lang.Object evtData)
Deliver the events to the player listeners.

param
evt the evt type
param
evtData the data associated with this event.


	//  There's always one listener for EOM -- itself.
	if (listeners.size() == 0 && evt != PlayerListener.END_OF_MEDIA)
	    return;

	// Deliver the event to the listeners.
	synchronized (evtLock) {
	    if (evtQ == null)
		evtQ = new EvtQ(this);
	    evtQ.sendEvent(evt, evtData);
	}
    
public intsetLevel(int ll)
Set the volume using a linear point scale 0 to 100.

param
ll The new volume specified in the level scale.
return
The level that was actually set.

	int newl;

	if (ll < 0) {
	    ll  = 0;
	} else if (ll > 100) {
	    ll = 100;
	} 

	if (!mute) {
	    newl = doSetLevel(ll);
	    if (newl != level) {
		level = newl;
		sendEvent(PlayerListener.VOLUME_CHANGED, this);
	    }
	}
	return level;
    
public voidsetLocator(java.lang.String locator, boolean con)
Set the locator of this player.

param
locator the locator to be set.
param
con the flag if to make the connection

	this.locator = locator;
	if (con)
	    openConnection();
    
public voidsetLoopCount(int count)
Set the number of times the Player will loop and play the content.

By default, the loop count is one. That is, once started, the Player will start playing from the current media time to the end of media once.

If the loop count is set to N where N is bigger than one, starting the Player 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.

Setting the loop count to 0 is invalid. An IllegalArgumentException will be thrown.

Setting the loop count to -1 will loop and play the content indefinitely.

If the Player is stopped before the preset loop count is reached either because stop is called, calling start again will resume the looping playback from where it was stopped until it fully reaches the preset loop count.

An END_OF_MEDIA event will be posted every time the Player reaches the end of media. If the Player loops back to the beginning and starts playing again because it has not completed the loop count, a STARTED 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 Player is in the STARTED or CLOSED state.

	chkClosed(false);
	if (state == STARTED)
	    throw new IllegalStateException("setLoopCount");
	if (count == 0 || count < -1)
	    throw new IllegalArgumentException("setLoopCount");
	loopCountSet = count;
	loopCount = count;
    
public synchronized longsetMediaTime(long now)
Sets the Player's media time.

For some media types, setting the media time may not be very accurate. The returned value will indicate the actual media time set.

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.

There are some media types that cannot support the setting of media time. Calling setMediaTime will throw a MediaException in those cases.

param
now The new media time in microseconds.
return
The actual media time set in microseconds.
exception
IllegalStateException Thrown if the Player is in the UNREALIZED or CLOSED state.
exception
MediaException Thrown if the media time cannot be set.
see
#getMediaTime

	chkClosed(true);

	if (now < 0)
	    now = 0;
	
	long theDur = getDuration();
	if ((theDur != TIME_UNKNOWN) && (now > theDur))
	    now = theDur;

	long rtn = doSetMediaTime(now);
	EOM = false;

	return rtn;
    
public voidsetMute(boolean mute)
set player mute.

param
mute the flag to mute the player or not


                                  

        

                      
        
	if (mute && !this.mute) {
	    doSetLevel(0);
	    this.mute = true;
	    sendEvent(PlayerListener.VOLUME_CHANGED, this);
	} else if (!mute && this.mute) {
	    this.level = doSetLevel(level);
	    this.mute = false;
	    sendEvent(PlayerListener.VOLUME_CHANGED, this);
	}
    
public voidsetStrm(java.io.InputStream stream)
Set the input stream of this player.

param
stream the input stream to be set.

	this.stream = stream;
    
protected longskipStrm(int numBytes)
This is a skip fully method

param
numBytes the number of bytes intended to skip.
return
the actual number of bytes has been skipped.
exception
if an error occurs or skipped bytes is less then the intended numBytes.

	long skipped = stream.skip(numBytes);
	if (skipped > 0)
	    location += skipped;
	if (skipped < numBytes)
	    throw new IOException("skipped over eom");
	return (skipped);
    
public synchronized voidstart()
Starts the Player as soon as possible. If the Player was previously stopped by calling stop, it will resume playback from where it was previously stopped. If the Player has reached the end of media, calling start will automatically start the playback from the start of the media.

When start returns successfully, the Player must have been started and a STARTED event will be delivered to the registered PlayerListeners. However, the Player is not guaranteed to be in the STARTED state. The Player may have already stopped (in the PREFETCHED state) because the media has 0 or a very short duration.

If start is called when the Player is in the UNREALIZED or REALIZED state, it will implicitly call prefetch.

If start is called when the Player is in the STARTED state, the request will be ignored.

exception
IllegalStateException Thrown if the Player is in the CLOSED state.
exception
MediaException Thrown if the Player cannot be started.
exception
SecurityException Thrown if the caller does not have security permission to start the Player.

	chkClosed(false);

	if (state >= STARTED)
	    return;

	if (state < REALIZED)
	    realize();

	if (state < PREFETCHED)
	    prefetch();

	// If it's at the EOM, it will automatically
	// loop back to the beginning.
	if (EOM)
	    setMediaTime(0);

	if (!doStart())
	    throw new MediaException("start");

	state = STARTED;
	sendEvent(PlayerListener.STARTED, new Long(getMediaTime()));
    
public synchronized voidstop()
Stops the Player. It will pause the playback at the current media time.

When stop returns, the Player is in the PREFETCHED state. A STOPPED event will be delivered to the registered PlayerListeners.

If stop is called on a stopped Player, the request is ignored.

exception
IllegalStateException Thrown if the Player is in the CLOSED state.

	chkClosed(false);

	loopAfterEOM = false;
	
	if (state < STARTED)
	    return;

	doStop();

	state = PREFETCHED;
	sendEvent(PlayerListener.STOPPED, new Long(getMediaTime()));