javauis/mmapi_qt/baseline/javasrc/com/nokia/microedition/media/animation/AnimationPlayer.java
changeset 26 dc7c549001d5
parent 23 98ccebc37403
child 35 85266cc22c7f
--- a/javauis/mmapi_qt/baseline/javasrc/com/nokia/microedition/media/animation/AnimationPlayer.java	Fri May 14 15:47:24 2010 +0300
+++ b/javauis/mmapi_qt/baseline/javasrc/com/nokia/microedition/media/animation/AnimationPlayer.java	Thu May 27 12:49:31 2010 +0300
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* 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"
@@ -11,12 +11,9 @@
 *
 * Contributors:
 *
-* Description: 
+* Description: AnimationPlayer
 *
 */
-/**
- * 
- */
 package com.nokia.microedition.media.animation;
 
 import java.io.InputStream;
@@ -28,7 +25,6 @@
 import javax.microedition.media.PlayerListener;
 import javax.microedition.media.protocol.DataSource;
 
-import org.eclipse.ercp.swt.mobile.MobileShell;
 import org.eclipse.swt.SWTException;
 import org.eclipse.swt.events.PaintEvent;
 import org.eclipse.swt.events.PaintListener;
@@ -38,19 +34,15 @@
 import org.eclipse.swt.graphics.ImageLoader;
 import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
 
 import com.nokia.microedition.media.BufferDataSource;
 import com.nokia.microedition.media.InputStreamDataSource;
 import com.nokia.microedition.media.InputStreamSourceStream;
-import com.nokia.microedition.media.Locator;
 import com.nokia.microedition.media.PlayerBase;
 import com.nokia.microedition.media.PlayerListenerImpl;
+import com.nokia.mj.impl.nokialcdui.LCDUIInvoker;
+import com.nokia.mj.impl.utils.Logger;
 
-/**
- * @author d35kumar
- *
- */
 public class AnimationPlayer extends PlayerBase {
 	// GIF image information, array length will be equal to the number of frames in image 
 	protected ImageData [] iImageData;
@@ -58,51 +50,59 @@
 	// by default it's value is one 
 	private int iTotalLoopCount=1;
 	// this holds all control related to this player 
-	Hashtable iControls= new Hashtable();
+	private Hashtable iControls= new Hashtable();
 	// Current frame index of the Animation file
-	private int iFrameindex;
+	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. 
-	Display iDisplay; 
+	private Display iDisplay; 
 	// Control object of ESWT API, return from LCDUIInvoker. 
 	org.eclipse.swt.widgets.Control iControl;
-	// Constants used everywhere to compare the string 
+	// Following constants are used for comparison of the string, throughout the class 
 	private static final String ANIMATION_CONTENT_TYPE = "image/gif";
-	
-	private final String fVideoControl=VideoControl.class.getName();
-	private final String fFramePositioningControl=FramePositioningControl.class.getName();
-	private final String fStopTimeControl=StopTimeControl.class.getName();
-	private final String fRateControl=RateControl.class.getName();
-	 /**
+	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.
      */
-    static final String CONTROL_DEFAULT_PACKAGE =
+    private static final String CONTROL_DEFAULT_PACKAGE =
         "javax.microedition.media.control.";
     
 	//For Player listener 
 	protected PlayerListenerImpl iPlayerListenerImpl;
-	//Image to be displayed, again object of eSWT API. 
+	//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 
-	Point iSourceDimension;
-	long iMediaTime;
+	private Point iSourceDimension;
+	// Total time taken so far to playe the animation 
+	private long iMediaTime;
+	// Time at which, player should be stopped
+	// This will set through StopTimeControl.setTime();
+	private long iStopTime=Long.MAX_VALUE;
 	
-	// Display Location, of the image   
+	// 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);
-	
 
 	/**
 	 * 
 	 * @param ds DataSource which contains the data to be displayed 
 	 */
 	public AnimationPlayer(DataSource ds){
-		final String DEBUG_STR="AnimationPlayer::AnimationPlayer(DataSource)";
-		System.out.println(DEBUG_STR+"+");
 		iPlayerListenerImpl= new PlayerListenerImpl(this);
 		//TODO check if we can do it in better way 
 		// this is temporary solution
@@ -119,7 +119,6 @@
 			iSourceDimension= new Point(imageLoader.logicalScreenWidth, imageLoader.logicalScreenHeight);
 		}
 		pupulateControl();
-		System.out.println(DEBUG_STR+"-");
 	}
 	
 	/**
@@ -128,27 +127,20 @@
 	 * @throws SWTException
 	 */
 	public AnimationPlayer(String locator) throws SWTException{
-		final String DEBUG_STR="AnimationPlayer::AnimationPlayer(Locator )";
-		System.out.println(DEBUG_STR+"+");
 		ImageLoader imageLoader= new ImageLoader();
-		System.out.println(DEBUG_STR+"Locator string is "+locator);
 		// Following line may throw SWTException 
 		iImageData=imageLoader.load(locator);
 		//iRepeatCount=imageLoader.repeatCount;
 		iSourceDimension= new Point(imageLoader.logicalScreenWidth, imageLoader.logicalScreenHeight);
 		pupulateControl();
-		System.out.println(DEBUG_STR+"-");
 	}
 	
 	/**
 	 * Moved the player to close state and releases all resources, called from PlayerBase class  
 	 */
 	protected void doClose() {
-		final String DEBUG_STR="AnimationPlayer::doClose()";
-		System.out.println(DEBUG_STR+"+");
 		iState=CLOSED;
 		iPlayerListenerImpl.postEvent(PlayerListener.CLOSED, null);
-		System.out.println(DEBUG_STR+"-");
 	}
 
 	protected void doDeallocate() {
@@ -156,28 +148,23 @@
 	}
 
 	protected void doPrefetch() throws MediaException {
-		final String DEBUG_STR="AnimationPlayer::doPrefetch()";
-		System.out.println(DEBUG_STR+"+");
 		iState=PREFETCHED;
-		System.out.println(DEBUG_STR+"-");
 	}
 
 	protected void doRealize() throws MediaException {
-		final String DEBUG_STR="AnimationPlayer::doRealize()";
-		System.out.println(DEBUG_STR+"+");
 		iState=REALIZED;
-		// this is temporary solution implement it in proper way 
+		// this is temporary solution implement it in proper way
+		// initialize the iImage object with first frame  
 		iImage=new Image(iDisplay, iImageData[0]);
-		System.out.println(DEBUG_STR+"-");
 	}
-
+	
+	/**
+	 * 
+	 */
 	protected void doStop() throws MediaException {
-		final String DEBUG_STR="AnimationPlayer::doStop()";
-		System.out.println(DEBUG_STR+"+");
 		// since after stopping the player the player state will move to pre-fetched state 
 		iState=PREFETCHED;
 		iPlayerListenerImpl.postEvent(PlayerListener.STOPPED, new Long(iMediaTime * 10000));
-		System.out.println(DEBUG_STR+"-");
 	}
 
 	public void addControl(Control aControl, String aControlType)
@@ -214,9 +201,10 @@
 	}
 	
 	/**
-	 * This returned the total time taken, till now, to play the video.  
+	 * This returns the total time taken, till now, to play the video.  
 	 */
 	public long getMediaTime() {
+		// Since we have to return it in microsecond multiply it with 1000;
 		return iMediaTime*10000;
 	}
 
@@ -231,91 +219,120 @@
 		closeCheck();
         iPlayerListenerImpl.removePlayerListener(aPlayerListener);
 	}
+	
+	/**
+	 * 
+	 */
+	
 	public void start() throws MediaException {
 		final String DEBUG_STR = "AnimationPlayer::start()";
-//		prefetch();
-		initialize();
-		addPaintListener(iControl);
-		iState = STARTED;
-		Thread thread = new Thread("Animation") {
-			int frameIndex = iFrameindex;
-			int loopCount = iCurrentLoopCount;
-			GC gc=null;
-			public void run() {
-				final int noOfFrames = iImageData.length;
-				while (frameIndex < noOfFrames && (loopCount < iTotalLoopCount)
-						&& (iState == STARTED)) {
-					final int delayTimeForNextFrame = iImageData[frameIndex].delayTime;
-					System.out.println("\n\n\n************" + DEBUG_STR
-							+ "Inside the while loop " + frameIndex + "/"
-							+ noOfFrames);
-					// Since we are going to display first frame, notify all
-					// PlayerListener that Player has started
-					if (frameIndex == 0) {
-						iPlayerListenerImpl.postEvent(PlayerListener.STARTED,
-								new Long(iMediaTime * 10000));
-					}
-					iDisplay.asyncExec(new Runnable() {
-						public void run() {
-							System.out.println(DEBUG_STR+"Inside run method");
-							try {
-								if (gc == null)gc = new GC(iImage);
-							} catch (Exception e) {
-								// TODO Auto-generated catch block
-								e.printStackTrace();
+		Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,DEBUG_STR + "+");
+		prefetch();
+		// Only prefetched player may be started. If player is already started
+		// this method returns silently.
+		if (getState() == PREFETCHED) {
+			initialize();
+			addPaintListener(iControl);
+			iState = STARTED;
+			Thread thread = new Thread("Animation") {
+				// int frameIndex = iFrameindex;
+				int loopCount = iCurrentLoopCount;
+				GC gc = null;
+				public void run() {
+					final int noOfFrames = iImageData.length;
+					while (iFrameIndex < noOfFrames
+							&& (iRepeatForeEver || (loopCount < iTotalLoopCount))
+							&& (iState == STARTED)) {
+						final int delayTimeForNextFrame = iImageData[iFrameIndex].delayTime;
+						// Since we are going to display first frame, notify all
+						// PlayerListener that Player has started
+						if (iFrameIndex == 0) {
+							// TODO Is it true that whenever STARTED event will
+							// be posted
+							// 2nd argument in postEvent function(mediaTime)
+							// will be zero?
+							// in that case just pass the 2nd argument as zero,
+							// instead of multiplying
+							// iMediaTime with 10000.
+							iPlayerListenerImpl.postEvent(
+									PlayerListener.STARTED, new Long(
+											iMediaTime * 10000));
+						}
+						// if stop time has become more than the media time
+						// TODO This solution may not be accurate, if the delay
+						// between two frames is grater than 1 second.
+						// Do we need to implement the TimerTask only.
+						if ( iMediaTime > iStopTime ) {
+							Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,DEBUG_STR+"Going to post Stopped at time event to player Listener ");
+							iPlayerListenerImpl.postEvent(
+									PlayerListener.STOPPED_AT_TIME, new Long(
+											iMediaTime * 10000));
+							break;
+						}
+						iDisplay.asyncExec(new Runnable() {
+							public void run() {
+								try {
+									if (gc == null)
+										gc = new GC(iImage);
+								} catch (Exception e) {
+									// TODO Auto-generated catch block
+									// e.printStackTrace();
+								}
+								// iImage.dispose();
+								// iImage=new Image(iDisplay,
+								// iImageData[iFrameIndex]);
+								Image tempImage = new Image(iDisplay,
+										iImageData[iFrameIndex]);
+								gc.drawImage(tempImage, 0, 0);
+								tempImage.dispose();
+								iFrameIndex = (iFrameIndex + 1) % noOfFrames;
+								iControl.redraw();
+								// update the mediaTime, as Animation progress
+								iMediaTime += delayTimeForNextFrame;
+
+								// If imageIndex becomes zero it means, all
+								// frames
+								// has been displayed
+								// So increase the loopCount
+								if (iFrameIndex == 0) {
+									// send the END_OF_MEDIA event to all
+									// listener
+									iPlayerListenerImpl.postEvent(
+											PlayerListener.END_OF_MEDIA,
+											new Long(iMediaTime * 10000));
+									loopCount++;
+									// since player is again going to start from
+									// the
+									// first frame
+									// so media time should be set to zero
+									iMediaTime = 0;
+								}
+								System.out
+										.println(DEBUG_STR
+												+ "\n End of asynchronous block imageIndex is "
+												+ iFrameIndex
+												+ " and loop count is"
+												+ loopCount);
 							}
-							System.out.println(DEBUG_STR+"Inside run method246");
-							Image tempImage = new Image(iDisplay,
-									iImageData[frameIndex]);
-							System.out.println(DEBUG_STR+"Inside run method246");
-							gc.drawImage(tempImage, 0, 0);
-							tempImage.dispose();
-							frameIndex = (frameIndex + 1) % noOfFrames;
-							System.out.println(DEBUG_STR+"Inside run method253>>>>>>>>>"+frameIndex);
-							iControl.redraw();
-							// update the mediaTime, as Animation progress
-							iMediaTime += delayTimeForNextFrame;
-							// If imageIndex becomes zero it means, all frames
-							// has been displayed
-							// So increase the loopCount
-							if (frameIndex == 0) {
-								// send the END_OF_MEDIA event to all listener
-								iPlayerListenerImpl.postEvent(
-										PlayerListener.END_OF_MEDIA, new Long(
-												iMediaTime * 10000));
-								loopCount++;
-								// since player is again going to start from the
-								// first frame
-								// so media time should be set to zero
-								iMediaTime = 0;
-							}
-							System.out
-									.println(DEBUG_STR
-											+ "end of asynchronous block imageIndex is "
-											+ frameIndex + " and loop count is"
-											+ loopCount );
+						});
+						try {
+							Thread.sleep(delayTimeForNextFrame * 10);
+						} catch (InterruptedException e) {
+							// TODO Auto-generated catch block
+							e.printStackTrace();
 						}
-					});
-					try {
-						Thread.sleep(delayTimeForNextFrame * 10);
-					} catch (InterruptedException e) {
-						// TODO Auto-generated catch block
-						e.printStackTrace();
 					}
-					System.out
-							.println("**********************End of while loop\n\n\n");
+					iCurrentLoopCount = loopCount;
+					Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,DEBUG_STR
+									+ "Came out side the while loop " + iState
+									+ " iFrameIndex " + iFrameIndex
+									+ " loopCount " + loopCount
+									);
 				}
-				iCurrentLoopCount=loopCount;
-				System.out.println(DEBUG_STR + "Came out side the while loop "
-						+ iState);
-			}
-		};
-		thread.start();
-		System.out.println(DEBUG_STR + "-");
-		// }catch(Exception e){
-		// System.out.println(DEBUG_STR+"Exception caught"+e);
-		// e.printStackTrace();
-		// }
+			};
+			thread.start();
+		}
+		Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,DEBUG_STR + "-");
 	}
 	
 	/**
@@ -325,26 +342,16 @@
 	 * @throws MediaException 
 	 */
 	 void addPaintListener(org.eclipse.swt.widgets.Control aControl) throws MediaException{
-		 final String DEBUG_STR="AnimationPlayer::addPaintListener()";
 		 iControl=aControl;
 		// iDisplay and IControl shouldn't be null here 
-		System.out.println(DEBUG_STR+" Control is "+iControl+" Display "+iDisplay);
 		// Following line should never execute
 		// TODO check what message to provide in case of Exception 
 		if(iControl==null)
 			throw new MediaException("Update this message");
 		iDisplay.syncExec(new Runnable(){
 			public void run() {
-				// if user is writing his MIDlet using eSWT API, then the Control object will be MobileShell
-				// and in that case it is mandatory to open the shell
-//				if(iControl instanceof MobileShell){
-				if(iControl instanceof Shell){
-					((Shell)iControl).open();
-				}
 				iControl.addPaintListener(new PaintListener(){
 					public void paintControl(PaintEvent pe) {
-//						System.out.println(DEBUG_STR+"paintControl() paintEvent is "+pe);
-//						System.out.println(DEBUG_STR+"paintControl() Display location is "+iDisplayLocation.x+", "+iDisplayLocation.y);
 						if(iImage!=null){
 							pe.gc.drawImage(iImage, iDisplayLocation.x, iDisplayLocation.y);
 						}
@@ -412,47 +419,46 @@
 	 * 
 	 */
 	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 {
+		final String DEBUG_STR="AnimationPlayer::setmediaTime()";
 		long now = super.setMediaTime(aNow);
 		int totalFrames = iImageData.length;
 		int totalTime = 0;
 		for (int i = 0; i < totalFrames; i++) {
-			if (now < totalTime) {
-				iFrameindex=i;
+			totalTime += iImageData[i].delayTime;
+			if (totalTime*10000 >= now ) {
+				iFrameIndex=i;
 				break;
 			}
-			totalTime += iImageData[i].delayTime * 10000;
 		}
-		return totalTime;
+		// we need to update the iMediaTime as well 
+		iMediaTime=totalTime;
+		return totalTime * 10000;
 	}
 	//////////////////////////////////////////////////////////////////////////////////////
 	// Following functions are for internal use, and not exposed to MIDlet developer//////
 	/////////////////////////////////////////////////////////////////////////////////////
-	/**
-	 * 
-	 */
-	private void doStart(){
-		
-	}
-	
-	
     /**
 	 * This function is responsible for creating all controls and adding it into Controls hashtable.
 	 */
 	private void pupulateControl(){
-		final String DEBUG_STR="AnimationPlayer::pupulateControl()";
-		System.out.println(DEBUG_STR+"+");
 		VideoControl videoControl= new VideoControl(this);
 		FramePositioningControl fpc= new FramePositioningControl(this);
 		StopTimeControl stc= new StopTimeControl(this);
 		RateControl rc= new RateControl(this);
+		// there are four control provided by AnimationPlayer 
+		// adding all one by one to the controlList(iControls)
 		try {
 			addControl(videoControl, fVideoControl);
 			addControl(fpc, fFramePositioningControl);
@@ -462,7 +468,6 @@
 			// TODO Auto-generated catch block
 			e.printStackTrace();
 		}
-		System.out.println(DEBUG_STR+"-");
 	}
 	/**
 	 * This function initialize iControl and iDisplay object if it is null,
@@ -474,10 +479,6 @@
 	 */
 	
 	private void initialize() {
-		final String DEBUG_STR = "AnimationPlayer::initialize()";
-		System.out.println(DEBUG_STR + "+");
-		System.out.println(DEBUG_STR + " Control is " + iControl
-				+ " display is " + iDisplay);
 		if (iControl == null || iDisplay == null) {
 			VideoControl vc = (VideoControl) getControl(fVideoControl);
 			iDisplay = vc.getiDisplay();
@@ -490,7 +491,6 @@
 				}
 			}
 		}
-		System.out.println(DEBUG_STR + "-");
 	}
 	
 	/**
@@ -500,14 +500,18 @@
 	 * @param height : height to be set of video(Animated GIF) 
 	 */
 	void updateImageData(int width, int height){
-		final String DEBUG_STR= "AnimationPlayer::updateImageData(int width, int height)";
-		System.out.println(DEBUG_STR+"+");
 		int noOfFrames= iImageData.length;
 		for(int i=0;i<noOfFrames;i++){
 			iImageData[i]=iImageData[i].scaledTo(width, height);
 		}
 		iImage=new Image(iDisplay, iImageData[0]);
-		System.out.println(DEBUG_STR+"-");
+	}
+	
+	/**
+	 * Overloaded function for calling the above function  
+	 */
+	void updateImageData(Point aSize){
+		updateImageData(aSize.x, aSize.y);
 	}
 	
 	/**
@@ -517,31 +521,9 @@
 	 * @param format
 	 */
 	// This function is not implemented fully  
-	int[] getCurrentFrame(String format){
-		final String DEBUG_STR="AnimationPlayer::getCurrentFrame()";
-		System.out.println(DEBUG_STR+"+");
-		ImageData currentFrameImageData=iImage.getImageData();
-		int data[][]= new int[currentFrameImageData.height][currentFrameImageData.width];
-		System.out.println("Width of the current Image is "+data[0].length+" height "+data.length);
-		
-		int imageWidth=data[0].length;
-		int imageHeight=data.length;
-		System.out.println("Image Width "+imageWidth+", "+currentFrameImageData.width+" height "+imageHeight+", "+currentFrameImageData.height);
-		
-		for(int i=0;i<imageHeight;i++){
-			currentFrameImageData.getPixels(0, i, imageWidth, data[i], 0);
-			System.out.println(DEBUG_STR+"=========>"+data[i]);
-		}
-		System.out.println(DEBUG_STR+"After reading all pixel value");
-		int[] byteArray=new int[imageWidth*imageHeight];
-		//int dataLength=data.length;
-		
-		for(int i=0;i<imageHeight;i++){
-			System.arraycopy(data[i], 0, byteArray, i*imageWidth, imageWidth);
-		}
-		System.out.println(DEBUG_STR+"After merging all array into single array ");
-		System.out.println(DEBUG_STR+"-"+byteArray+">>>>>"+byteArray.length);
-		return byteArray;
+	javax.microedition.lcdui.Image getCurrentFrame(String format){
+		javax.microedition.lcdui.Image currentFrameImage= LCDUIInvoker.createLcduiImage(iImage);
+		return currentFrameImage;
 	}
 	
 	/**
@@ -589,4 +571,55 @@
 	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 is in started state
+				// also we do not need to notify to the playerListener that player has been stopped or paused 
+				iState=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 iStopTime the iStopTime to set
+	 */
+	void setiStopTime(long iStopTime) {
+		this.iStopTime = iStopTime;
+	}
 }