• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/lighttpd-1.4.39/external_file/js_src/jplayer.2.6.0/actionscript/
1/*
2 * jPlayer Plugin for jQuery JavaScript Library
3 * http://www.jplayer.org
4 *
5 * Copyright (c) 2009 - 2014 Happyworm Ltd
6 * Licensed under the MIT license.
7 * http://opensource.org/licenses/MIT
8 *
9 * Author: Mark J Panaghiston
10 * Version: 2.6.0
11 * Date: 2nd April 2014
12 *
13 * FlashVars expected: (AS3 property of: loaderInfo.parameters)
14 *	id: 	(URL Encoded: String) Id of jPlayer instance
15 *	vol:	(Number) Sets the initial volume
16 *	muted:	(Boolean in a String) Sets the initial muted state
17 *	jQuery:	(URL Encoded: String) Sets the jQuery var name. Used with: someVar = jQuery.noConflict(true); The someVar name must contain jQuery in it.
18 *
19 * Compiled using: Adobe Flex Compiler (mxmlc) Version 4.5.1 build 21328
20 */
21
22package {
23	import flash.system.Security;
24	import flash.external.ExternalInterface;
25
26	import flash.utils.Timer;
27	import flash.events.TimerEvent;
28	
29	import flash.text.TextField;
30	import flash.text.TextFormat;
31
32	import flash.events.KeyboardEvent;
33
34	import flash.display.Sprite;
35	import happyworm.jPlayer.*;
36
37	import flash.display.StageAlign;
38	import flash.display.StageScaleMode;
39	import flash.events.Event;
40	import flash.net.LocalConnection;
41	import flash.events.StatusEvent;
42
43	import flash.events.MouseEvent;
44
45	import flash.ui.ContextMenu;
46	import flash.ui.ContextMenuItem;
47	import flash.events.ContextMenuEvent;
48	import flash.net.URLRequest;
49	import flash.net.navigateToURL;
50	import flash.media.Video;
51
52	public class Jplayer extends Sprite {
53		private var jQuery:String;
54		private var sentNumberFractionDigits:uint = 2;
55
56		public var commonStatus:JplayerStatus = new JplayerStatus(); // Used for inital ready event so volume is correct.
57
58		private var myInitTimer:Timer = new Timer(100, 0);
59
60		private var myMp3Player:JplayerMp3;
61		private var myMp4Player:JplayerMp4;
62
63		private var myRtmpPlayer:JplayerRtmp;
64		
65		private var isRtmp:Boolean = false;
66		private var isMp4:Boolean = false;
67
68		private var isMp3:Boolean = false;
69		private var isVideo:Boolean = false;
70
71		private var securityIssue:Boolean = false; // On direct access and when SWF parameters contain illegal characters
72
73		private var contextMenuFix:Sprite = new Sprite(); // A sprite that will be on top and fix the content menu over video bug. (A Flash plugin bug.)
74
75		private var txLog:TextField;
76		private var debug:Boolean = false; // Set debug to false for release compile!
77		private var localAIRDebug:Boolean = false; // This is autodetermined by AIR app - leave false!
78
79		private var traceOut:TraceOut; // This class was found to cause problems on OSX with Firefox and Safari where more than 8 instances of the SWF are on a page.
80
81		public function Jplayer() {
82
83			flash.system.Security.allowDomain("*");
84			flash.system.Security.allowInsecureDomain("*");
85
86			// Fix to the security exploit reported by Jason Calvert http://appsec.ws/
87			checkFlashVars(loaderInfo.parameters);
88
89			stage.scaleMode = StageScaleMode.NO_SCALE;
90			stage.align = StageAlign.TOP_LEFT;
91
92			if(!securityIssue) {
93				// The jQuery param is the primary cause of security concerns.
94				jQuery = loaderInfo.parameters.jQuery + "('#" + loaderInfo.parameters.id + "').jPlayer";
95				commonStatus.volume = Number(loaderInfo.parameters.vol);
96				commonStatus.muted = loaderInfo.parameters.muted == "true";
97
98				stage.addEventListener(Event.RESIZE, resizeHandler);
99				stage.addEventListener(MouseEvent.CLICK, clickHandler);
100
101				var initialVolume:Number = commonStatus.volume;
102				if(commonStatus.muted) {
103					initialVolume = 0;
104				}
105
106				myMp3Player = new JplayerMp3(initialVolume);
107				addChild(myMp3Player);
108
109				myMp4Player = new JplayerMp4(initialVolume);
110				addChild(myMp4Player);
111
112				myRtmpPlayer = new JplayerRtmp(initialVolume);
113				addChild(myRtmpPlayer);
114
115				switchType("mp3"); // set default state to mp3
116			}
117
118			// The ContextMenu only partially works. The menu select events never occur.
119			// Investigated and it is something to do with the way jPlayer inserts the Flash on the page.
120			// A simple test inserting the Jplayer.swf on a page using: 1) SWFObject 2.2 works. 2) AC_FL_RunContent() works.
121			// jPlayer Flash insertion is based on SWFObject 2.2 and the resaon behind this failure is not clear. The Flash insertion HTML on the page looks similar.
122			var myContextMenu:ContextMenu = new ContextMenu();
123			myContextMenu.hideBuiltInItems();
124			var menuItem_jPlayer:ContextMenuItem = new ContextMenuItem("jPlayer " + JplayerStatus.VERSION);
125			var menuItem_happyworm:ContextMenuItem = new ContextMenuItem("�� 2009-2014 Happyworm Ltd", true);
126			menuItem_jPlayer.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, menuSelectHandler_jPlayer);
127			menuItem_happyworm.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, menuSelectHandler_happyworm);
128			myContextMenu.customItems.push(menuItem_jPlayer, menuItem_happyworm);
129			contextMenu = myContextMenu;
130
131			// Log console for dev compile option: debug
132			if(debug || securityIssue) {
133				txLog = new TextField();
134				txLog.x = 5;
135				txLog.y = 5;
136				txLog.width = stage.stageWidth - 10;
137				txLog.height = stage.stageHeight - 10;
138				txLog.backgroundColor = 0xEEEEFF;
139				txLog.border = true;
140				txLog.background = true;
141				txLog.multiline = true;
142				txLog.text = "jPlayer " + JplayerStatus.VERSION;
143
144				if(securityIssue) {
145					txLog.visible = true;
146				} else if(debug) {
147					txLog.visible = false;
148				}
149
150				this.addChild(txLog);
151
152				if(debug && !securityIssue) {
153					this.stage.addEventListener(KeyboardEvent.KEY_UP, keyboardHandler);
154
155					myMp3Player.addEventListener(JplayerEvent.DEBUG_MSG, debugMsgHandler);
156					myMp4Player.addEventListener(JplayerEvent.DEBUG_MSG, debugMsgHandler);
157					myRtmpPlayer.addEventListener(JplayerEvent.DEBUG_MSG, debugMsgHandler);
158
159					traceOut = new TraceOut(); // Instance it only when in debug mode. See comment above at var declaration.
160				}
161			}
162
163			// Known Flash problem with contextMenu over video player.
164			// Add a transparent rectangle into the sprite.
165			contextMenuFix.graphics.beginFill(0x000000, 0); // Transparent black
166			contextMenuFix.graphics.drawRect(0, 0, 10, 10); // Arbitary rectangle
167			contextMenuFix.graphics.endFill();
168			addChild(contextMenuFix); // Put the sprite on the top layer.
169
170			if(!securityIssue) {
171				// Delay init() because Firefox 3.5.7+ developed a bug with local testing in Firebug.
172				myInitTimer.addEventListener(TimerEvent.TIMER, init);
173				myInitTimer.start();
174			}
175		}
176
177		private function switchType(playType:String):void {
178			switch(playType) {
179				case "rtmpa":
180				isRtmp=true;
181				isMp3=false;
182				isMp4=false;
183				isVideo=false;
184				break;
185			case "rtmpv":
186				isRtmp=true;
187				isMp3=false;
188				isMp4=false;
189				isVideo=true;
190				break;
191			case "mp3":
192				isRtmp=false;
193				isMp3=true;
194				isMp4=false;
195				isVideo=false;
196				break;
197			case "mp4":
198				isRtmp=false;
199				isMp3=false;
200				isMp4=true;
201				isVideo=false;
202				break;
203			case "m4v":
204				isRtmp=false;
205				isMp3=false;
206				isMp4=true;
207				isVideo=true;
208				break;
209			}
210			
211			listenToMp3(isMp3);
212			listenToMp4(isMp4);
213			listenToRtmp(isRtmp);
214		}
215		
216		private function init(e:TimerEvent):void {
217			myInitTimer.stop();
218			if(ExternalInterface.available && !securityIssue) {
219				ExternalInterface.addCallback("fl_setAudio_mp3", fl_setAudio_mp3);
220				ExternalInterface.addCallback("fl_setAudio_m4a", fl_setAudio_m4a);
221				ExternalInterface.addCallback("fl_setVideo_m4v", fl_setVideo_m4v);
222				ExternalInterface.addCallback("fl_setAudio_rtmp", fl_setAudio_rtmp);
223				ExternalInterface.addCallback("fl_setVideo_rtmp", fl_setVideo_rtmp);
224				ExternalInterface.addCallback("fl_clearMedia", fl_clearMedia);
225				ExternalInterface.addCallback("fl_load", fl_load);
226				ExternalInterface.addCallback("fl_play", fl_play);
227				ExternalInterface.addCallback("fl_pause", fl_pause);
228				ExternalInterface.addCallback("fl_play_head", fl_play_head);
229				ExternalInterface.addCallback("fl_volume", fl_volume);
230				ExternalInterface.addCallback("fl_mute", fl_mute);
231
232				ExternalInterface.call(jQuery, "jPlayerFlashEvent", JplayerEvent.JPLAYER_READY, extractStatusData(commonStatus)); // See JplayerStatus() class for version number.
233			}
234		}
235		private function checkFlashVars(p:Object):void {
236			// Check for direct access. Inspired by mediaelement.js - Also added name to HTML object for non-IE browsers.
237			if(ExternalInterface.objectID != null && ExternalInterface.objectID.toString() != "") {
238				for each (var s:String in p) {
239					if(illegalChar(s)) {
240						securityIssue = true; // Found a security concern.
241					}
242				}
243				if(!securityIssue) {
244					if(jQueryIllegal(p.jQuery)) {
245						securityIssue = true; // Found a security concern.
246					}
247				}
248			} else {
249				securityIssue = true; // Direct access disables the callbacks, which were a security concern.
250			}
251		}
252		private function illegalChar(s:String):Boolean {
253			// A whitelist of accepted chars.
254			var validParam:RegExp = /^[-A-Za-z0-9_.]+$/;
255			return !validParam.test(s);
256		}
257		private function jQueryIllegal(s:String):Boolean {
258			// Check param contains the term jQuery.
259			var validParam:RegExp = /(jQuery)/;
260			return !validParam.test(s);
261		}
262		// switchType() here
263		private function listenToMp3(active:Boolean):void {
264			if(active) {
265				myMp3Player.addEventListener(JplayerEvent.JPLAYER_ERROR, jPlayerFlashEvent);
266				myMp3Player.addEventListener(JplayerEvent.JPLAYER_PROGRESS, jPlayerFlashEvent);
267				myMp3Player.addEventListener(JplayerEvent.JPLAYER_TIMEUPDATE, jPlayerFlashEvent);
268				myMp3Player.addEventListener(JplayerEvent.JPLAYER_ENDED, jPlayerFlashEvent);
269				
270				myMp3Player.addEventListener(JplayerEvent.JPLAYER_PLAY, jPlayerFlashEvent);
271				myMp3Player.addEventListener(JplayerEvent.JPLAYER_PAUSE, jPlayerFlashEvent);
272				myMp3Player.addEventListener(JplayerEvent.JPLAYER_LOADSTART, jPlayerFlashEvent);
273
274				myMp3Player.addEventListener(JplayerEvent.JPLAYER_SEEKING, jPlayerFlashEvent);
275				myMp3Player.addEventListener(JplayerEvent.JPLAYER_SEEKED, jPlayerFlashEvent);
276
277				myMp3Player.addEventListener(JplayerEvent.JPLAYER_WAITING, jPlayerFlashEvent); // only MP3 atm
278				myMp3Player.addEventListener(JplayerEvent.JPLAYER_PLAYING, jPlayerFlashEvent); // only MP3 atm
279
280				myMp3Player.addEventListener(JplayerEvent.JPLAYER_CANPLAY, jPlayerFlashEvent); // only MP3 atm
281				myMp3Player.addEventListener(JplayerEvent.JPLAYER_CANPLAYTHROUGH, jPlayerFlashEvent); // only MP3 atm
282
283				myMp3Player.addEventListener(JplayerEvent.JPLAYER_LOADEDMETADATA, jPlayerFlashEvent);
284				myMp3Player.addEventListener(JplayerEvent.JPLAYER_DURATIONCHANGE, jPlayerFlashEvent); // only MP3 atm
285			} else {
286				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_ERROR, jPlayerFlashEvent);
287				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_PROGRESS, jPlayerFlashEvent);
288				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_TIMEUPDATE, jPlayerFlashEvent);
289				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_ENDED, jPlayerFlashEvent);
290				
291				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_PLAY, jPlayerFlashEvent);
292				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_PAUSE, jPlayerFlashEvent);
293				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_LOADSTART, jPlayerFlashEvent);
294
295				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_SEEKING, jPlayerFlashEvent);
296				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_SEEKED, jPlayerFlashEvent);
297
298				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_WAITING, jPlayerFlashEvent); // only MP3 atm
299				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_PLAYING, jPlayerFlashEvent); // only MP3 atm
300
301				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_CANPLAY, jPlayerFlashEvent); // only MP3 atm
302				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_CANPLAYTHROUGH, jPlayerFlashEvent); // only MP3 atm
303
304				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_LOADEDMETADATA, jPlayerFlashEvent);
305				myMp3Player.removeEventListener(JplayerEvent.JPLAYER_DURATIONCHANGE, jPlayerFlashEvent); // only MP3 atm
306			}
307		}
308		private function listenToMp4(active:Boolean):void {
309			if(active) {
310				myMp4Player.addEventListener(JplayerEvent.JPLAYER_ERROR, jPlayerFlashEvent);
311				myMp4Player.addEventListener(JplayerEvent.JPLAYER_PROGRESS, jPlayerFlashEvent);
312				myMp4Player.addEventListener(JplayerEvent.JPLAYER_TIMEUPDATE, jPlayerFlashEvent);
313				myMp4Player.addEventListener(JplayerEvent.JPLAYER_ENDED, jPlayerFlashEvent);
314
315				myMp4Player.addEventListener(JplayerEvent.JPLAYER_PLAY, jPlayerFlashEvent);
316				myMp4Player.addEventListener(JplayerEvent.JPLAYER_PAUSE, jPlayerFlashEvent);
317				myMp4Player.addEventListener(JplayerEvent.JPLAYER_LOADSTART, jPlayerFlashEvent);
318
319				myMp4Player.addEventListener(JplayerEvent.JPLAYER_SEEKING, jPlayerFlashEvent);
320				myMp4Player.addEventListener(JplayerEvent.JPLAYER_SEEKED, jPlayerFlashEvent);
321
322				myMp4Player.addEventListener(JplayerEvent.JPLAYER_LOADEDMETADATA, jPlayerMetaDataHandler); // Note the unique handler
323			} else {
324				myMp4Player.removeEventListener(JplayerEvent.JPLAYER_ERROR, jPlayerFlashEvent);
325				myMp4Player.removeEventListener(JplayerEvent.JPLAYER_PROGRESS, jPlayerFlashEvent);
326				myMp4Player.removeEventListener(JplayerEvent.JPLAYER_TIMEUPDATE, jPlayerFlashEvent);
327				myMp4Player.removeEventListener(JplayerEvent.JPLAYER_ENDED, jPlayerFlashEvent);
328
329				myMp4Player.removeEventListener(JplayerEvent.JPLAYER_PLAY, jPlayerFlashEvent);
330				myMp4Player.removeEventListener(JplayerEvent.JPLAYER_PAUSE, jPlayerFlashEvent);
331				myMp4Player.removeEventListener(JplayerEvent.JPLAYER_LOADSTART, jPlayerFlashEvent);
332
333				myMp4Player.removeEventListener(JplayerEvent.JPLAYER_SEEKING, jPlayerFlashEvent);
334				myMp4Player.removeEventListener(JplayerEvent.JPLAYER_SEEKED, jPlayerFlashEvent);
335
336				myMp4Player.removeEventListener(JplayerEvent.JPLAYER_LOADEDMETADATA, jPlayerMetaDataHandler); // Note the unique handler
337			}
338		}
339
340		private function listenToRtmp(active:Boolean):void {
341			if(active) {
342				myRtmpPlayer.addEventListener(JplayerEvent.JPLAYER_ERROR, jPlayerFlashEvent);
343				myRtmpPlayer.addEventListener(JplayerEvent.JPLAYER_PROGRESS, jPlayerFlashEvent);
344				myRtmpPlayer.addEventListener(JplayerEvent.JPLAYER_TIMEUPDATE, jPlayerFlashEvent);
345				myRtmpPlayer.addEventListener(JplayerEvent.JPLAYER_ENDED, jPlayerFlashEvent);
346
347				myRtmpPlayer.addEventListener(JplayerEvent.JPLAYER_PLAY, jPlayerFlashEvent);
348				myRtmpPlayer.addEventListener(JplayerEvent.JPLAYER_PAUSE, jPlayerFlashEvent);
349				myRtmpPlayer.addEventListener(JplayerEvent.JPLAYER_LOADSTART, jPlayerFlashEvent);
350				
351				myRtmpPlayer.addEventListener(JplayerEvent.JPLAYER_CANPLAY, jPlayerFlashEvent);
352
353				myRtmpPlayer.addEventListener(JplayerEvent.JPLAYER_SEEKING, jPlayerFlashEvent);
354				myRtmpPlayer.addEventListener(JplayerEvent.JPLAYER_SEEKED, jPlayerFlashEvent);
355
356				myRtmpPlayer.addEventListener(JplayerEvent.JPLAYER_LOADEDMETADATA, jPlayerMetaDataHandler); // Note the unique handler
357			} else {
358				myRtmpPlayer.removeEventListener(JplayerEvent.JPLAYER_ERROR, jPlayerFlashEvent);
359				myRtmpPlayer.removeEventListener(JplayerEvent.JPLAYER_PROGRESS, jPlayerFlashEvent);
360				myRtmpPlayer.removeEventListener(JplayerEvent.JPLAYER_TIMEUPDATE, jPlayerFlashEvent);
361				myRtmpPlayer.removeEventListener(JplayerEvent.JPLAYER_ENDED, jPlayerFlashEvent);
362
363				myRtmpPlayer.removeEventListener(JplayerEvent.JPLAYER_PLAY, jPlayerFlashEvent);
364				myRtmpPlayer.removeEventListener(JplayerEvent.JPLAYER_PAUSE, jPlayerFlashEvent);
365				myRtmpPlayer.removeEventListener(JplayerEvent.JPLAYER_LOADSTART, jPlayerFlashEvent);
366				
367				myRtmpPlayer.addEventListener(JplayerEvent.JPLAYER_CANPLAY, jPlayerFlashEvent);
368
369				myRtmpPlayer.removeEventListener(JplayerEvent.JPLAYER_SEEKING, jPlayerFlashEvent);
370				myRtmpPlayer.removeEventListener(JplayerEvent.JPLAYER_SEEKED, jPlayerFlashEvent);
371
372				myRtmpPlayer.removeEventListener(JplayerEvent.JPLAYER_LOADEDMETADATA, jPlayerMetaDataHandler); // Note the unique handler
373			}
374		}
375
376		private function fl_setAudio_mp3(src:String):Boolean {
377			if (src != null) {
378				log("fl_setAudio_mp3: "+src);
379				switchType("mp3");
380				myMp4Player.clearFile();
381				myRtmpPlayer.clearFile();
382				myMp3Player.setFile(src);
383				return true;
384			} else {
385				log("fl_setAudio_mp3: null");
386				return false;
387			}
388		}
389		private function fl_setAudio_rtmp(src:String):Boolean {
390			if (src != null) {
391				log("fl_setAudio_rtmp: "+src);
392				switchType("rtmpa");
393				myMp4Player.clearFile();
394				myMp3Player.clearFile();
395				myRtmpPlayer.setFile(src,false);
396				return true;
397			} else {
398				log("fl_setAudio_rtmp: null");
399				return false;
400			}
401		}
402		
403		private function fl_setVideo_rtmp(src:String):Boolean {
404			if (src != null) {
405				log("fl_setVideo_rtmp: "+src);
406				switchType("rtmpv");
407				myMp4Player.clearFile();
408				myMp3Player.clearFile();
409				myRtmpPlayer.setFile(src,true);
410				return true;
411			} else {
412				log("fl_setVideo_rtmp: null");
413				return false;
414			}
415		}
416		private function fl_setAudio_m4a(src:String):Boolean {
417			if (src != null) {
418				log("fl_setAudio_m4a: "+src);
419				switchType("mp4")
420				myMp3Player.clearFile();
421				myRtmpPlayer.clearFile();
422				myMp4Player.setFile(src);
423				return true;
424			} else {
425				log("fl_setAudio_m4a: null");
426				return false;
427			}
428		}
429		private function fl_setVideo_m4v(src:String):Boolean {
430			if (src != null) {
431				log("fl_setVideo_m4v: "+src);
432				switchType("m4v");
433				myMp3Player.clearFile();
434				myRtmpPlayer.clearFile();
435				myMp4Player.setFile(src);
436				return true;
437			} else {
438				log("fl_setVideo_m4v: null");
439				return false;
440			}
441		}
442		private function fl_clearMedia():void {
443			log("clearMedia.");
444			myMp3Player.clearFile();
445			myMp4Player.clearFile();
446			myRtmpPlayer.clearFile();
447		}
448
449		private function getType():Object {
450			var returnType:Object;
451			if(isMp3) {
452				returnType=myMp3Player;
453			} 
454			if(isRtmp) {
455				returnType=myRtmpPlayer;
456			}
457			if(isMp4) {
458				returnType=myMp4Player;
459			}
460			return returnType;
461		}
462
463		private function fl_load():Boolean {
464			log("load.");
465			var returnType:Object = getType();
466			return returnType.load();
467		}
468		private function fl_play(time:Number = NaN):Boolean {
469			log("play: time = " + time);
470			var returnType:Object = getType();
471			return returnType.play(time * 1000); // Flash uses milliseconds
472		}
473		private function fl_pause(time:Number = NaN):Boolean {
474			log("pause: time = " + time);
475			var returnType:Object = getType();
476			return returnType.pause(time * 1000); // Flash uses milliseconds
477		}
478		private function fl_play_head(percent:Number):Boolean {
479			log("play_head: "+percent+"%");
480			var returnType:Object = getType();
481			return returnType.playHead(percent);
482		}
483		private function fl_volume(v:Number):void {
484			log("volume: "+v);
485			commonStatus.volume = v;
486			if(!commonStatus.muted) {
487				myMp3Player.setVolume(v);
488				myMp4Player.setVolume(v);
489				myRtmpPlayer.setVolume(v);
490			}
491		}
492		private function fl_mute(mute:Boolean):void {
493			log("mute: "+mute);
494			commonStatus.muted = mute;
495			if(mute) {
496				myMp3Player.setVolume(0);
497				myMp4Player.setVolume(0);
498				myRtmpPlayer.setVolume(0);
499			} else {
500				myMp3Player.setVolume(commonStatus.volume);
501				myMp4Player.setVolume(commonStatus.volume);
502				myRtmpPlayer.setVolume(commonStatus.volume);
503			}
504		}
505		private function jPlayerFlashEvent(e:JplayerEvent):void {
506			log("jPlayer Flash Event: " + e.type + ": " + e.target);
507			if(ExternalInterface.available && !securityIssue) {
508				ExternalInterface.call(jQuery, "jPlayerFlashEvent", e.type, extractStatusData(e.data));
509			}
510		}
511		
512		private function tracer(msg:String):void {
513			if(debug) {
514				traceOut.tracer(msg);
515			}
516		}
517		
518		private function extractStatusData(data:JplayerStatus):Object {
519			var myStatus:Object = {
520				version: JplayerStatus.VERSION,
521				src: data.src,
522				paused: !data.isPlaying, // Changing this name requires inverting all assignments and conditional statements.
523				srcSet: data.srcSet,
524				seekPercent: data.seekPercent,
525				currentPercentRelative: data.currentPercentRelative,
526				currentPercentAbsolute: data.currentPercentAbsolute,
527				currentTime: data.currentTime / 1000, // JavaScript uses seconds
528				duration: data.duration / 1000, // JavaScript uses seconds
529				videoWidth: data.videoWidth,
530				videoHeight: data.videoHeight,
531				volume: commonStatus.volume,
532				muted: commonStatus.muted
533			};
534			log("extractStatusData: sp="+myStatus.seekPercent+" cpr="+myStatus.currentPercentRelative+" cpa="+myStatus.currentPercentAbsolute+" ct="+myStatus.currentTime+" d="+myStatus.duration);
535			return myStatus;
536		}
537		private function jPlayerMetaDataHandler(e:JplayerEvent):void {
538			log("jPlayerMetaDataHandler:" + e.target);
539			if(ExternalInterface.available && !securityIssue) {
540				resizeHandler(new Event(Event.RESIZE));
541				ExternalInterface.call(jQuery, "jPlayerFlashEvent", e.type, extractStatusData(e.data));
542			}
543		}
544		private function resizeHandler(e:Event):void {
545			log("resizeHandler: stageWidth = " + stage.stageWidth + " | stageHeight = " + stage.stageHeight);
546
547			var mediaX:Number = 0;
548			var mediaY:Number = 0;
549			var mediaWidth:Number = 0;
550			var mediaHeight:Number = 0;
551			
552			var aspectRatioStage:Number = 0;
553			var aspectRatioVideo:Number = 0;
554			
555			var videoItem:*;
556			
557			if(isRtmp) {
558				videoItem = myRtmpPlayer;
559			}
560			if(isMp4) {
561				videoItem = myMp4Player;
562			}
563			
564			if(videoItem) {
565				if(stage.stageWidth > 0 && stage.stageHeight > 0 && videoItem.myVideo.width > 0 && videoItem.myVideo.height > 0) {
566					aspectRatioStage = stage.stageWidth / stage.stageHeight;
567					aspectRatioVideo = videoItem.myVideo.width / videoItem.myVideo.height;
568					if(aspectRatioStage < aspectRatioVideo) {
569						mediaWidth = stage.stageWidth;
570						mediaHeight = stage.stageWidth / aspectRatioVideo;
571						mediaX = 0;
572						mediaY = (stage.stageHeight - mediaHeight) / 2;
573					} else {
574						mediaWidth = stage.stageHeight * aspectRatioVideo;
575						mediaHeight = stage.stageHeight;
576						mediaX = (stage.stageWidth - mediaWidth) / 2;
577						mediaY = 0;
578					}
579					resizeEntity(videoItem, mediaX, mediaY, mediaWidth, mediaHeight);
580				}
581			}
582			if((debug || securityIssue) && stage.stageWidth > 20 && stage.stageHeight > 20) {
583				txLog.width = stage.stageWidth - 10;
584				txLog.height = stage.stageHeight - 10;
585			}
586			// Resize the sprite so it covers the entire stage area
587			contextMenuFix.x = 0;
588			contextMenuFix.y = 0;
589			contextMenuFix.width = stage.stageWidth;
590			contextMenuFix.height = stage.stageHeight;
591		}
592		private function resizeEntity(entity:Sprite, mediaX:Number, mediaY:Number, mediaWidth:Number, mediaHeight:Number):void {
593			entity.x = mediaX;
594			entity.y = mediaY;
595			entity.width = mediaWidth;
596			entity.height = mediaHeight;
597		}
598		private function clickHandler(e:MouseEvent):void {
599			// This needs to work with RTMP format too!
600			if(isMp3) {
601				jPlayerFlashEvent(new JplayerEvent(JplayerEvent.JPLAYER_CLICK, myMp3Player.myStatus, "click"))
602			} else {
603				jPlayerFlashEvent(new JplayerEvent(JplayerEvent.JPLAYER_CLICK, myMp4Player.myStatus, "click"))
604			}
605		}
606		// This event is never called. See comments in class constructor.
607		private function menuSelectHandler_jPlayer(e:ContextMenuEvent):void {
608			navigateToURL(new URLRequest("http://jplayer.org/"), "_blank");
609		}
610		// This event is never called. See comments in class constructor.
611		private function menuSelectHandler_happyworm(e:ContextMenuEvent):void {
612			navigateToURL(new URLRequest("http://happyworm.com/"), "_blank");
613		}
614		private function log(t:String):void {
615			if(debug) {
616				txLog.text = t + "\n" + txLog.text;
617				localAIRDebug = traceOut.localAIRDebug();
618				if(localAIRDebug) {
619					tracer(t);
620				}
621
622				if(ExternalInterface.available && !securityIssue) {
623					ExternalInterface.call("console.log", t);
624				}
625			}
626		}
627		private function debugMsgHandler(e:JplayerEvent):void {
628			log(e.msg);
629		}
630		private function keyboardHandler(e:KeyboardEvent):void {
631			log("keyboardHandler: e.keyCode = " + e.keyCode);
632			switch(e.keyCode) {
633				case 68 : // d
634					txLog.visible = !txLog.visible;
635					log("Toggled log display: " + txLog.visible);
636					break;
637				case 76 : // l
638					if(e.ctrlKey && e.shiftKey) {
639						txLog.text = "Cleared log.";
640					}
641					break;
642			}
643		}
644	}
645}
646