javauis/mmapi_qt/baseline/javasrc/com/nokia/microedition/media/animation/AnimationPlayer.java
branchRCL_3
changeset 65 ae942d28ec0e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/mmapi_qt/baseline/javasrc/com/nokia/microedition/media/animation/AnimationPlayer.java	Tue Aug 31 15:09:22 2010 +0300
@@ -0,0 +1,789 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: AnimationPlayer
+*
+*/
+package com.nokia.microedition.media.animation;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.microedition.media.Control;
+import javax.microedition.media.MediaException;
+import javax.microedition.media.PlayerListener;
+import javax.microedition.media.protocol.DataSource;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoader;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Display;
+
+import com.nokia.microedition.media.BufferDataSource;
+import com.nokia.microedition.media.InputStreamDataSource;
+import com.nokia.microedition.media.InputStreamSourceStream;
+import com.nokia.microedition.media.PlayerBase;
+import com.nokia.microedition.media.PlayerListenerImpl;
+
+public class AnimationPlayer extends PlayerBase implements ESWTinitializeListener
+{
+    // GIF image information, array length will be equal to the number of frames in image
+    protected ImageData [] iImageData;
+    // number of times we need to repeat the animation
+    // by default it's value is one
+    private int iTotalLoopCount=1;
+    // HashTable object which contains all control related to this player
+    private Hashtable iControls= new Hashtable();
+    // Current frame index of the Animation file
+    private int iFrameIndex;
+    // Current Loop Count
+    private int iCurrentLoopCount;
+    // Indicates if looping indefinitely
+    private boolean iRepeatForeEver;
+    // Current rate of the player, Used for RateControl
+    // Currently only two mode are supported
+    // paused and default rate
+    private int iCurrentRate;
+    // Display object of the eSWT API, creating this object will integrate the current java code with eSWT API.
+    private Display iDisplay;
+    // Control object of ESWT API, return from LCDUIInvoker.
+    org.eclipse.swt.widgets.Control iControl;
+    // Following constants are used for comparison of the string, throughout the class
+    private static final String ANIMATION_CONTENT_TYPE      = "image/gif";
+    private static final String fVideoControl               = VideoControl.class.getName();
+    private static final String fFramePositioningControl    = FramePositioningControl.class.getName();
+    private static final String fStopTimeControl            = StopTimeControl.class.getName();
+    private static final String fRateControl                = RateControl.class.getName();
+
+    /**
+     * Default control package. Used when getting control with
+     * getControl method which appends default control package if package is
+     * not specified.
+     */
+    private static final String CONTROL_DEFAULT_PACKAGE =
+        "javax.microedition.media.control.";
+
+    //For Player listener
+    protected PlayerListenerImpl iPlayerListenerImpl;
+    //Image to be displayed, an object of eSWT API.
+    protected Image iImage;
+    // Actual dimension of the image, this should be initialized while creating the player
+    // as user can change the size of the image later, in that case too, getSourceheight and getSourceWidth
+    // of VideoControl should return the actual width and height of the image
+    private Point iSourceDimension;
+    // Current dimension of the image, MIDlet developer may change the size of VideoControl
+    private Point iCurrentVideoDimension;
+    // Total time taken so far to player the animation, it keeps updating as player moves
+    private long iMediaTime;
+    // Time at which, player should be stopped
+    // This will set through StopTimeControl.setTime();
+    // otherwise default time is Long.MAX_VALUE
+    //private long iStopTime=Long.MAX_VALUE;
+    AnimationObserver iAnimationObserver;
+
+    // Display Location, of the image
+    // there won't be any use of this, in case of Form(customItem)
+    private Point iDisplayLocation= new Point(0,0);
+    // in case of Canvas(USE_DIRECT_VIDEO) , it should be invisible by default
+    // this is handled in initDisplayMode function, if the mode is USE_DIRECT_VIDEO, we are
+    // changing it to false
+    private boolean iIsControlVisible=true;
+    // we keep the background pixel in it, used while taking the snapshot of the currentframe
+    private int iBackgroundPixel=-1;
+    // Total duration of the player
+    private long iDuration=TIME_UNKNOWN;
+    /**
+     *
+     * @param ds DataSource which contains the data to be displayed
+     * @throws MediaException
+     */
+    public AnimationPlayer(DataSource ds) throws MediaException
+    {
+        iPlayerListenerImpl= new PlayerListenerImpl(this);
+        //TODO check if we can do it in better way
+        // this is temporary solution
+        // for this I have written two functions getDataSource and getInputStream function
+        BufferDataSource bds =(BufferDataSource)ds;
+        InputStreamDataSource isds=(InputStreamDataSource)bds.getDataSource();
+        InputStreamSourceStream isss=(InputStreamSourceStream)isds.getStreams()[0];
+        InputStream is = isss.getInputStream();
+        if (is!=null)
+        {
+            ImageLoader imageLoader= new ImageLoader();
+
+            // If it is any other format other than the image(jpeg, png and gif),
+            // following line will throw the SWT exception
+            iImageData=imageLoader.load(is);
+            // If the image is loaded properly, we need to check whether it is GIF image or not.
+            // It can be PNG and JPEG as well
+            if (iImageData[0].type!=SWT.IMAGE_GIF)
+                throw new MediaException("Could not create player");
+            try
+            {
+                is.close();
+            }
+            catch (IOException e)
+            {
+                e.printStackTrace();
+            }
+            iSourceDimension= new Point(imageLoader.logicalScreenWidth, imageLoader.logicalScreenHeight);
+            iCurrentVideoDimension= new Point(imageLoader.logicalScreenWidth, imageLoader.logicalScreenHeight);
+            iBackgroundPixel= imageLoader.backgroundPixel;
+        }
+        populateControl();
+
+    }
+
+    /**
+     *
+     * @param locator
+     * @throws SWTException
+     */
+    public AnimationPlayer(String locator) throws SWTException, MediaException
+    {
+        ImageLoader imageLoader= new ImageLoader();
+        // If it is any other format other than the image(jpeg, png and gif),
+        // following line will throw the SWT exception
+        iImageData=imageLoader.load(locator);
+        // If the image is loaded properly, we need to check whether it is GIF image or not.
+        // It can be PNG and JPEG as well
+        if (iImageData[0].type!=SWT.IMAGE_GIF)
+            throw new MediaException("Could not create player");
+        iPlayerListenerImpl= new PlayerListenerImpl(this);
+        iSourceDimension= new Point(imageLoader.logicalScreenWidth, imageLoader.logicalScreenHeight);
+        iCurrentVideoDimension= new Point(imageLoader.logicalScreenWidth, imageLoader.logicalScreenHeight);
+        iBackgroundPixel= imageLoader.backgroundPixel;
+        populateControl();
+    }
+
+    /**
+     * Moved the player to close state and releases all resources, called from PlayerBase class
+     */
+    protected void doClose()
+    {
+        // state is already changed in playerbase.close() method
+        //      changePlayerState(CLOSED);
+        iPlayerListenerImpl.postEvent(PlayerListener.CLOSED, null);
+    }
+
+    /**
+     * Called from the PlayerBase class if the Player is in pre-fetched state
+     *
+     */
+    protected void doDeallocate()
+    {
+        //when the player is in pre-fetched state, calling this
+        //function should change the state of the player to RELAIZED state
+        changePlayerState(REALIZED);
+    }
+
+    protected void doPrefetch() throws MediaException
+    {
+        changePlayerState(PREFETCHED);
+        iDuration= getMediaTimeForFrame(getTotalNumberFrames());
+    }
+
+    protected void doRealize() throws MediaException
+    {
+        changePlayerState(REALIZED);
+    }
+
+    /**
+     *
+     */
+    protected void doStop() throws MediaException
+    {
+        // since after stopping the player the player state will move to pre-fetched state
+        changePlayerState(PREFETCHED);
+        //iPlayerListenerImpl.postEvent(PlayerListener.STOPPED, new Long(iMediaTime * 10000));
+        iPlayerListenerImpl.postEvent(PlayerListener.STOPPED, new Long(iMediaTime));
+    }
+
+    /**
+     * Function of InternalPlayer interface
+     */
+    public void addControl(Control aControl, String aControlType)
+    {
+        iControls.put(aControlType, aControl);
+    }
+
+    /**
+     *
+     */
+    public void addPlayerListener(PlayerListener aPlayerListener)
+    {
+        closeCheck();
+        iPlayerListenerImpl.addPlayerListener(aPlayerListener);
+    }
+
+    /**
+     * Returns the Content type("image/GIF") supported for by this player,
+     */
+    public String getContentType()
+    {
+        closeCheck();
+        unrealizedCheck();
+        return ANIMATION_CONTENT_TYPE;
+    }
+
+    /**
+     * This function will return total time in microseconds, this player can be played
+     */
+    public long getDuration()
+    {
+        closeCheck();
+        return iDuration;
+    }
+
+    /**
+     * This returns the total time taken, till now, to play the video.
+     */
+    public long getMediaTime()
+    {
+        closeCheck();
+        return iMediaTime;
+    }
+
+    public int getState()
+    {
+        return iState;
+    }
+
+    /**
+     * Removes the specified playerListner from this player
+     */
+    public void removePlayerListener(PlayerListener aPlayerListener)
+    {
+        closeCheck();
+        iPlayerListenerImpl.removePlayerListener(aPlayerListener);
+    }
+
+    /**
+     *
+     */
+    GC gc = null;
+    public void start() throws MediaException
+    {
+        final String DEBUG_STR = "AnimationPlayer::start()";
+//        final long inTime = System.currentTimeMillis();
+        prefetch();
+        // Only prefetched player may be started. If player is already started
+        // this method returns silently.
+        if (getState() == PREFETCHED)
+        {
+            //initialize();
+            changePlayerState(STARTED);
+            Thread thread = new Thread("Animation")
+            {
+                int loopCount = iCurrentLoopCount;
+                public void run()
+                {
+                    //changePlayerState(STARTED);
+                    final int noOfFrames = iImageData.length;
+                    while (iState == STARTED)
+                    {
+                        final int delayTimeForNextFrame = iImageData[iFrameIndex].delayTime*10000 ;
+                        // Since we are going to display first frame, notify all
+                        // PlayerListener that Player has started
+                        if (iFrameIndex == 0)
+                        {
+                            iMediaTime=0;
+                            iPlayerListenerImpl.postEvent(
+                                PlayerListener.STARTED, new Long(0));
+
+                        }
+                        if (iDisplay != null)
+                        {
+                            iDisplay.syncExec(new Runnable()
+                            {
+                                public void run()
+                                {
+                                    // For out of memory issue in case of full screen, we are scaling the image
+                                    // while displaying it.
+                                    ImageData tempImageData =iImageData[iFrameIndex] ;
+                                    if (iSourceDimension.x!=iCurrentVideoDimension.x || iSourceDimension.x!=iCurrentVideoDimension.x)
+                                    {
+                                        tempImageData = iImageData[iFrameIndex].scaledTo(iCurrentVideoDimension.x , iCurrentVideoDimension.y);
+                                    }
+                                    Image tempImage = new Image(iDisplay,tempImageData);
+                                    //Image tempImage = new Image(iDisplay,iImageData[iFrameIndex]);
+                                    gc.drawImage(tempImage, 0, 0);
+                                    tempImage.dispose();
+                                    iFrameIndex = (iFrameIndex + 1) % noOfFrames;
+                                    if (iControl != null)
+                                    {
+                                        iControl.redraw();
+                                    }
+                                    iMediaTime += delayTimeForNextFrame;
+                                }
+                            });
+                        }
+                        else// if the initDisplayMode is not called yet
+                        {
+                            iFrameIndex = (iFrameIndex + 1) % noOfFrames;
+                            iMediaTime += delayTimeForNextFrame;
+                        }
+                        try
+                        {
+                            Thread.sleep(delayTimeForNextFrame / 1000);
+                        }
+                        catch (InterruptedException e)
+                        {
+                            e.printStackTrace();
+                        }
+                        // post EOM event
+                        if (iFrameIndex == 0)
+                        {
+                            loopCount++;
+                            if (!(iRepeatForeEver || (loopCount < iTotalLoopCount)))
+                            {
+                                // when this loop is getting braked, we need to change the state to pre-fetched
+                                //TODO Player should change it's state in doStop();
+                                changePlayerState(PREFETCHED);
+                            }
+                            // send the END_OF_MEDIA event to all
+                            // listener
+                            iPlayerListenerImpl.postEvent(
+                                PlayerListener.END_OF_MEDIA,
+                                new Long(iMediaTime));
+                        }
+                        if (iAnimationObserver!=null)
+                        {
+                            iAnimationObserver.animationAdvanced(iMediaTime);
+                        }
+                    }// end of while loop
+                    iCurrentLoopCount = loopCount;
+                }
+            };
+            thread.start();
+        }
+    }
+
+    /**
+     * State of the player should be changed from this function only.
+     * @param aState
+     */
+    private synchronized void  changePlayerState(int aState)
+    {
+        iState=aState;
+    }
+    /**
+     * On each repaint event, control is getting disposed and created each time,
+     * So we need to call each time the Control is available
+     * @param aControl
+     */
+    private void addPaintListener(org.eclipse.swt.widgets.Control aControl)
+    {
+        iControl=aControl;
+        if (iControl != null)
+        {
+            iDisplay.syncExec(new Runnable()
+            {
+                public void run()
+                {
+                    iControl.addPaintListener(new PaintListener()
+                    {
+                        public void paintControl(PaintEvent pe)
+                        {
+                            if (iImage != null && iIsControlVisible)
+                            {
+                                pe.gc.drawImage(iImage, iDisplayLocation.x,
+                                                iDisplayLocation.y);
+                            }
+                        }
+                    });
+                }
+            });
+        }
+    }
+
+
+    /**
+     * This returns player Control.
+     *
+     * @param controlType - the class name of the Control. The class name should be given either
+     * as the fully-qualified name of the class; or if the package of the class is not given, the
+     * package javax.microedition.media.control is assumed.
+     *
+     *  @return the object that implements the control, or null.
+     */
+    public Control getControl(String aControlType)
+    {
+        if (aControlType == null)
+        {
+            throw new IllegalArgumentException("argument is null");
+        }
+        closeCheck();
+        unrealizedCheck();
+
+        String controlType = aControlType;
+        // check if package name exists
+        if (controlType.indexOf(".") == -1)
+        {
+            // add package name
+            controlType = CONTROL_DEFAULT_PACKAGE + aControlType;
+        }
+        Control control = (Control)iControls.get(controlType);
+        // If control does not exists with default name, check if there is
+        // is a control with same type ( extends the given class name ).
+        if (control == null)
+        {
+            try
+            {
+                // try to create class for control
+                Class controlClass = Class.forName(controlType);
+                Enumeration elements = iControls.elements();
+                // search if any control is same type that requested control
+                while (elements.hasMoreElements())
+                {
+                    Control tmpControl = (Control) elements.nextElement();
+                    if (controlClass.isInstance(tmpControl))
+                    {
+                        // control is found
+                        control = tmpControl;
+                    }
+                }
+            }
+            catch (ClassNotFoundException cnfe) // the class could not be
+                // found
+            {
+                // Exception is ignored and null is returned from this method
+            }
+            catch (Error e) // the function failed for any other reason.
+            {
+                // Error is ignored and null is returned from this method
+            }
+        }
+        return control;
+    }
+    /**
+     * Returns all the control associated with this player
+     */
+    public Control[] getControls()
+    {
+        closeCheck();
+        unrealizedCheck();
+        Control control[]= new Control[iControls.size()];
+        Enumeration enumeration= iControls.elements();
+        byte index=0;
+        while (enumeration.hasMoreElements())
+        {
+            control[index++]=(Control)enumeration.nextElement();
+        }
+        return control;
+    }
+    /**
+     *
+     */
+    public void setLoopCount(int aCount)
+    {
+        iRepeatForeEver = (aCount == -1);
+        super.setLoopCount(aCount);
+        iTotalLoopCount=aCount;
+    }
+    /**
+     * From PlayerBase
+     * Here iFrameIndex variable will be updated according to the argument(aNow) supplied
+     * We are updating the iFrameIndex variable, which is being used in the start function
+     *
+     * @see PlayerBase
+     */
+    public long setMediaTime(long aNow) throws MediaException
+    {
+        long now = super.setMediaTime(aNow);
+        if (iDuration == TIME_UNKNOWN)
+            iDuration=getMediaTimeForFrame(getTotalNumberFrames());
+        if (now >= iDuration)
+        {
+            iFrameIndex=getTotalNumberFrames()-1;
+            iMediaTime = iDuration;
+        }
+        else
+        {
+            iFrameIndex = findFrame(now);
+            iMediaTime= getMediaTimeForFrame(iFrameIndex);
+        }
+        return iMediaTime ;
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    // Following functions are for internal use, and not exposed to MIDlet developer//////
+    /////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Before calling this function check frameIndex is in range or not, from 0 to last index
+     */
+    long getMediaTimeForFrame(int aFrameIndex)
+    {
+        long time=0;
+        for (int i=0; i < aFrameIndex; i++)
+        {
+            time+=iImageData[i].delayTime;
+        }
+        return time*10000;
+    }
+
+    /**
+     * Utility function to calculate the framNumber
+     * @param aTime
+     * @return
+     */
+    int findFrame(long aTime)
+    {
+        long time=0;
+        int frameIndex=0;
+        if (aTime > iDuration)
+            return -1;
+        else if (aTime==0)
+            return 0;
+        int totalNoOfFrame= getTotalNumberFrames();
+        while (time *10000 < aTime && frameIndex < totalNoOfFrame)
+        {
+            time += iImageData[frameIndex++].delayTime;
+        }
+        return frameIndex;
+    }
+    /**
+     * This function is responsible for creating all controls and adding it into Controls hashtable.
+     */
+    private void populateControl()
+    {
+        // there are four control provided by AnimationPlayer
+        // adding all one by one to the controlList(iControls)
+        addControl(new VideoControl(this), fVideoControl);
+        addControl(new FramePositioningControl(this), fFramePositioningControl);
+        addControl(new StopTimeControl(this), fStopTimeControl);
+        addControl(new RateControl(this), fRateControl);
+    }
+
+    /**
+     *  Notified when the display object of ESWT is created
+     *  It is getting created, when initDisplayMode of VideoControl class is called.
+     */
+    public void notifyDisplayAvailable(Display aDisplay)
+    {
+        iDisplay= aDisplay;
+        //iImage=new Image(iDisplay, iImageData[0]);
+        iImage=new Image(iDisplay, iImageData[iFrameIndex]);
+        iDisplay.syncExec(new Runnable()
+        {
+            public void run()
+            {
+                gc = new GC(iImage);
+            }
+        });
+    }
+    /**
+     * Notified when the control is available
+     * @param aControl(this is eSWTControl )
+     */
+    public void notifyControlAvailable(org.eclipse.swt.widgets.Control aControl)
+    {
+        iControl=aControl;
+        addPaintListener(iControl);
+    }
+
+
+
+    /**
+     * This function will be called from setDisplaySize(int width, int height) of animation/VideoControl class
+     * When MIDlet developer will try to alter the size of the image
+     * @param width : to be set of the video(Animated GIF)
+     * @param height : height to be set of video(Animated GIF)
+     */
+    void updateImageData(int aWidth, int aHeight)
+    {
+//        int noOfFrames= iImageData.length;
+//        for (int i=0; i<noOfFrames; i++)
+//        {
+//            iImageData[i]=iImageData[i].scaledTo(aWidth, aHeight);
+//        }
+//        iImage=new Image(iDisplay, iImageData[iFrameIndex]);
+        iCurrentVideoDimension.x=aWidth;
+        iCurrentVideoDimension.y= aHeight;
+        iImage=new Image(iDisplay, iImageData[iFrameIndex].scaledTo(aWidth, aHeight));
+    }
+
+    /**
+     * Overloaded function for calling the above function
+     */
+    void updateImageData(Point aSize)
+    {
+        updateImageData(aSize.x, aSize.y);
+    }
+
+    /**
+     * This function will be called from getSnapshot() function of VideoControl class
+     * to get the snap shot of the video
+     *
+     * @param format
+     */
+    // This function is not implemented fully
+    byte[] getCurrentFrame(String format)
+    {
+        // create a new ImageLoader object
+        ImageLoader il= new ImageLoader();
+        // create a ImageData array of length 1 and assign it to 'data' member of ImageLoader
+        il.data= new ImageData[1];
+        int currentFrameIndex= iFrameIndex;
+        // assign the current frame ImageData to image
+        il.data[0]= iImageData[currentFrameIndex];
+        il.logicalScreenWidth  = iImageData[currentFrameIndex].width;
+        il.logicalScreenHeight = iImageData[currentFrameIndex].height;
+        il.backgroundPixel= iBackgroundPixel;
+        ByteArrayOutputStream baos= new ByteArrayOutputStream();
+        il.save(baos, SWT.IMAGE_PNG);
+        //il.save(baos, SWT.IMAGE_GIF);
+        return baos.toByteArray();
+    }
+
+    /**
+     * Returns Point object, which contains the width and height of the image
+     * Called from VideoControl to get the image width and height,
+     * so that Item will be created exactly of same dimension
+     */
+    Point getCurrentVideoDimension()
+    {
+        return iCurrentVideoDimension;
+        // return new org.eclipse.swt.graphics.Point(iImageData[0].width, iImageData[0].height);
+    }
+
+
+    int getTotalNumberFrames()
+    {
+        return iImageData.length;
+    }
+    /**
+     *
+     * @param aDisplayLocation x,y coordinate where image is to be displayed
+     */
+    void setDisplayLocation(int aX, int aY)
+    {
+        iDisplayLocation.x=aX;
+        iDisplayLocation.y=aY;
+    }
+    /**
+     * @return the position of the image to be displayed
+     */
+    Point getiDisplayLocation()
+    {
+        return iDisplayLocation;
+    }
+    /**
+     * Called from VideoControl to get the dimension of original image size
+     * @return
+     */
+    Point getSourceDimension()
+    {
+        return iSourceDimension;
+        //return new Point(iImageData[0].width, iImageData[0].height);
+    }
+
+    /**
+     * @return the iPlayerListenerImpl
+     */
+    PlayerListenerImpl getiPlayerListenerImpl()
+    {
+        return iPlayerListenerImpl;
+    }
+
+    /**
+     * @return the iFrameIndex
+     */
+    int getiFrameIndex()
+    {
+        return iFrameIndex;
+    }
+
+    /**
+     * @return the iCurrentRate
+     */
+    int getiCurrentRate()
+    {
+        return iCurrentRate;
+    }
+
+    /**
+     * @param aCurrentRate the iCurrentRate to set
+     * @return actual rate set
+     */
+    int setiCurrentRate(int aCurrentRate)
+    {
+        // if the player is already started and was paused due to setRate
+        // then we need to start the player again from the same frame
+        if (iState == STARTED &&  iCurrentRate != aCurrentRate)
+        {
+            if (aCurrentRate<=0)
+            {
+                // pause the player
+                // following line will break the while loop in start method
+                // Objective here is to pause the animation, if it is in started state
+                // also we do not need to notify to the playerListener that player has been stopped or paused
+                changePlayerState(PREFETCHED);
+            }
+            else
+            {
+                //start the player
+                // this will start playing animation from the very same frame
+                // where it was paused due to setRate(0)
+                try
+                {
+                    start();
+                }
+                catch (MediaException e)
+                {
+                    // ignore the exception
+                    e.printStackTrace();
+                }
+            }
+        }
+        this.iCurrentRate = aCurrentRate;
+        return iCurrentRate;
+    }
+
+    /**
+     * @param iIsControlVisible the iIsControlVisible to set
+     */
+    void setiIsControlVisible(boolean iIsControlVisible)
+    {
+        this.iIsControlVisible = iIsControlVisible;
+    }
+    /**
+     * Called from StopTimeControl.animationAdvanced(long), once the stopped time is greater than or equal media time.
+     */
+    void postEvent(long aMediaTime)
+    {
+        changePlayerState(PREFETCHED);
+        iPlayerListenerImpl.postEvent(PlayerListener.STOPPED_AT_TIME, new Long(
+                                          aMediaTime));
+    }
+
+    /**
+     * @param aAnimationObserver the iAnimationObserver to set
+     */
+    void setiAnimationObserver(AnimationObserver aAnimationObserver)
+    {
+        this.iAnimationObserver = aAnimationObserver;
+    }
+
+
+}
+