14 * Description: AnimationPlayer |
14 * Description: AnimationPlayer |
15 * |
15 * |
16 */ |
16 */ |
17 package com.nokia.microedition.media.animation; |
17 package com.nokia.microedition.media.animation; |
18 |
18 |
19 import java.io.ByteArrayInputStream; |
|
20 import java.io.ByteArrayOutputStream; |
19 import java.io.ByteArrayOutputStream; |
21 import java.io.IOException; |
20 import java.io.IOException; |
22 import java.io.InputStream; |
21 import java.io.InputStream; |
23 import java.io.OutputStream; |
|
24 import java.util.Enumeration; |
22 import java.util.Enumeration; |
25 import java.util.Hashtable; |
23 import java.util.Hashtable; |
26 import java.util.Timer; |
|
27 import java.util.TimerTask; |
|
28 |
24 |
29 import javax.microedition.media.Control; |
25 import javax.microedition.media.Control; |
30 import javax.microedition.media.MediaException; |
26 import javax.microedition.media.MediaException; |
31 import javax.microedition.media.Player; |
|
32 import javax.microedition.media.PlayerListener; |
27 import javax.microedition.media.PlayerListener; |
33 import javax.microedition.media.protocol.DataSource; |
28 import javax.microedition.media.protocol.DataSource; |
34 |
29 |
35 import org.eclipse.swt.SWT; |
30 import org.eclipse.swt.SWT; |
36 import org.eclipse.swt.SWTException; |
31 import org.eclipse.swt.SWTException; |
46 import com.nokia.microedition.media.BufferDataSource; |
41 import com.nokia.microedition.media.BufferDataSource; |
47 import com.nokia.microedition.media.InputStreamDataSource; |
42 import com.nokia.microedition.media.InputStreamDataSource; |
48 import com.nokia.microedition.media.InputStreamSourceStream; |
43 import com.nokia.microedition.media.InputStreamSourceStream; |
49 import com.nokia.microedition.media.PlayerBase; |
44 import com.nokia.microedition.media.PlayerBase; |
50 import com.nokia.microedition.media.PlayerListenerImpl; |
45 import com.nokia.microedition.media.PlayerListenerImpl; |
51 import com.nokia.mj.impl.nokialcdui.LCDUIInvoker; |
|
52 import com.nokia.mj.impl.utils.Logger; |
|
53 |
46 |
54 public class AnimationPlayer extends PlayerBase implements ESWTinitializeListener |
47 public class AnimationPlayer extends PlayerBase implements ESWTinitializeListener |
55 { |
48 { |
56 // GIF image information, array length will be equal to the number of frames in image |
49 // GIF image information, array length will be equal to the number of frames in image |
57 protected ImageData [] iImageData; |
50 protected ImageData [] iImageData; |
96 // Actual dimension of the image, this should be initialized while creating the player |
89 // Actual dimension of the image, this should be initialized while creating the player |
97 // as user can change the size of the image later, in that case too, getSourceheight and getSourceWidth |
90 // as user can change the size of the image later, in that case too, getSourceheight and getSourceWidth |
98 // of VideoControl should return the actual width and height of the image |
91 // of VideoControl should return the actual width and height of the image |
99 private Point iSourceDimension; |
92 private Point iSourceDimension; |
100 // Current dimension of the image, MIDlet developer may change the size of VideoControl |
93 // Current dimension of the image, MIDlet developer may change the size of VideoControl |
101 // private Point iCurrentVideoDimension; |
94 private Point iCurrentVideoDimension; |
102 // Total time taken so far to player the animation, it keeps updating as player moves |
95 // Total time taken so far to player the animation, it keeps updating as player moves |
103 private long iMediaTime; |
96 private long iMediaTime; |
104 // Time at which, player should be stopped |
97 // Time at which, player should be stopped |
105 // This will set through StopTimeControl.setTime(); |
98 // This will set through StopTimeControl.setTime(); |
106 // otherwise default time is Long.MAX_VALUE |
99 // otherwise default time is Long.MAX_VALUE |
119 // Total duration of the player |
112 // Total duration of the player |
120 private long iDuration=TIME_UNKNOWN; |
113 private long iDuration=TIME_UNKNOWN; |
121 /** |
114 /** |
122 * |
115 * |
123 * @param ds DataSource which contains the data to be displayed |
116 * @param ds DataSource which contains the data to be displayed |
124 */ |
117 * @throws MediaException |
125 public AnimationPlayer(DataSource ds) |
118 */ |
|
119 public AnimationPlayer(DataSource ds) throws MediaException |
126 { |
120 { |
127 iPlayerListenerImpl= new PlayerListenerImpl(this); |
121 iPlayerListenerImpl= new PlayerListenerImpl(this); |
128 //TODO check if we can do it in better way |
122 //TODO check if we can do it in better way |
129 // this is temporary solution |
123 // this is temporary solution |
130 // for this I have written two functions getDataSource and getInputStream function |
124 // for this I have written two functions getDataSource and getInputStream function |
133 InputStreamSourceStream isss=(InputStreamSourceStream)isds.getStreams()[0]; |
127 InputStreamSourceStream isss=(InputStreamSourceStream)isds.getStreams()[0]; |
134 InputStream is = isss.getInputStream(); |
128 InputStream is = isss.getInputStream(); |
135 if (is!=null) |
129 if (is!=null) |
136 { |
130 { |
137 ImageLoader imageLoader= new ImageLoader(); |
131 ImageLoader imageLoader= new ImageLoader(); |
|
132 |
|
133 // If it is any other format other than the image(jpeg, png and gif), |
|
134 // following line will throw the SWT exception |
138 iImageData=imageLoader.load(is); |
135 iImageData=imageLoader.load(is); |
|
136 // If the image is loaded properly, we need to check whether it is GIF image or not. |
|
137 // It can be PNG and JPEG as well |
|
138 if (iImageData[0].type!=SWT.IMAGE_GIF) |
|
139 throw new MediaException("Could not create player"); |
139 try |
140 try |
140 { |
141 { |
141 is.close(); |
142 is.close(); |
142 } |
143 } |
143 catch (IOException e) |
144 catch (IOException e) |
144 { |
145 { |
145 e.printStackTrace(); |
146 e.printStackTrace(); |
146 } |
147 } |
147 iSourceDimension= new Point(imageLoader.logicalScreenWidth, imageLoader.logicalScreenHeight); |
148 iSourceDimension= new Point(imageLoader.logicalScreenWidth, imageLoader.logicalScreenHeight); |
|
149 iCurrentVideoDimension= new Point(imageLoader.logicalScreenWidth, imageLoader.logicalScreenHeight); |
148 iBackgroundPixel= imageLoader.backgroundPixel; |
150 iBackgroundPixel= imageLoader.backgroundPixel; |
149 } |
151 } |
150 populateControl(); |
152 populateControl(); |
151 |
153 |
152 } |
154 } |
154 /** |
156 /** |
155 * |
157 * |
156 * @param locator |
158 * @param locator |
157 * @throws SWTException |
159 * @throws SWTException |
158 */ |
160 */ |
159 public AnimationPlayer(String locator) throws SWTException |
161 public AnimationPlayer(String locator) throws SWTException, MediaException |
160 { |
162 { |
|
163 ImageLoader imageLoader= new ImageLoader(); |
|
164 // If it is any other format other than the image(jpeg, png and gif), |
|
165 // following line will throw the SWT exception |
|
166 iImageData=imageLoader.load(locator); |
|
167 // If the image is loaded properly, we need to check whether it is GIF image or not. |
|
168 // It can be PNG and JPEG as well |
|
169 if (iImageData[0].type!=SWT.IMAGE_GIF) |
|
170 throw new MediaException("Could not create player"); |
161 iPlayerListenerImpl= new PlayerListenerImpl(this); |
171 iPlayerListenerImpl= new PlayerListenerImpl(this); |
162 ImageLoader imageLoader= new ImageLoader(); |
|
163 // Following line may throw SWTException |
|
164 iImageData=imageLoader.load(locator); |
|
165 iSourceDimension= new Point(imageLoader.logicalScreenWidth, imageLoader.logicalScreenHeight); |
172 iSourceDimension= new Point(imageLoader.logicalScreenWidth, imageLoader.logicalScreenHeight); |
|
173 iCurrentVideoDimension= new Point(imageLoader.logicalScreenWidth, imageLoader.logicalScreenHeight); |
166 iBackgroundPixel= imageLoader.backgroundPixel; |
174 iBackgroundPixel= imageLoader.backgroundPixel; |
167 populateControl(); |
175 populateControl(); |
168 } |
176 } |
169 |
177 |
170 /** |
178 /** |
204 */ |
212 */ |
205 protected void doStop() throws MediaException |
213 protected void doStop() throws MediaException |
206 { |
214 { |
207 // since after stopping the player the player state will move to pre-fetched state |
215 // since after stopping the player the player state will move to pre-fetched state |
208 changePlayerState(PREFETCHED); |
216 changePlayerState(PREFETCHED); |
209 iPlayerListenerImpl.postEvent(PlayerListener.STOPPED, new Long(iMediaTime * 10000)); |
217 //iPlayerListenerImpl.postEvent(PlayerListener.STOPPED, new Long(iMediaTime * 10000)); |
|
218 iPlayerListenerImpl.postEvent(PlayerListener.STOPPED, new Long(iMediaTime)); |
210 } |
219 } |
211 |
220 |
212 /** |
221 /** |
213 * Function of InternalPlayer interface |
222 * Function of InternalPlayer interface |
214 */ |
223 */ |
270 } |
278 } |
271 |
279 |
272 /** |
280 /** |
273 * |
281 * |
274 */ |
282 */ |
275 |
283 GC gc = null; |
276 public void start() throws MediaException |
284 public void start() throws MediaException |
277 { |
285 { |
278 final String DEBUG_STR = "AnimationPlayer::start()"; |
286 final String DEBUG_STR = "AnimationPlayer::start()"; |
279 final long inTime = System.currentTimeMillis(); |
287 // final long inTime = System.currentTimeMillis(); |
280 |
|
281 prefetch(); |
288 prefetch(); |
282 // Only prefetched player may be started. If player is already started |
289 // Only prefetched player may be started. If player is already started |
283 // this method returns silently. |
290 // this method returns silently. |
284 if (getState() == PREFETCHED) |
291 if (getState() == PREFETCHED) |
285 { |
292 { |
286 //initialize(); |
293 //initialize(); |
287 changePlayerState(STARTED); |
294 changePlayerState(STARTED); |
288 Thread thread = new Thread("Animation") |
295 Thread thread = new Thread("Animation") |
289 { |
296 { |
290 int loopCount = iCurrentLoopCount; |
297 int loopCount = iCurrentLoopCount; |
291 GC gc = null; |
|
292 public void run() |
298 public void run() |
293 { |
299 { |
294 //changePlayerState(STARTED); |
300 //changePlayerState(STARTED); |
295 final int noOfFrames = iImageData.length; |
301 final int noOfFrames = iImageData.length; |
296 while (iState == STARTED) |
302 while (iState == STARTED) |
297 { |
303 { |
298 final int delayTimeForNextFrame = iImageData[iFrameIndex].delayTime; |
304 final int delayTimeForNextFrame = iImageData[iFrameIndex].delayTime*10000 ; |
299 // Since we are going to display first frame, notify all |
305 // Since we are going to display first frame, notify all |
300 // PlayerListener that Player has started |
306 // PlayerListener that Player has started |
301 if (iFrameIndex == 0) |
307 if (iFrameIndex == 0) |
302 { |
308 { |
|
309 iMediaTime=0; |
303 iPlayerListenerImpl.postEvent( |
310 iPlayerListenerImpl.postEvent( |
304 PlayerListener.STARTED, new Long( |
311 PlayerListener.STARTED, new Long(0)); |
305 iMediaTime * 10000)); |
312 |
306 } |
313 } |
307 if (iDisplay != null) |
314 if (iDisplay != null) |
308 { |
315 { |
309 iDisplay.syncExec(new Runnable() |
316 iDisplay.syncExec(new Runnable() |
310 { |
317 { |
311 public void run() |
318 public void run() |
312 { |
319 { |
313 if (gc == null) |
320 // For out of memory issue in case of full screen, we are scaling the image |
314 gc = new GC(iImage); |
321 // while displaying it. |
315 Image tempImage = new Image(iDisplay,iImageData[iFrameIndex]); |
322 ImageData tempImageData =iImageData[iFrameIndex] ; |
|
323 if (iSourceDimension.x!=iCurrentVideoDimension.x || iSourceDimension.x!=iCurrentVideoDimension.x) |
|
324 { |
|
325 tempImageData = iImageData[iFrameIndex].scaledTo(iCurrentVideoDimension.x , iCurrentVideoDimension.y); |
|
326 } |
|
327 Image tempImage = new Image(iDisplay,tempImageData); |
|
328 //Image tempImage = new Image(iDisplay,iImageData[iFrameIndex]); |
316 gc.drawImage(tempImage, 0, 0); |
329 gc.drawImage(tempImage, 0, 0); |
317 tempImage.dispose(); |
330 tempImage.dispose(); |
318 iFrameIndex = (iFrameIndex + 1) % noOfFrames; |
331 iFrameIndex = (iFrameIndex + 1) % noOfFrames; |
319 if (iControl != null) |
332 if (iControl != null) |
320 { |
333 { |
322 } |
335 } |
323 iMediaTime += delayTimeForNextFrame; |
336 iMediaTime += delayTimeForNextFrame; |
324 } |
337 } |
325 }); |
338 }); |
326 } |
339 } |
327 else// if the initDisplayMode is not called yer |
340 else// if the initDisplayMode is not called yet |
328 { |
341 { |
329 iFrameIndex = (iFrameIndex + 1) % noOfFrames; |
342 iFrameIndex = (iFrameIndex + 1) % noOfFrames; |
330 iMediaTime += delayTimeForNextFrame; |
343 iMediaTime += delayTimeForNextFrame; |
331 } |
344 } |
332 try |
345 try |
333 { |
346 { |
334 Thread.sleep(delayTimeForNextFrame * 10); |
347 Thread.sleep(delayTimeForNextFrame / 1000); |
335 } |
348 } |
336 catch (InterruptedException e) |
349 catch (InterruptedException e) |
337 { |
350 { |
338 // TODO Auto-generated catch block |
|
339 e.printStackTrace(); |
351 e.printStackTrace(); |
340 } |
352 } |
341 // post EOM event |
353 // post EOM event |
342 if (iFrameIndex == 0) |
354 if (iFrameIndex == 0) |
343 { |
355 { |
350 } |
362 } |
351 // send the END_OF_MEDIA event to all |
363 // send the END_OF_MEDIA event to all |
352 // listener |
364 // listener |
353 iPlayerListenerImpl.postEvent( |
365 iPlayerListenerImpl.postEvent( |
354 PlayerListener.END_OF_MEDIA, |
366 PlayerListener.END_OF_MEDIA, |
355 new Long(iMediaTime * 10000)); |
367 new Long(iMediaTime)); |
356 iMediaTime = 0; |
|
357 } |
368 } |
358 if (iAnimationObserver!=null) |
369 if (iAnimationObserver!=null) |
359 { |
370 { |
360 iAnimationObserver.animationAdvanced(iMediaTime*10000); |
371 iAnimationObserver.animationAdvanced(iMediaTime); |
361 } |
372 } |
362 }// end of while loop |
373 }// end of while loop |
363 iCurrentLoopCount = loopCount; |
374 iCurrentLoopCount = loopCount; |
364 // Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo, DEBUG_STR |
|
365 |
|
366 } |
375 } |
367 }; |
376 }; |
368 thread.start(); |
377 thread.start(); |
369 } |
378 } |
370 // Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,DEBUG_STR + "-"); |
|
371 } |
379 } |
372 |
380 |
373 /** |
381 /** |
374 * State of the player should be changed from this function only. |
382 * State of the player should be changed from this function only. |
375 * @param aState |
383 * @param aState |
571 * It is getting created, when initDisplayMode of VideoControl class is called. |
579 * It is getting created, when initDisplayMode of VideoControl class is called. |
572 */ |
580 */ |
573 public void notifyDisplayAvailable(Display aDisplay) |
581 public void notifyDisplayAvailable(Display aDisplay) |
574 { |
582 { |
575 iDisplay= aDisplay; |
583 iDisplay= aDisplay; |
576 iImage=new Image(iDisplay, iImageData[0]); |
584 //iImage=new Image(iDisplay, iImageData[0]); |
|
585 iImage=new Image(iDisplay, iImageData[iFrameIndex]); |
|
586 iDisplay.syncExec(new Runnable() |
|
587 { |
|
588 public void run() |
|
589 { |
|
590 gc = new GC(iImage); |
|
591 } |
|
592 }); |
577 } |
593 } |
578 /** |
594 /** |
579 * Notified when the control is available |
595 * Notified when the control is available |
580 * @param aControl(this is eSWTControl ) |
596 * @param aControl(this is eSWTControl ) |
581 */ |
597 */ |
591 * This function will be called from setDisplaySize(int width, int height) of animation/VideoControl class |
607 * This function will be called from setDisplaySize(int width, int height) of animation/VideoControl class |
592 * When MIDlet developer will try to alter the size of the image |
608 * When MIDlet developer will try to alter the size of the image |
593 * @param width : to be set of the video(Animated GIF) |
609 * @param width : to be set of the video(Animated GIF) |
594 * @param height : height to be set of video(Animated GIF) |
610 * @param height : height to be set of video(Animated GIF) |
595 */ |
611 */ |
596 void updateImageData(int width, int height) |
612 void updateImageData(int aWidth, int aHeight) |
597 { |
613 { |
598 int noOfFrames= iImageData.length; |
614 // int noOfFrames= iImageData.length; |
599 for (int i=0; i<noOfFrames; i++) |
615 // for (int i=0; i<noOfFrames; i++) |
600 { |
616 // { |
601 iImageData[i]=iImageData[i].scaledTo(width, height); |
617 // iImageData[i]=iImageData[i].scaledTo(aWidth, aHeight); |
602 } |
618 // } |
603 iImage=new Image(iDisplay, iImageData[iFrameIndex]); |
619 // iImage=new Image(iDisplay, iImageData[iFrameIndex]); |
|
620 iCurrentVideoDimension.x=aWidth; |
|
621 iCurrentVideoDimension.y= aHeight; |
|
622 iImage=new Image(iDisplay, iImageData[iFrameIndex].scaledTo(aWidth, aHeight)); |
604 } |
623 } |
605 |
624 |
606 /** |
625 /** |
607 * Overloaded function for calling the above function |
626 * Overloaded function for calling the above function |
608 */ |
627 */ |
639 /** |
658 /** |
640 * Returns Point object, which contains the width and height of the image |
659 * Returns Point object, which contains the width and height of the image |
641 * Called from VideoControl to get the image width and height, |
660 * Called from VideoControl to get the image width and height, |
642 * so that Item will be created exactly of same dimension |
661 * so that Item will be created exactly of same dimension |
643 */ |
662 */ |
644 Point getImageDimension() |
663 Point getCurrentVideoDimension() |
645 { |
664 { |
646 // return iCurrentVideoDimension; |
665 return iCurrentVideoDimension; |
647 return new org.eclipse.swt.graphics.Point(iImageData[0].width, iImageData[0].height); |
666 // return new org.eclipse.swt.graphics.Point(iImageData[0].width, iImageData[0].height); |
648 } |
667 } |
649 |
668 |
650 |
669 |
651 int getTotalNumberFrames() |
670 int getTotalNumberFrames() |
652 { |
671 { |
747 void setiIsControlVisible(boolean iIsControlVisible) |
765 void setiIsControlVisible(boolean iIsControlVisible) |
748 { |
766 { |
749 this.iIsControlVisible = iIsControlVisible; |
767 this.iIsControlVisible = iIsControlVisible; |
750 } |
768 } |
751 /** |
769 /** |
752 * Called from |
770 * Called from StopTimeControl.animationAdvanced(long), once the stopped time is greater than or equal media time. |
753 */ |
771 */ |
754 void postEvent(long aMediaTime) |
772 void postEvent(long aMediaTime) |
755 { |
773 { |
756 changePlayerState(PREFETCHED); |
774 changePlayerState(PREFETCHED); |
757 iPlayerListenerImpl.postEvent(PlayerListener.STOPPED_AT_TIME, new Long( |
775 iPlayerListenerImpl.postEvent(PlayerListener.STOPPED_AT_TIME, new Long( |