FileDocCategorySizeDatePackage
ABBBasicPlayer.javaAPI DocphoneME MR2 API (J2ME)35785Wed May 02 18:00:46 BST 2007com.sun.mmedia

ABBBasicPlayer

public abstract class ABBBasicPlayer extends Object implements Player
BasicPlayer provides basic implementation for the Player methods. Many of the methods call do to do the actual work that can be overridden by subclasses.
created
January 13, 2005

Fields Summary
private static int
pcount
global player id
private static Object
idLock
lock object
public 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
boolean
listenersModified
flag shows that "listeners" have been modified while player is executing callbacks from "listeners".
PlayerEventQueue
eventQueue
Asynchronous event mechanism.
Object
evtLock
event queue lock obj
protected int
pID
player ID of this player
private static Hashtable
mplayers
hastable to map playerID to instances
private static Hashtable
pstates
table of player states
private static Hashtable
mtimes
table of media times
protected static final String
pkgName
Control package name
protected static final String
fpcName
Description of the Field
protected static final String
guiName
Description of the Field
protected static final String
mdcName
Description of the Field
protected static final String
micName
Description of the Field
protected static final String
picName
Description of the Field
protected static final String
racName
Description of the Field
protected static final String
recName
Description of the Field
protected static final String
stcName
Description of the Field
protected static final String
tecName
Description of the Field
protected static final String
tocName
Description of the Field
protected static final String
vicName
Description of the Field
protected static final String
vocName
Description of the Field
protected static final String
rtspName
This 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[]
allCtrls
An 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[]
allPermissions
An 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
isTrusted
is set by checkPermissions() to bypass further checks
private String[]
control_names
array of controls for a given player
private int[]
permissions
array of permissions for a given player
int
eventQueueSize
the default size of the event queue can be overridden by descendants
private boolean
closedDelivered
flag to prevent delivering events after the CLOSED event
private static MIDletPauseListener
pauseListener
listener 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
Constructors Summary
public ABBBasicPlayer()
Constructor for the ABBBasicPlayer object

        init();
        control_names = allCtrls;
        permissions = allPermissions;
    
protected ABBBasicPlayer(String[] n, int[] p)

        init();
        control_names = (n == null) ? allCtrls : n;
        permissions = (p == null) ? allPermissions : p;
    
Methods Summary
public voidaddPlayerListener(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 voidcheckPermissions()
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 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 Description of the Parameter

        /*
         * 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 voidclose()

        //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 voiddeallocate()

        //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 voiddoClose()
Subclasses need to implement this to close the Player.

protected abstract voiddoDeallocate()
Subclasses need to implement this to deallocate the Player.

synchronized voiddoFinishLoopIteration()

        //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 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()
Subclasses need to implement this to get the duration of the Player.

return
Description of the Return Value

protected abstract longdoGetMediaTime()
Subclasses need to implement this to get the media time of the Player

return
Description of the Return Value

synchronized voiddoNextLoopIteration()
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 voiddoPostStart()
Subclasses can override this method to do the actual starting of worker threads.

    
protected abstract voiddoPrefetch()
Subclasses need to implement this to prefetch the Player.

exception
MediaException Description of the Exception

protected abstract voiddoRealize()
Subclasses need to implement this to realize the Player.

exception
MediaException Description of the Exception

public intdoSetLevel(int ll)
Implementation method for VolumeControl

param
ll Description of the Parameter
return
Description of the Return Value

        return ll;
    
protected voiddoSetLoopCount(int count)
Description of the Method

param
count Description of the Parameter

    
protected abstract longdoSetMediaTime(long now)
Subclasses need to implement this to set the media time of the Player.

param
now Description of the Parameter
return
Description of the Return Value
exception
MediaException Description of the Exception

protected abstract booleandoStart()
Subclasses need to implement this start the Player.

return
Description of the Return Value

protected abstract voiddoStop()
Subclasses need to implement this to realize the Player.

exception
MediaException Description of the Exception

public static com.sun.mmedia.ABBBasicPlayerget(int pid)
For global PlayerID management

param
pid Description of the Parameter
return
Description of the Return Value

        return (ABBBasicPlayer) (mplayers.get(new Integer(pid)));
    
public intgetAudioType()


       
        return AUDIO_NONE;
    
public java.lang.StringgetContentType()

        chkClosed(true);
        return "";
    
public final 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 Description of the Parameter
return
Control for the class or interface name.

        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

return
The controls value

        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 longgetDuration()

        //System.out.println("DEBUG: about to BP.getDuration() for player=" + this);
        chkClosed(false);
        return doGetDuration();
    
public longgetMediaTime()

        //System.out.println("DEBUG: about to BP.getMediaTime() for player=" + this);
        chkClosed(false);
        return doGetMediaTime();
    
public java.lang.ObjectgetOutput()

 return null; 
public intgetState()

        return state;
    
private voidinit()


        synchronized (idLock) {
            pcount = (pcount + 1) % 32767;
            pID = pcount;
        }
        mplayers.put(new Integer(pID), this);
    
public booleaninitFromURL(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.

param
encodings media encodings in form "key=value", separated by '&'.
returns
true if initialization was successful, false otherwise

        return true;
    
final voidnotifyListeners(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 voidnotifyPauseListener(java.lang.String msg)

        if (vmPaused && pauseListener != null) {
            pauseListener.reportActivity(msg);
        }
    
public static voidpauseAll()
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 voidpauseStateEntered(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 voidprefetch()

        //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 voidrealize()

        //System.out.println("DEBUG: about to BP.realize() for player=" + this);
        chkClosed(false);

        if (state >= REALIZED) {
            return;
        }

        doRealize();
        
        state = REALIZED;
    
public voidremovePlayerListener(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 voidresumeAll()
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 voidsendEvent(java.lang.String evtName, java.lang.Object evtData)
Description of the Method

param
evtName Description of the Parameter
param
evtData Description of the Parameter

        //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 voidsetLoopCount(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 voidsetMIDletPauseListener(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 longsetMediaTime(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 voidsetOutput(java.lang.Object output)

 
public voidsetSource(java.io.InputStream source)

        this.source = source;
    
public synchronized voidstart()

        //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 voidstop()

        //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);