PageRenderTime 103ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/mediaElement/src/flash/htmlelements/VideoElement.as

http://buddypress-media.googlecode.com/
ActionScript | 388 lines | 273 code | 91 blank | 24 comment | 41 complexity | 296b7fa35426354731fb0b402464ed82 MD5 | raw file
Possible License(s): AGPL-1.0, Apache-2.0, GPL-2.0, LGPL-2.1
  1. package htmlelements
  2. {
  3. import flash.display.Sprite;
  4. import flash.events.*;
  5. import flash.net.NetConnection;
  6. import flash.net.NetStream;
  7. import flash.media.Video;
  8. import flash.media.SoundTransform;
  9. import flash.utils.Timer;
  10. import FlashMediaElement;
  11. import HtmlMediaEvent;
  12. public class VideoElement extends Sprite implements IMediaElement
  13. {
  14. private var _currentUrl:String = "";
  15. private var _autoplay:Boolean = true;
  16. private var _preload:String = "";
  17. private var _connection:NetConnection;
  18. private var _stream:NetStream;
  19. private var _video:Video;
  20. private var _element:FlashMediaElement;
  21. private var _soundTransform;
  22. private var _oldVolume:Number = 1;
  23. // event values
  24. private var _duration:Number = 0;
  25. private var _framerate:Number;
  26. private var _isPaused:Boolean = true;
  27. private var _isEnded:Boolean = false;
  28. private var _volume:Number = 1;
  29. private var _isMuted:Boolean = false;
  30. private var _bytesLoaded:Number = 0;
  31. private var _bytesTotal:Number = 0;
  32. private var _bufferedTime:Number = 0;
  33. private var _bufferEmpty:Boolean = false;
  34. private var _videoWidth:Number = -1;
  35. private var _videoHeight:Number = -1;
  36. private var _timer:Timer;
  37. private var _isRTMP:Boolean = false;
  38. private var _isConnected:Boolean = false;
  39. private var _playWhenConnected:Boolean = false;
  40. private var _hasStartedPlaying:Boolean = false;
  41. public function get video():Video {
  42. return _video;
  43. }
  44. public function get videoHeight():Number {
  45. return _videoHeight;
  46. }
  47. public function get videoWidth():Number {
  48. return _videoWidth;
  49. }
  50. public function duration():Number {
  51. return _duration;
  52. }
  53. public function currentTime():Number {
  54. if (_stream != null) {
  55. return _stream.time;
  56. } else {
  57. return 0;
  58. }
  59. }
  60. // (1) load()
  61. // calls _connection.connect();
  62. // waits for NetConnection.Connect.Success
  63. // _stream gets created
  64. public function VideoElement(element:FlashMediaElement, autoplay:Boolean, preload:String, timerRate:Number, startVolume:Number)
  65. {
  66. _element = element;
  67. _autoplay = autoplay;
  68. _volume = startVolume;
  69. _preload = preload;
  70. _video = new Video();
  71. addChild(_video);
  72. _connection = new NetConnection();
  73. _connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
  74. _connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
  75. //_connection.connect(null);
  76. _timer = new Timer(timerRate);
  77. _timer.addEventListener("timer", timerHandler);
  78. }
  79. private function timerHandler(e:TimerEvent) {
  80. _bytesLoaded = _stream.bytesLoaded;
  81. _bytesTotal = _stream.bytesTotal;
  82. if (!_isPaused)
  83. sendEvent(HtmlMediaEvent.TIMEUPDATE);
  84. trace("bytes", _bytesLoaded, _bytesTotal);
  85. if (_bytesLoaded < _bytesTotal)
  86. sendEvent(HtmlMediaEvent.PROGRESS);
  87. }
  88. // internal events
  89. private function netStatusHandler(event:NetStatusEvent):void {
  90. trace("netStatus", event.info.code);
  91. switch (event.info.code) {
  92. case "NetStream.Buffer.Empty":
  93. _bufferEmpty = true;
  94. _isEnded ? sendEvent(HtmlMediaEvent.ENDED) : null;
  95. break;
  96. case "NetStream.Buffer.Full":
  97. _bytesLoaded = _stream.bytesLoaded;
  98. _bytesTotal = _stream.bytesTotal;
  99. _bufferEmpty = false;
  100. sendEvent(HtmlMediaEvent.PROGRESS);
  101. break;
  102. case "NetConnection.Connect.Success":
  103. connectStream();
  104. break;
  105. case "NetStream.Play.StreamNotFound":
  106. trace("Unable to locate video");
  107. break;
  108. // STREAM
  109. case "NetStream.Play.Start":
  110. _isPaused = false;
  111. sendEvent(HtmlMediaEvent.LOADEDDATA);
  112. sendEvent(HtmlMediaEvent.CANPLAY);
  113. sendEvent(HtmlMediaEvent.PLAY);
  114. sendEvent(HtmlMediaEvent.PLAYING);
  115. _timer.start();
  116. break;
  117. case "NetStream.Seek.Notify":
  118. sendEvent(HtmlMediaEvent.SEEKED);
  119. break;
  120. case "NetStream.Pause.Notify":
  121. _isPaused = true;
  122. sendEvent(HtmlMediaEvent.PAUSE);
  123. break;
  124. case "NetStream.Play.Stop":
  125. _isEnded = true;
  126. _isPaused = false;
  127. _timer.stop();
  128. _bufferEmpty ? sendEvent(HtmlMediaEvent.ENDED) : null;
  129. break;
  130. }
  131. }
  132. private function securityErrorHandler(event:SecurityErrorEvent):void {
  133. trace("securityErrorHandler: " + event);
  134. }
  135. private function asyncErrorHandler(event:AsyncErrorEvent):void {
  136. // ignore AsyncErrorEvent events.
  137. }
  138. private function onMetaDataHandler(info:Object):void {
  139. _duration = info.duration;
  140. _framerate = info.framerate;
  141. _videoWidth = info.width;
  142. _videoHeight = info.height;
  143. // set size?
  144. sendEvent(HtmlMediaEvent.LOADEDMETADATA);
  145. }
  146. // interface members
  147. public function setSrc(url:String):void {
  148. if (_isConnected && _stream) {
  149. // stop and restart
  150. _stream.pause();
  151. }
  152. _currentUrl = url;
  153. _isRTMP = !!_currentUrl.match(/^rtmp(s|t|e|te)?\:\/\//);
  154. _isConnected = false;
  155. _hasStartedPlaying = false;
  156. }
  157. public function load():void {
  158. // disconnect existing stream and connection
  159. if (_isConnected && _stream) {
  160. _stream.pause();
  161. _stream.close();
  162. _connection.close();
  163. }
  164. _isConnected = false;
  165. // start new connection
  166. if (_isRTMP) {
  167. _connection.connect(_currentUrl.replace(/\/[^\/]+$/,"/"));
  168. } else {
  169. _connection.connect(null);
  170. }
  171. // in a few moments the "NetConnection.Connect.Success" event will fire
  172. // and call createConnection which finishes the "load" sequence
  173. sendEvent(HtmlMediaEvent.LOADSTART);
  174. }
  175. private function connectStream():void {
  176. trace("connectStream");
  177. _stream = new NetStream(_connection);
  178. // explicitly set the sound since it could have come before the connection was made
  179. _soundTransform = new SoundTransform(_volume);
  180. _stream.soundTransform = _soundTransform;
  181. _stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); // same event as connection
  182. _stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
  183. var customClient:Object = new Object();
  184. customClient.onMetaData = onMetaDataHandler;
  185. _stream.client = customClient;
  186. _video.attachNetStream(_stream);
  187. // start downloading without playing )based on preload and play() hasn't been called)
  188. // I wish flash had a load() command to make this less awkward
  189. if (_preload != "none" && !_playWhenConnected) {
  190. _stream.play(_currentUrl, 0, 0);
  191. _stream.pause();
  192. _isPaused = true;
  193. sendEvent(HtmlMediaEvent.PAUSE); // have to send this because the "playing" event gets sent via event handlers
  194. }
  195. _isConnected = true;
  196. if (_playWhenConnected && !_hasStartedPlaying) {
  197. play();
  198. _playWhenConnected = false;
  199. }
  200. }
  201. public function play():void {
  202. if (!_hasStartedPlaying && !_isConnected) {
  203. _playWhenConnected = true;
  204. load();
  205. return;
  206. }
  207. if (_hasStartedPlaying) {
  208. if (_isPaused) {
  209. _stream.resume();
  210. _timer.start();
  211. _isPaused = false;
  212. sendEvent(HtmlMediaEvent.PLAY);
  213. sendEvent(HtmlMediaEvent.PLAYING);
  214. }
  215. } else {
  216. if (_isRTMP) {
  217. _stream.play(_currentUrl.split("/").pop());
  218. } else {
  219. _stream.play(_currentUrl);
  220. }
  221. _timer.start();
  222. _isPaused = false;
  223. _hasStartedPlaying = true;
  224. // don't toss play/playing events here, because we haven't sent a
  225. // canplay / loadeddata event yet. that'll be handled in the net
  226. // event listener
  227. }
  228. }
  229. public function pause():void {
  230. if (_stream == null)
  231. return;
  232. _stream.pause();
  233. _isPaused = true;
  234. if (_bytesLoaded == _bytesTotal) {
  235. _timer.stop();
  236. }
  237. _isPaused = true;
  238. sendEvent(HtmlMediaEvent.PAUSE);
  239. }
  240. public function stop():void {
  241. if (_stream == null)
  242. return;
  243. _stream.close();
  244. _isPaused = false;
  245. _timer.stop();
  246. sendEvent(HtmlMediaEvent.STOP);
  247. }
  248. public function setCurrentTime(pos:Number):void {
  249. if (_stream == null)
  250. return;
  251. sendEvent(HtmlMediaEvent.SEEKING);
  252. _stream.seek(pos);
  253. sendEvent(HtmlMediaEvent.TIMEUPDATE);
  254. }
  255. public function setVolume(volume:Number):void {
  256. if (_stream != null) {
  257. _soundTransform = new SoundTransform(volume);
  258. _stream.soundTransform = _soundTransform;
  259. }
  260. _volume = volume;
  261. _isMuted = (_volume == 0);
  262. sendEvent(HtmlMediaEvent.VOLUMECHANGE);
  263. }
  264. public function setMuted(muted:Boolean):void {
  265. if (_isMuted == muted)
  266. return;
  267. if (muted) {
  268. _oldVolume = (_stream == null) ? _oldVolume : _stream.soundTransform.volume;
  269. setVolume(0);
  270. } else {
  271. setVolume(_oldVolume);
  272. }
  273. _isMuted = muted;
  274. }
  275. private function sendEvent(eventName:String) {
  276. // calculate this to mimic HTML5
  277. _bufferedTime = _bytesLoaded / _bytesTotal * _duration;
  278. // build JSON
  279. var values:String =
  280. "duration:" + _duration +
  281. ",framerate:" + _framerate +
  282. ",currentTime:" + (_stream != null ? _stream.time : 0) +
  283. ",muted:" + _isMuted +
  284. ",paused:" + _isPaused +
  285. ",ended:" + _isEnded +
  286. ",volume:" + _volume +
  287. ",src:\"" + _currentUrl + "\"" +
  288. ",bytesTotal:" + _bytesTotal +
  289. ",bufferedBytes:" + _bytesLoaded +
  290. ",bufferedTime:" + _bufferedTime +
  291. ",videoWidth:" + _videoWidth +
  292. ",videoHeight:" + _videoHeight +
  293. "";
  294. _element.sendEvent(eventName, values);
  295. }
  296. }
  297. }