javauis/mmapi_qt/baseline/javasrc/com/nokia/microedition/media/animation/AnimationPlayer.java
changeset 23 98ccebc37403
child 26 dc7c549001d5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/mmapi_qt/baseline/javasrc/com/nokia/microedition/media/animation/AnimationPlayer.java	Fri May 14 15:47:24 2010 +0300
@@ -0,0 +1,592 @@
+/*
+* Copyright (c) 2009 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: 
+*
+*/
+/**
+ * 
+ */
+package com.nokia.microedition.media.animation;
+
+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.ercp.swt.mobile.MobileShell;
+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 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;
+
+/**
+ * @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;
+	// number of times we need to repeat the animation
+	// by default it's value is one 
+	private int iTotalLoopCount=1;
+	// this holds all control related to this player 
+	Hashtable iControls= new Hashtable();
+	// Current frame index of the Animation file
+	private int iFrameindex;
+	// Current Loop Count 
+	private int iCurrentLoopCount;
+	// Display object of the eSWT API, creating this object will integrate the current java code with eSWT API. 
+	Display iDisplay; 
+	// Control object of ESWT API, return from LCDUIInvoker. 
+	org.eclipse.swt.widgets.Control iControl;
+	// Constants used everywhere to compare the string 
+	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();
+	 /**
+     * 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 =
+        "javax.microedition.media.control.";
+    
+	//For Player listener 
+	protected PlayerListenerImpl iPlayerListenerImpl;
+	//Image to be displayed, again 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;
+	
+	// Display Location, of the image   
+	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
+		// 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();
+			iImageData=imageLoader.load(is);
+			//iRepeatCount=imageLoader.repeatCount;
+			iSourceDimension= new Point(imageLoader.logicalScreenWidth, imageLoader.logicalScreenHeight);
+		}
+		pupulateControl();
+		System.out.println(DEBUG_STR+"-");
+	}
+	
+	/**
+	 * 
+	 * @param locator
+	 * @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() {
+		// what to do here, nullify image data and display etc???
+	}
+
+	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 
+		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)
+			throws MediaException {
+		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();
+		long time = TIME_UNKNOWN;
+		int totalNoOfFrames = iImageData.length;
+		for (int i = 0; i < totalNoOfFrames; i++) {
+			time += iImageData[i].delayTime;
+		}
+		// Since we have to return it in microsecond multiply it with 1000; 
+		return time * 10000;
+	}
+	
+	/**
+	 * This returned the total time taken, till now, to play the video.  
+	 */
+	public long getMediaTime() {
+		return iMediaTime*10000;
+	}
+
+	public int getState() {
+		return iState;
+	}
+	
+	/**
+	 * Removes the specified playerListner from this player  
+	 */
+	public void removePlayerListener(PlayerListener aPlayerListener) {
+		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();
+							}
+							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();
+					}
+					System.out
+							.println("**********************End of while loop\n\n\n");
+				}
+				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();
+		// }
+	}
+	
+	/**
+	 * This function is also being called from VideoControl class, 
+	 * Since on each event 
+	 * @param aControl
+	 * @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);
+						}
+					}
+				});
+			}
+		});
+	}
+	/**
+	 * 
+	 */
+	public Control getControl(String aControlType) {
+		if (aControlType == null) {
+			throw new IllegalArgumentException("argument is null");
+		}
+		
+		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() {
+		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){
+		super.setLoopCount(aCount);
+		iTotalLoopCount=aCount;
+	}
+	/**
+     * From PlayerBase
+     * @see PlayerBase
+     */
+	public long setMediaTime(long aNow) throws MediaException {
+		long now = super.setMediaTime(aNow);
+		int totalFrames = iImageData.length;
+		int totalTime = 0;
+		for (int i = 0; i < totalFrames; i++) {
+			if (now < totalTime) {
+				iFrameindex=i;
+				break;
+			}
+			totalTime += iImageData[i].delayTime * 10000;
+		}
+		return totalTime;
+	}
+	//////////////////////////////////////////////////////////////////////////////////////
+	// 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);
+		try {
+			addControl(videoControl, fVideoControl);
+			addControl(fpc, fFramePositioningControl);
+			addControl(stc, fStopTimeControl);
+			addControl(rc,fRateControl);
+		} catch (MediaException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		System.out.println(DEBUG_STR+"-");
+	}
+	/**
+	 * This function initialize iControl and iDisplay object if it is null,
+	 * otherwise return immediately.
+	 * 
+	 * In case of Canvas, eSWT control will be returned immediately from VideoControl(vc.getControl()), 
+	 * but in case of CustomItem we need to keep polling, eSWT doesn't return the control for CustomItem 
+	 * until CustomItem is appended to Form.      
+	 */
+	
+	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();
+			// in case of CustomItem,
+			while ((iControl = vc.getControl()) == null) {
+				try {
+					Thread.sleep(100);
+				} catch (InterruptedException e) {
+					e.printStackTrace();
+				}
+			}
+		}
+		System.out.println(DEBUG_STR + "-");
+	}
+	
+	/**
+	 * 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 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+"-");
+	}
+	
+	/**
+	 * 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  
+	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;
+	}
+	
+	/**
+	 * 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 
+	 */
+	org.eclipse.swt.graphics.Point getImageDimension(){
+		return new org.eclipse.swt.graphics.Point(iImageData[0].width, iImageData[0].height);  
+	}
+	
+	/**
+	 * This returns the imageData array, 
+	 * called from FramePositioningControl class to calculate the frame time 
+	 */
+	ImageData[] getImageData(){
+		return iImageData;
+	}
+	
+	/**
+	 * 
+	 * @param aDisplayLocation x,y coordinate where image is to be displayed 
+	 */
+	void setDisplayLocation(int aX, int aY){
+		iDisplayLocation=new Point(aX,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 the iPlayerListenerImpl
+	 */
+	PlayerListenerImpl getiPlayerListenerImpl() {
+		return iPlayerListenerImpl;
+	}
+}