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

/backend/web/filemanager/js/jPlayer/actionscript/happyworm/jPlayer/JplayerMp3.as

https://gitlab.com/angrydevops/workerpro
ActionScript | 367 lines | 332 code | 14 blank | 21 comment | 79 complexity | 420af37f469de61e8c25c3029e5b7b4d MD5 | raw file
  1. /*
  2. * jPlayer Plugin for jQuery JavaScript Library
  3. * http://www.jplayer.org
  4. *
  5. * Copyright (c) 2009 - 2013 Happyworm Ltd
  6. * Licensed under the MIT license.
  7. * http://opensource.org/licenses/MIT
  8. *
  9. * Author: Mark J Panaghiston
  10. * Date: 28th May 2013
  11. */
  12. package happyworm.jPlayer {
  13. import flash.display.Sprite;
  14. import flash.media.Sound;
  15. import flash.media.SoundChannel;
  16. import flash.media.SoundLoaderContext;
  17. import flash.media.SoundTransform;
  18. import flash.net.URLRequest;
  19. import flash.utils.Timer;
  20. import flash.errors.IOError;
  21. import flash.events.*;
  22. public class JplayerMp3 extends Sprite {
  23. private var mySound:Sound = new Sound();
  24. private var myChannel:SoundChannel = new SoundChannel();
  25. private var myContext:SoundLoaderContext = new SoundLoaderContext(3000, false);
  26. private var myTransform:SoundTransform = new SoundTransform();
  27. private var myRequest:URLRequest = new URLRequest();
  28. private var timeUpdateTimer:Timer = new Timer(250, 0); // Matched to HTML event freq
  29. private var progressTimer:Timer = new Timer(250, 0); // Matched to HTML event freq
  30. private var seekingTimer:Timer = new Timer(100, 0); // Internal: How often seeking is checked to see if it is over.
  31. private var playingTimer:Timer = new Timer(100, 0); // Internal: How often waiting/playing is checked.
  32. private var waitingTimer:Timer = new Timer(3000, 0); // Internal: Check from loadstart to loadOpen. Generates a waiting event.
  33. public var myStatus:JplayerStatus = new JplayerStatus();
  34. public function JplayerMp3(volume:Number) {
  35. timeUpdateTimer.addEventListener(TimerEvent.TIMER, timeUpdateHandler);
  36. progressTimer.addEventListener(TimerEvent.TIMER, progressHandler);
  37. seekingTimer.addEventListener(TimerEvent.TIMER, seekingHandler);
  38. playingTimer.addEventListener(TimerEvent.TIMER, playingHandler);
  39. waitingTimer.addEventListener(TimerEvent.TIMER, waitingHandler);
  40. setVolume(volume);
  41. }
  42. public function setFile(src:String):void {
  43. this.dispatchEvent(new JplayerEvent(JplayerEvent.DEBUG_MSG, myStatus, "setFile: " + src));
  44. if(myStatus.isPlaying) {
  45. myChannel.stop();
  46. }
  47. progressUpdates(false);
  48. timeUpdates(false);
  49. waitingTimer.stop();
  50. try {
  51. mySound.close();
  52. } catch (err:IOError) {
  53. // Occurs if the file is either yet to be opened or has finished downloading.
  54. }
  55. mySound = null;
  56. mySound = new Sound();
  57. mySound.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
  58. mySound.addEventListener(Event.OPEN, loadOpen);
  59. mySound.addEventListener(Event.COMPLETE, loadComplete);
  60. myRequest = new URLRequest(src);
  61. myStatus.reset();
  62. myStatus.src = src;
  63. myStatus.srcSet = true;
  64. timeUpdateEvent();
  65. }
  66. public function clearFile():void {
  67. setFile("");
  68. myStatus.srcSet = false;
  69. }
  70. private function errorHandler(err:IOErrorEvent):void {
  71. // MP3 player needs to stop progress and timeupdate events as they are started before the error occurs.
  72. // NB: The MP4 player works differently and the error occurs before they are started.
  73. progressUpdates(false);
  74. timeUpdates(false);
  75. myStatus.error(); // Resets status except the src, and it sets srcError property.
  76. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_ERROR, myStatus));
  77. }
  78. private function loadOpen(e:Event):void {
  79. this.dispatchEvent(new JplayerEvent(JplayerEvent.DEBUG_MSG, myStatus, "loadOpen:"));
  80. waitingTimer.stop();
  81. myStatus.loading();
  82. if(myStatus.playOnLoad) {
  83. myStatus.playOnLoad = false; // Capture the flag
  84. // this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_LOADSTART, myStatus)); // So loadstart event happens before play event occurs.
  85. play();
  86. } else {
  87. // this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_LOADSTART, myStatus));
  88. pause();
  89. }
  90. progressUpdates(true);
  91. }
  92. private function loadComplete(e:Event):void {
  93. this.dispatchEvent(new JplayerEvent(JplayerEvent.DEBUG_MSG, myStatus, "loadComplete:"));
  94. myStatus.loaded();
  95. progressUpdates(false);
  96. progressEvent();
  97. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_CANPLAYTHROUGH, myStatus));
  98. }
  99. private function soundCompleteHandler(e:Event):void {
  100. myStatus.pausePosition = 0;
  101. myStatus.isPlaying = false;
  102. timeUpdates(false);
  103. timeUpdateEvent();
  104. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_ENDED, myStatus));
  105. }
  106. private function progressUpdates(active:Boolean):void {
  107. // Using a timer rather than Flash's load progress event, because that event gave data at about 200Hz. The 10Hz timer is closer to HTML5 norm.
  108. if(active) {
  109. progressTimer.start();
  110. } else {
  111. progressTimer.stop();
  112. }
  113. }
  114. private function progressHandler(e:TimerEvent):void {
  115. progressEvent();
  116. }
  117. private function progressEvent():void {
  118. this.dispatchEvent(new JplayerEvent(JplayerEvent.DEBUG_MSG, myStatus, "progressEvent:"));
  119. updateStatusValues();
  120. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_PROGRESS, myStatus));
  121. }
  122. private function timeUpdates(active:Boolean):void {
  123. if(active) {
  124. timeUpdateTimer.start();
  125. playingTimer.start();
  126. } else {
  127. timeUpdateTimer.stop();
  128. playingTimer.stop();
  129. }
  130. }
  131. private function timeUpdateHandler(e:TimerEvent):void {
  132. timeUpdateEvent();
  133. }
  134. private function timeUpdateEvent():void {
  135. updateStatusValues();
  136. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_TIMEUPDATE, myStatus));
  137. }
  138. private function seeking(active:Boolean):void {
  139. if(active) {
  140. seekingEvent();
  141. waitingEvent();
  142. seekingTimer.start();
  143. } else {
  144. seekingTimer.stop();
  145. }
  146. }
  147. private function seekingHandler(e:TimerEvent):void {
  148. if(myStatus.pausePosition <= getDuration()) {
  149. seekedEvent();
  150. seeking(false);
  151. if(myStatus.playOnSeek) {
  152. myStatus.playOnSeek = false; // Capture the flag.
  153. play();
  154. }
  155. } else if(myStatus.isLoaded && (myStatus.pausePosition > getDuration())) {
  156. // Illegal seek time
  157. seeking(false);
  158. seekedEvent();
  159. pause(0);
  160. }
  161. }
  162. private function seekingEvent():void {
  163. myStatus.isSeeking = true;
  164. updateStatusValues();
  165. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_SEEKING, myStatus));
  166. }
  167. private function seekedEvent():void {
  168. myStatus.isSeeking = false;
  169. updateStatusValues();
  170. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_SEEKED, myStatus));
  171. }
  172. private function playingHandler(e:TimerEvent):void {
  173. checkPlaying(false); // Without forcing playing event.
  174. }
  175. private function checkPlaying(force:Boolean):void {
  176. if(mySound.isBuffering) {
  177. if(!myStatus.isWaiting) {
  178. waitingEvent();
  179. }
  180. } else {
  181. if(myStatus.isWaiting || force) {
  182. playingEvent();
  183. }
  184. }
  185. }
  186. private function waitingEvent():void {
  187. myStatus.isWaiting = true;
  188. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_WAITING, myStatus));
  189. }
  190. private function playingEvent():void {
  191. myStatus.isWaiting = false;
  192. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_CANPLAY, myStatus));
  193. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_PLAYING, myStatus));
  194. }
  195. private function waitingHandler(e:TimerEvent):void {
  196. waitingTimer.stop();
  197. if(myStatus.playOnLoad) {
  198. waitingEvent();
  199. }
  200. }
  201. public function load():Boolean {
  202. if(myStatus.loadRequired()) {
  203. myStatus.startingDownload();
  204. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_LOADSTART, myStatus));
  205. waitingTimer.start();
  206. mySound.load(myRequest, myContext);
  207. return true;
  208. } else {
  209. return false;
  210. }
  211. }
  212. public function play(time:Number = NaN):Boolean {
  213. var wasPlaying:Boolean = myStatus.isPlaying;
  214. if(!isNaN(time) && myStatus.srcSet) {
  215. if(myStatus.isPlaying) {
  216. myChannel.stop();
  217. myStatus.isPlaying = false;
  218. }
  219. myStatus.pausePosition = time;
  220. }
  221. if(myStatus.isStartingDownload) {
  222. myStatus.playOnLoad = true; // Raise flag, captured in loadOpen()
  223. return true;
  224. } else if(myStatus.loadRequired()) {
  225. myStatus.playOnLoad = true; // Raise flag, captured in loadOpen()
  226. return load();
  227. } else if((myStatus.isLoading || myStatus.isLoaded) && !myStatus.isPlaying) {
  228. if(myStatus.isLoaded && myStatus.pausePosition > getDuration()) { // The time is invalid, ie., past the end.
  229. myStatus.pausePosition = 0;
  230. timeUpdates(false);
  231. timeUpdateEvent();
  232. if(wasPlaying) { // For when playing and then get a play(huge)
  233. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_PAUSE, myStatus));
  234. }
  235. } else if(myStatus.pausePosition > getDuration()) {
  236. myStatus.playOnSeek = true;
  237. seeking(true);
  238. } else {
  239. myStatus.isPlaying = true; // Set immediately before playing. Could affects events.
  240. myChannel = mySound.play(myStatus.pausePosition);
  241. myChannel.soundTransform = myTransform;
  242. myChannel.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
  243. timeUpdates(true);
  244. if(!wasPlaying) {
  245. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_PLAY, myStatus));
  246. }
  247. checkPlaying(true); // Force the playing event unless waiting, which will be dealt with in the playingTimer.
  248. }
  249. return true;
  250. } else {
  251. return false;
  252. }
  253. }
  254. public function pause(time:Number = NaN):Boolean {
  255. myStatus.playOnLoad = false; // Reset flag in case load/play issued immediately before this command, ie., before loadOpen() event.
  256. myStatus.playOnSeek = false; // Reset flag in case play(time) issued before the command and is still seeking to time set.
  257. var wasPlaying:Boolean = myStatus.isPlaying;
  258. // To avoid possible loops with timeupdate and pause(time). A pause() does not have the problem.
  259. var alreadyPausedAtTime:Boolean = false;
  260. if(!isNaN(time) && myStatus.pausePosition == time) {
  261. alreadyPausedAtTime = true;
  262. }
  263. if(myStatus.isPlaying) {
  264. myStatus.isPlaying = false;
  265. myChannel.stop();
  266. if(myChannel.position > 0) { // Required otherwise a fast play then pause causes myChannel.position to equal zero and not the correct value. ie., When it happens leave pausePosition alone.
  267. myStatus.pausePosition = myChannel.position;
  268. }
  269. }
  270. if(!isNaN(time) && myStatus.srcSet) {
  271. myStatus.pausePosition = time;
  272. }
  273. if(wasPlaying) {
  274. this.dispatchEvent(new JplayerEvent(JplayerEvent.JPLAYER_PAUSE, myStatus));
  275. }
  276. if(myStatus.isStartingDownload) {
  277. return true;
  278. } else if(myStatus.loadRequired()) {
  279. if(time > 0) { // We do not want the stop() command, which does pause(0), causing a load operation.
  280. return load();
  281. } else {
  282. return true; // Technically the pause(0) succeeded. ie., It did nothing, since nothing was required.
  283. }
  284. } else if(myStatus.isLoading || myStatus.isLoaded) {
  285. if(myStatus.isLoaded && myStatus.pausePosition > getDuration()) { // The time is invalid, ie., past the end.
  286. myStatus.pausePosition = 0;
  287. } else if(myStatus.pausePosition > getDuration()) {
  288. seeking(true);
  289. }
  290. timeUpdates(false);
  291. // Need to be careful with timeupdate event, otherwise a pause in a timeupdate event can cause a loop.
  292. // Neither pause() nor pause(time) will cause a timeupdate loop.
  293. if(wasPlaying || !isNaN(time) && !alreadyPausedAtTime) {
  294. timeUpdateEvent();
  295. }
  296. return true;
  297. } else {
  298. return false;
  299. }
  300. }
  301. public function playHead(percent:Number):Boolean {
  302. var time:Number = percent * getDuration() / 100;
  303. if(myStatus.isPlaying || myStatus.playOnLoad || myStatus.playOnSeek) {
  304. return play(time);
  305. } else {
  306. return pause(time);
  307. }
  308. }
  309. public function setVolume(v:Number):void {
  310. myStatus.volume = v;
  311. myTransform.volume = v;
  312. myChannel.soundTransform = myTransform;
  313. }
  314. private function updateStatusValues():void {
  315. myStatus.seekPercent = 100 * getLoadRatio();
  316. myStatus.currentTime = getCurrentTime();
  317. myStatus.currentPercentRelative = 100 * getCurrentRatioRel();
  318. myStatus.currentPercentAbsolute = 100 * getCurrentRatioAbs();
  319. myStatus.duration = getDuration();
  320. }
  321. public function getLoadRatio():Number {
  322. if((myStatus.isLoading || myStatus.isLoaded) && mySound.bytesTotal > 0) {
  323. return mySound.bytesLoaded / mySound.bytesTotal;
  324. } else {
  325. return 0;
  326. }
  327. }
  328. public function getDuration():Number {
  329. if(mySound.length > 0) {
  330. return mySound.length;
  331. } else {
  332. return 0;
  333. }
  334. }
  335. public function getCurrentTime():Number {
  336. if(myStatus.isPlaying) {
  337. return myChannel.position;
  338. } else {
  339. return myStatus.pausePosition;
  340. }
  341. }
  342. public function getCurrentRatioRel():Number {
  343. if((getDuration() > 0) && (getCurrentTime() <= getDuration())) {
  344. return getCurrentTime() / getDuration();
  345. } else {
  346. return 0;
  347. }
  348. }
  349. public function getCurrentRatioAbs():Number {
  350. return getCurrentRatioRel() * getLoadRatio();
  351. }
  352. }
  353. }