PageRenderTime 4022ms CodeModel.GetById 195ms RepoModel.GetById 0ms app.codeStats 1ms

/MediaKit/RCVideo.hx

http://ralcr.googlecode.com/
Haxe | 409 lines | 273 code | 70 blank | 66 comment | 52 complexity | 577d45f4ec425e7f9c8ab8879b9a9e62 MD5 | raw file
  1. //
  2. // VideoPlayer
  3. //
  4. // Created by Baluta Cristian on 2007-10-18.
  5. // Copyright (c) 2007 http://ralcr.com.
  6. // This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
  7. //
  8. #if flash
  9. import flash.display.Sprite;
  10. import flash.events.Event;
  11. import flash.events.NetStatusEvent;
  12. import flash.events.SecurityErrorEvent;
  13. import flash.events.AsyncErrorEvent;
  14. import flash.events.TimerEvent;
  15. import flash.media.Video;
  16. import flash.net.NetConnection;
  17. import flash.net.NetStream;
  18. import flash.utils.Timer;
  19. import flash.media.SoundTransform;
  20. class RCVideo extends RCView, implements RCVideoInterface {
  21. public static var BUFFER_TIME :Int = 2;
  22. public static var DEFAULT_VOLUME :Float = 0.8;
  23. public static var DISPLAY_TIMER_UPDATE_DELAY :Int = 1000;
  24. var videoURL :String;
  25. var inited_ :Bool;
  26. var loaded_ :Bool;
  27. var seeking_ :Bool;
  28. var volume_ :Float;
  29. var timer :Timer;
  30. var nc :NetConnection;
  31. var ns :NetStream;
  32. var video :Video;
  33. public var background :RCRectangle;
  34. public var updateTime :Int;
  35. public var isPlaying :Bool;
  36. public var aspectRatio :Null<Float>;
  37. public var time :Float;
  38. public var duration :Float;
  39. public var percentLoaded :Int;
  40. public var percentPlayed :Int;
  41. public var statusMessage :String;
  42. public var secureToken :String;// This is sent by the server and is stored here for later access
  43. public var volume (getVolume, setVolume) :Float;
  44. /**
  45. * Dispatch events
  46. */
  47. dynamic public function onInit () :Void {}
  48. dynamic public function onError () :Void {}
  49. dynamic public function videoDidStart () :Void {}
  50. dynamic public function videoDidStop () :Void {}
  51. dynamic public function videoDidFinishPlaying () :Void {}
  52. dynamic public function onLoadingProgress () :Void {}
  53. dynamic public function onPlayingProgress () :Void {}
  54. dynamic public function onBufferEmpty () :Void {}
  55. dynamic public function onBufferFull () :Void {}
  56. dynamic public function streamWantsSecureToken () :Void {}
  57. public function new (x, y, URL:String, ?w:Null<Float>, ?h:Null<Float>) {
  58. super (x, y, w, h);
  59. this.videoURL = URL;
  60. this.inited_ = false;
  61. this.loaded_ = false;
  62. this.seeking_ = false;
  63. this.isPlaying = false;
  64. this.percentLoaded = 0;
  65. this.percentPlayed = 0;
  66. this.time = 0.0;
  67. this.duration = 0.0;
  68. this.statusMessage = "Not inited";
  69. this.updateTime = DISPLAY_TIMER_UPDATE_DELAY;
  70. volume_ = DEFAULT_VOLUME;
  71. this.addChild ( background = new RCRectangle(0, 0, w, h, 0x000000) );
  72. }
  73. // sets up the player for video files
  74. public function init () :Void {
  75. // Create timer to update all visual parts of the player
  76. timer = new Timer ( updateTime );
  77. timer.addEventListener (TimerEvent.TIMER, loop);
  78. // Create a new net connection
  79. // add event listeners
  80. // connect to null (because we don't have a media server)
  81. nc = new NetConnection();
  82. nc.addEventListener (NetStatusEvent.NET_STATUS, netStatusHandler);
  83. nc.addEventListener (SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
  84. nc.connect ( null );
  85. }
  86. function netStatusHandler (e:NetStatusEvent) :Void {
  87. statusMessage = e.info.description;
  88. //trace ("RCVideo - "+e.info.code+" - "+statusMessage);
  89. //trace("e.info.secureToken "+e.info.secureToken);
  90. switch (e.info.code) {
  91. case "NetConnection.Connect.Success":
  92. if (e.info.secureToken != null) {
  93. secureToken = e.info.secureToken;
  94. streamWantsSecureToken();
  95. }
  96. initHandler();
  97. case "NetConnection.Connect.Rejected": onError();
  98. case "NetStream.Play.StreamNotFound": onError();
  99. case "NetStream.Play.Start": videoDidStart();
  100. case "NetStream.Play.Stop": videoDidStop();
  101. case "NetStream.Play.Complete": trace("NetStream.Play.Complete");
  102. case "NetStream.Buffer.Full": onBufferFull();
  103. case "NetStream.Buffer.Empty": onBufferEmpty();
  104. case "NetStream.Buffer.Flush": null;
  105. case "NetStream.Seek.InvalidTime": null;
  106. case "NetStream.Play.InsufficientBW": trace("insufficiend bandwith");
  107. }
  108. }
  109. public function secureTokenResponse (token:String) :Void {
  110. nc.call ("secureTokenResponse", null, token);
  111. }
  112. function initHandler () :Void {
  113. var customClient:Dynamic = {};
  114. customClient.onCuePoint = onCuePoint;
  115. customClient.onMetaData = onMetaData;
  116. //customClient.onTextData = onTextDataHandler;
  117. ns = new NetStream ( nc );
  118. ns.addEventListener (NetStatusEvent.NET_STATUS, netStatusHandler);
  119. ns.addEventListener (AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
  120. ns.client = customClient;// call onMetaData and onCuePoint
  121. ns.bufferTime = BUFFER_TIME;
  122. video = new Video();
  123. video.attachNetStream ( ns );
  124. video.smoothing = true;
  125. layer.addChild ( video );
  126. setVolume ( volume_ );
  127. onInit();
  128. }
  129. function securityErrorHandler (e:SecurityErrorEvent) :Void {
  130. statusMessage = e.text;
  131. onError();
  132. }
  133. function asyncErrorHandler (e:AsyncErrorEvent) :Void {
  134. statusMessage = e.text;
  135. onError();
  136. }
  137. /**
  138. * Main loop which dispatch some events: loading progress, playing progress
  139. */
  140. function loop (e:TimerEvent) :Void { try {
  141. if (ns == null) return;
  142. if (!seeking_) {
  143. time = ns.time;
  144. percentPlayed = Math.round (time / duration * 100);
  145. onPlayingProgress();
  146. //this.dispatchEvent ( new VideoEvent (VideoEvent.PLAYING_PROGRESS, time, duration));
  147. //trace(time+", "+duration);
  148. // Fire from here the event that the video did finish playing.
  149. // The NetStream.Play.Stop is fired too often
  150. if (Math.abs (duration - time) <= 0.1 && duration > 0) {trace(time+", "+duration);
  151. stopVideo();
  152. videoDidFinishPlaying();
  153. }
  154. }
  155. // update the loading progress
  156. if (!loaded_) {
  157. percentLoaded = Math.round (ns.bytesLoaded / ns.bytesTotal * 100);
  158. if (percentLoaded >= 100) loaded_ = true;
  159. onLoadingProgress();
  160. //this.dispatchEvent ( new VideoEvent (VideoEvent.LOADING_PROGRESS, time, duration));
  161. }
  162. } catch (e:Dynamic) {
  163. trace(e);
  164. var stack = haxe.Stack.exceptionStack();
  165. trace (haxe.Stack.toString ( stack ));
  166. }
  167. }
  168. /**
  169. * Listeners for metaData and cuePoints
  170. */
  171. function onMetaData (meta:Dynamic) :Void {
  172. trace("RCVideo medatada received. Now ready to play.");
  173. if (seeking_) return;
  174. if (duration != 0) return;
  175. aspectRatio = (meta.width != null && meta.height != null) ? (meta.width / meta.height) : null;
  176. duration = meta.duration;
  177. trace("aspectRatio "+aspectRatio);
  178. for (m in Reflect.fields(meta)) trace(m + " -> "+Reflect.field(meta, m));
  179. // Check the size specified by the user
  180. if (size.width != 0 && size.height != 0) {
  181. setSize (size.width, size.height);
  182. }
  183. // Otherwise set it to the size from metadata
  184. else setSize (meta.width, meta.height);
  185. // Now that we have the metadata, we can start the timer
  186. timer.start();
  187. //this.dispatchEvent ( new MetaEvent (MetaEvent.META, meta) );
  188. }
  189. function onCuePoint (cue:Dynamic) :Void {
  190. //trace(Std.string(cue));
  191. //this.dispatchEvent ( new CuePoint (CuePoint.CUE_POINT, cue) );
  192. }
  193. /**
  194. * Control the player
  195. */
  196. public function startVideo (?file:String) :Void {
  197. if (ns == null) return;
  198. // check's, if the flv has already begun
  199. // to download. if so, resume playback, else
  200. // load the file
  201. if (!inited_) {
  202. ns.play (file != null ? file : videoURL);
  203. inited_ = true;
  204. }
  205. else {
  206. ns.resume();
  207. timer.start();
  208. }
  209. isPlaying = true;
  210. }
  211. public function replayVideo () : Void {
  212. // Pause netstream, set time position to zero
  213. if (ns != null) {
  214. seeking_ = true;
  215. ns.pause();
  216. ns.seek ( 0 );// This may cause the metadata to be called again
  217. haxe.Timer.delay (doReplay, 2);
  218. //doReplay();
  219. }
  220. }
  221. function doReplay(){
  222. ns.resume();
  223. isPlaying = true;
  224. seeking_ = false;
  225. timer.start();
  226. }
  227. public function stopVideo () : Void {
  228. pauseVideo();
  229. if (ns != null) {
  230. ns.seek ( duration );
  231. }
  232. }
  233. /**
  234. * Pause the video
  235. */
  236. public function pauseVideo () :Void {
  237. if (ns != null) {
  238. ns.pause();
  239. timer.stop();
  240. isPlaying = false;
  241. }
  242. }
  243. /**
  244. * Resume video from where was stopped
  245. */
  246. public function resumeVideo () :Void {
  247. if (ns != null) {
  248. ns.resume();
  249. timer.start();
  250. isPlaying = true;
  251. }
  252. }
  253. /**
  254. * Pause/unpause the video
  255. */
  256. public function togglePause () :Void {
  257. if (isPlaying)
  258. pauseVideo();
  259. else
  260. resumeVideo();
  261. }
  262. /**
  263. * Seek video to time (sec)
  264. */
  265. public function seekTo (time:Float) :Bool {
  266. seeking_ = true;
  267. if (time > duration * percentLoaded / 100) return false;//Do not seek beyound current loaded
  268. if (ns != null)
  269. ns.seek ( time );
  270. return true;
  271. }
  272. public function stopSeeking () :Void {
  273. seeking_ = false;
  274. }
  275. /**
  276. * Control the volume
  277. */
  278. public function getVolume () :Float {
  279. return volume_;
  280. }
  281. public function setVolume (volume:Float) :Float {
  282. volume_ = volume > 1 ? 1 : volume;
  283. if (ns != null)
  284. ns.soundTransform = new SoundTransform ( volume_ );
  285. return volume_;
  286. }
  287. /**
  288. * Sets the size of the video object and maintains its aspect ratio
  289. */
  290. public function setSize (w, h) :Void {
  291. size.width = w;
  292. size.height = h;
  293. background.width = w;
  294. background.height = h;
  295. var holderAspectRatio = w / h;
  296. if (aspectRatio != null) {
  297. if (aspectRatio < holderAspectRatio) {
  298. video.height = h;
  299. video.width = h * aspectRatio;
  300. }
  301. else {
  302. video.width = w;
  303. video.height = w / aspectRatio;
  304. }
  305. }
  306. else {
  307. video.width = w;
  308. video.height = h;
  309. }
  310. // Center the video object in the provided width and height
  311. video.x = Math.round ((w - video.width) / 2);
  312. video.y = Math.round ((h - video.height) / 2);
  313. }
  314. /**
  315. * Cleanup the mess, stop the player
  316. */
  317. override public function destroy () :Void {
  318. if (timer != null) {
  319. timer.stop();
  320. timer.removeEventListener (TimerEvent.TIMER, loop);
  321. }
  322. if (ns != null) {
  323. ns.removeEventListener (NetStatusEvent.NET_STATUS, netStatusHandler);
  324. ns.removeEventListener (AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
  325. ns.close();
  326. ns = null;
  327. }
  328. if (nc != null) {
  329. nc.removeEventListener (NetStatusEvent.NET_STATUS, netStatusHandler);
  330. nc.removeEventListener (SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
  331. nc = null;
  332. }
  333. video = null;
  334. super.destroy();
  335. }
  336. }
  337. #elseif js
  338. typedef RCVideo = JSVideo;
  339. #end