flash on 2013-10-22

by adamh
♥0 | Line 1590 | Modified 2013-10-22 12:53:13 | MIT License
play

ActionScript3 source code

/**
 * Copyright adamh ( http://wonderfl.net/user/adamh )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/9fMg
 */

package  {

  //START FlashMediaElement.as

  import flash.display.*;

    import flash.events.*;

    import flash.media.*;

    import flash.net.*;

    import flash.text.*;

    import flash.system.*;

    

    import flash.media.Video;

    import flash.net.NetConnection;

    import flash.net.NetStream;

    

    import flash.geom.ColorTransform;

    

    import flash.filters.DropShadowFilter;

    import flash.utils.Timer;

    import flash.external.ExternalInterface;

    import flash.geom.Rectangle;

    

    

    public class FlashMediaElement extends MovieClip {



        private var _mediaUrl:String;

        private var _autoplay:Boolean;

        private var _preload:String;

        private var _debug:Boolean;

        private var _isVideo:Boolean;

        private var _video:DisplayObject;

        private var _timerRate:Number;

        private var _stageWidth:Number;

        private var _stageHeight:Number;

        private var _enableSmoothing:Boolean;

        private var _allowedPluginDomain:String;

        private var _isFullScreen:Boolean = false;

        private var _startVolume:Number;

        private var _controlStyle:String;

        private var _autoHide:Boolean = true;

        private var _streamer:String = "";

        private var _enablePseudoStreaming:Boolean;

        private var _pseudoStreamingStartQueryParam:String;



        // native video size (from meta data)

        private var _nativeVideoWidth:Number = 0;

        private var _nativeVideoHeight:Number = 0;



        // visual elements

        private var _output:TextField;

        private var _fullscreenButton:SimpleButton;



        // media

        private var _mediaElement:IMediaElement;



        // connection to fullscreen 

        private var _connection:LocalConnection;

        private var _connectionName:String;



        //private var fullscreen_btn:SimpleButton;



        // CONTROLS

        private var _alwaysShowControls:Boolean;

        private var _controlBar:MovieClip;

        private var _controlBarBg:MovieClip;

        private var _scrubBar:MovieClip;

        private var _scrubTrack:MovieClip;

        private var _scrubOverlay:MovieClip;

        private var _scrubLoaded:MovieClip;

        private var _hoverTime:MovieClip;

        private var _hoverTimeText:TextField;

        private var _playButton:SimpleButton;

        private var _pauseButton:SimpleButton;

        private var _duration:TextField;

        private var _currentTime:TextField;

        private var _fullscreenIcon:SimpleButton;

        private var _volumeMuted:SimpleButton;

        private var _volumeUnMuted:SimpleButton;

        private var _scrubTrackColor:String;

        private var _scrubBarColor:String;

        private var _scrubLoadedColor:String;

        

        // IDLE Timer for mouse for showing/hiding controls

        private var _inactiveTime:int;

        private var _timer:Timer;

        private var _idleTime:int;

        private var _isMouseActive:Boolean

        private var _isOverStage:Boolean = false;

        

        // security checkes

        private var securityIssue:Boolean = false; // When SWF parameters contain illegal characters

        private var directAccess:Boolean = false; // When SWF visited directly with no parameters (or when security issue detected)     





        public function FlashMediaElement() {

            // check for security issues (borrowed from jPLayer)

            checkFlashVars(loaderInfo.parameters);

            

            // allows this player to be called from a different domain than the HTML page hosting the player

            Security.allowDomain("*");

            Security.allowInsecureDomain('*');            

            

            

            // add debug output

            _output = new TextField();

            _output.textColor = 0xeeeeee;

            _output.width = stage.stageWidth - 100;

            _output.height = stage.stageHeight;

            _output.multiline = true;

            _output.wordWrap = true;

            _output.border = false;

            _output.filters = [new DropShadowFilter(1, 0x000000, 45, 1, 2, 2, 1)];



            _output.text = "Initializing...\n";

            addChild(_output);

            _output.visible = securityIssue;            



            if (securityIssue) {

                _output.text = "WARNING: Security issue detected. Player stopped.";

                return;

            }

                

            // get parameters

            // Use only FlashVars, ignore QueryString

            var params:Object, pos:int, query:Object;



            params = LoaderInfo(this.root.loaderInfo).parameters;

            pos = root.loaderInfo.url.indexOf('?');

            if (pos !== -1) {

                query = parseStr(root.loaderInfo.url.substr(pos + 1));



                for (var key:String in params) {

                    if (query.hasOwnProperty(trim(key))) {

                        delete params[key];

                    }

                }

            }



            _mediaUrl = (params['file'] != undefined) ? String(params['file']) : "";

            _autoplay = (params['autoplay'] != undefined) ? (String(params['autoplay']) == "true") : false;

            _debug = (params['debug'] != undefined) ? (String(params['debug']) == "true") : false;

            _isVideo = (params['isvideo'] != undefined) ? ((String(params['isvideo']) == "false") ? false : true  ) : true;

            _timerRate = (params['timerrate'] != undefined) ? (parseInt(params['timerrate'], 10)) : 250;

            _alwaysShowControls = (params['controls'] != undefined) ? (String(params['controls']) == "true") : false;

            _enableSmoothing = (params['smoothing'] != undefined) ? (String(params['smoothing']) == "true") : false;

            _startVolume = (params['startvolume'] != undefined) ? (parseFloat(params['startvolume'])) : 0.8;

            _preload = (params['preload'] != undefined) ? params['preload'] : "none";

            _controlStyle = (params['controlstyle'] != undefined) ? (String(params['controlstyle'])) : ""; // blank or "floating"

            _autoHide = (params['autohide'] != undefined) ? (String(params['autohide'])) : true;

            _scrubTrackColor = (params['scrubtrackcolor'] != undefined) ? (String(params['scrubtrackcolor'])) : "0x333333";

            _scrubBarColor = (params['scrubbarcolor'] != undefined) ? (String(params['scrubbarcolor'])) : "0xefefef";

            _scrubLoadedColor = (params['scrubloadedcolor'] != undefined) ? (String(params['scrubloadedcolor'])) : "0x3CACC8";

            _enablePseudoStreaming = (params['pseudostreaming'] != undefined) ? (String(params['pseudostreaming']) == "true") : false;          

            _pseudoStreamingStartQueryParam = (params['pseudostreamstart'] != undefined) ? (String(params['pseudostreamstart'])) : "start";

            _streamer = (params['flashstreamer'] != undefined) ? (String(params['flashstreamer'])) : "";



            _output.visible = _debug;   

            

            if (isNaN(_timerRate))

                _timerRate = 250;



            // setup stage and player sizes/scales

            stage.align = StageAlign.TOP_LEFT;

            stage.scaleMode = StageScaleMode.NO_SCALE;

            _stageWidth = stage.stageWidth;

            _stageHeight = stage.stageHeight;



            //_autoplay = true;

            //_mediaUrl  = "http://mediafiles.dts.edu/chapel/mp4/20100609.mp4";

            //_alwaysShowControls = true;

            //_mediaUrl  = "../media/Parades-PastLives.mp3";

            //_mediaUrl  = "../media/echo-hereweare.mp4";



            //_mediaUrl = "http://video.ted.com/talks/podcast/AlGore_2006_480.mp4";

            //_mediaUrl = "rtmp://stream2.france24.yacast.net/france24_live/en/f24_liveen";

            

            //_mediaUrl = "http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0"; // hosea

            //_mediaUrl = "http://www.youtube.com/watch?feature=player_embedded&v=m5VDDJlsD6I"; // railer with notes

            

            //_alwaysShowControls = true;



            //_debug=true;

        



            



            // position and hide

            _fullscreenButton = getChildByName("fullscreen_btn") as SimpleButton;

            //_fullscreenButton.visible = false;

            _fullscreenButton.alpha = 0;

            _fullscreenButton.addEventListener(MouseEvent.CLICK, fullscreenClick, false);

            _fullscreenButton.x = stage.stageWidth - _fullscreenButton.width;

            _fullscreenButton.y = stage.stageHeight - _fullscreenButton.height;

            



            // create media element

            if (_isVideo) {

                

                if (_mediaUrl.indexOf("youtube.com") > -1 || _mediaUrl.indexOf("youtu.be") > -1) {

                    

                    //Security.allowDomain("http://www.youtube.com");

                    

                    _mediaElement = new YouTubeElement(this, _autoplay, _preload, _timerRate, _startVolume);

                    _video = (_mediaElement as YouTubeElement).player;

                    

                    // these are set and then used once the player is loaded

                    (_mediaElement as YouTubeElement).initWidth = _stageWidth;

                    (_mediaElement as YouTubeElement).initHeight = _stageHeight;

                

                } else {

                    

                    _mediaElement = new VideoElement(this, _autoplay, _preload, _timerRate, _startVolume, _streamer);

                    _video = (_mediaElement as VideoElement).video;

                    _video.width = _stageWidth;

                    _video.height = _stageHeight;

                    (_video as Video).smoothing = _enableSmoothing;                 

                    (_mediaElement as VideoElement).setReference(this);

                    (_mediaElement as VideoElement).setPseudoStreaming(_enablePseudoStreaming);

                    (_mediaElement as VideoElement).setPseudoStreamingStartParam(_pseudoStreamingStartQueryParam);

                    //_video.scaleMode = VideoScaleMode.MAINTAIN_ASPECT_RATIO;

                    addChild(_video);

                }

            } else {

                

                //var player2:AudioDecoder = new com.automatastudios.audio.audiodecoder.AudioDecoder();

                _mediaElement = new AudioElement(this, _autoplay, _preload, _timerRate, _startVolume);

            }





            // controls!

            _controlBar = getChildByName("controls_mc") as MovieClip;

            _controlBarBg = _controlBar.getChildByName("controls_bg_mc") as MovieClip;

            _scrubTrack = _controlBar.getChildByName("scrubTrack") as MovieClip;

            _scrubBar = _controlBar.getChildByName("scrubBar") as MovieClip;

            _scrubOverlay = _controlBar.getChildByName("scrubOverlay") as MovieClip;

            _scrubLoaded = _controlBar.getChildByName("scrubLoaded") as MovieClip;

            

            _scrubOverlay.buttonMode = true;

            _scrubOverlay.useHandCursor = true

            

            applyColor(_scrubTrack, _scrubTrackColor);

            applyColor(_scrubBar, _scrubBarColor);

            applyColor(_scrubLoaded, _scrubLoadedColor);

            

            _fullscreenIcon = _controlBar.getChildByName("fullscreenIcon") as SimpleButton;

            

            // New fullscreenIcon for new fullscreen floating controls

            //if(_alwaysShowControls && _controlStyle.toUpperCase()=="FLOATING") {

                _fullscreenIcon.addEventListener(MouseEvent.CLICK, fullScreenIconClick, false);

            //}

            

            _volumeMuted = _controlBar.getChildByName("muted_mc") as SimpleButton;

            _volumeUnMuted = _controlBar.getChildByName("unmuted_mc") as SimpleButton;

            

            _volumeMuted.addEventListener(MouseEvent.CLICK, toggleVolume, false);

            _volumeUnMuted.addEventListener(MouseEvent.CLICK, toggleVolume, false);

            

            _playButton = _controlBar.getChildByName("play_btn") as SimpleButton;

            _playButton.addEventListener(MouseEvent.CLICK, function(e:MouseEvent) {

                _mediaElement.play();                    

            });

            _pauseButton = _controlBar.getChildByName("pause_btn") as SimpleButton;

            _pauseButton.addEventListener(MouseEvent.CLICK, function(e:MouseEvent) {

                _mediaElement.pause();                   

            });

            _pauseButton.visible = false;

            _duration = _controlBar.getChildByName("duration_txt") as TextField;

            _currentTime = _controlBar.getChildByName("currentTime_txt") as TextField;

            _hoverTime = _controlBar.getChildByName("hoverTime") as MovieClip;

            _hoverTimeText = _hoverTime.getChildByName("hoverTime_txt") as TextField;

            _hoverTime.visible=false;

            _hoverTime.y=(_hoverTime.height/2)+1;

            _hoverTime.x=0;

            



            

            // Add new timeline scrubber events

            _scrubOverlay.addEventListener(MouseEvent.MOUSE_MOVE, scrubMove);

            _scrubOverlay.addEventListener(MouseEvent.CLICK, scrubClick);

            _scrubOverlay.addEventListener(MouseEvent.MOUSE_OVER, scrubOver);

            _scrubOverlay.addEventListener(MouseEvent.MOUSE_OUT, scrubOut);

            

            if (_autoHide) { // && _alwaysShowControls) {

                // Add mouse activity for show/hide of controls

                stage.addEventListener(Event.MOUSE_LEAVE, mouseActivityLeave);

                stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseActivityMove);

                _inactiveTime = 2500;

                _timer = new Timer(_inactiveTime)

                _timer.addEventListener(TimerEvent.TIMER, idleTimer);

                _timer.start();

                // set

            }

            

            if(_startVolume<=0) {

                trace("INITIAL VOLUME: "+_startVolume+" MUTED");

                _volumeMuted.visible=true;

                _volumeUnMuted.visible=false;

            } else {

                trace("INITIAL VOLUME: "+_startVolume+" UNMUTED");

                _volumeMuted.visible=false;

                _volumeUnMuted.visible=true;

            }

    

            _controlBar.visible = _alwaysShowControls;



            setControlDepth();



            _output.appendText("stage: " + stage.stageWidth + "x" + stage.stageHeight + "\n");

            _output.appendText("file: " + _mediaUrl + "\n");

            _output.appendText("autoplay: " + _autoplay.toString() + "\n");

            _output.appendText("preload: " + _preload.toString() + "\n");

            _output.appendText("isvideo: " + _isVideo.toString() + "\n");

            _output.appendText("smoothing: " + _enableSmoothing.toString() + "\n");

            _output.appendText("timerrate: " + _timerRate.toString() + "\n");

            _output.appendText("displayState: " +(stage.hasOwnProperty("displayState")).toString() + "\n");



            // attach javascript

            _output.appendText("ExternalInterface.available: " + ExternalInterface.available.toString() + "\n");

            _output.appendText("ExternalInterface.objectID: " + ((ExternalInterface.objectID != null)? ExternalInterface.objectID.toString() : "null") + "\n");



            if (_mediaUrl != "") {

                _mediaElement.setSrc(_mediaUrl);

            }



            positionControls();

            

            // Fire this once just to set the width on some dynamically sized scrub bar items;

            _scrubBar.scaleX=0;

            _scrubLoaded.scaleX=0;

            



            if (ExternalInterface.available) { //  && !_alwaysShowControls



                _output.appendText("Adding callbacks...\n");

                try {

                    if (ExternalInterface.objectID != null && ExternalInterface.objectID.toString() != "") {

                        

                        // add HTML media methods

                        ExternalInterface.addCallback("playMedia", playMedia);

                        ExternalInterface.addCallback("loadMedia", loadMedia);

                        ExternalInterface.addCallback("pauseMedia", pauseMedia);

                        ExternalInterface.addCallback("stopMedia", stopMedia);

    

                        ExternalInterface.addCallback("setSrc", setSrc);

                        ExternalInterface.addCallback("setCurrentTime", setCurrentTime);

                        ExternalInterface.addCallback("setVolume", setVolume);

                        ExternalInterface.addCallback("setMuted", setMuted);

    

                        ExternalInterface.addCallback("setFullscreen", setFullscreen);

                        ExternalInterface.addCallback("setVideoSize", setVideoSize);

                        

                        ExternalInterface.addCallback("positionFullscreenButton", positionFullscreenButton);

                        ExternalInterface.addCallback("hideFullscreenButton", hideFullscreenButton);

    

                        // fire init method                 

                        ExternalInterface.call("mejs.MediaPluginBridge.initPlugin", ExternalInterface.objectID);

                    }



                    _output.appendText("Success...\n");



                } catch (error:SecurityError) {

                    _output.appendText("A SecurityError occurred: " + error.message + "\n");

                } catch (error:Error) {

                    _output.appendText("An Error occurred: " + error.message + "\n");

                }



            }



            if (_preload != "none") {

                _mediaElement.load();

                

                if (_autoplay) {

                    _mediaElement.play();

                }

            } else if (_autoplay) {

                _mediaElement.load();

                _mediaElement.play();

            }



            // listen for resize

            stage.addEventListener(Event.RESIZE, resizeHandler);



            // send click events up to javascript

            stage.addEventListener(MouseEvent.CLICK, stageClicked);

            

            // resize

            stage.addEventListener(FullScreenEvent.FULL_SCREEN, stageFullScreenChanged);    

        }

        

        public function setControlDepth():void {

            // put these on top

            addChild(_output);

            addChild(_controlBar);

            addChild(_fullscreenButton);

            

        }

                

        // borrowed from jPLayer 

        // https://github.com/happyworm/jPlayer/blob/e8ca190f7f972a6a421cb95f09e138720e40ed6d/actionscript/Jplayer.as#L228

        private function checkFlashVars(p:Object):void {

            var i:Number = 0;

            for (var s:String in p) {

                if (isIllegalChar(p[s], s === 'file')) {

                    securityIssue = true; // Illegal char found

                }

                i++;

            }

            if(i === 0 || securityIssue) {

                directAccess = true;

            }

        }



        private static function parseStr (str:String) : Object {

            var hash:Object = {},

                arr1:Array, arr2:Array;

            

            str = unescape(str).replace(/\+/g, " ");

            

            arr1 = str.split('&');

            if (!arr1.length) {

                return {};

            }

            

            for (var i:uint = 0, length:uint = arr1.length; i < length; i++) {

                arr2 = arr1[i].split('=');

                if (!arr2.length) {

                    continue;

                }

                hash[trim(arr2[0])] = trim(arr2[1]);

            } 

            return hash;

        }

        

        

        private static function trim(str:String) : String {             

            if (!str) {

                return str; 

            }

            

            return str.toString().replace(/^\s*/, '').replace(/\s*$/, '');  

        }



        private function isIllegalChar(s:String, isUrl:Boolean):Boolean {

            var illegals:String = "' \" ( ) { } * + \\ < >";

            if(isUrl) {

                illegals = "\" { } \\ < >";

            }

            if(Boolean(s)) { // Otherwise exception if parameter null.

                for each (var illegal:String in illegals.split(' ')) {

                    if(s.indexOf(illegal) >= 0) {

                        return true; // Illegal char found

                    }

                }

            }

            return false;

        }               

                

                

        // START: Controls and events

        function mouseActivityMove(event:MouseEvent):void {

            

            // if mouse is in the video area

            if (_autoHide && (mouseX>=0 && mouseX<=stage.stageWidth) && (mouseY>=0 && mouseY<=stage.stageHeight)) {



                // This could be move to a nice fade at some point...

                _controlBar.visible = (_alwaysShowControls || _isFullScreen);

                _isMouseActive = true;

                _idleTime = 0;

                _timer.reset();

                _timer.start()

            }

        }

        

        function mouseActivityLeave(event:Event):void {

            if (_autoHide) {

                _isOverStage = false;

                // This could be move to a nice fade at some point...

                _controlBar.visible = false;

                _isMouseActive = false;

                _idleTime = 0;

                _timer.reset();

                _timer.stop();

            }

        }

        

        function idleTimer(event:TimerEvent):void    {

          

            if (_autoHide) {

                // This could be move to a nice fade at some point...

                _controlBar.visible = false;

                _isMouseActive = false;

                _idleTime += _inactiveTime;

                _idleTime = 0;

                _timer.reset();

                _timer.stop();

            } 

        }

        

        

        function scrubMove(event:MouseEvent):void {

            

            //if (_alwaysShowControls) {

                if (_hoverTime.visible) {

                    var seekBarPosition:Number =  ((event.localX / _scrubTrack.width) *_mediaElement.duration())*_scrubTrack.scaleX;

                    var hoverPos:Number = (seekBarPosition / _mediaElement.duration()) *_scrubTrack.scaleX;

                    

                    if (_isFullScreen) {

                        _hoverTime.x=event.target.parent.mouseX;

                    } else {

                        _hoverTime.x=mouseX;

                    }

                    _hoverTime.y = _scrubBar.y - (_hoverTime.height/2);

                    _hoverTimeText.text = secondsToTimeCode(seekBarPosition);

                }

            //}

            //trace(event);

        }

        

        function scrubOver(event:MouseEvent):void {

            _hoverTime.y = _scrubBar.y-(_hoverTime.height/2)+1;

            _hoverTime.visible = true;

            trace(event);

        }

        

        function scrubOut(event:MouseEvent):void {

            _hoverTime.y = _scrubBar.y+(_hoverTime.height/2)+1;

            _hoverTime.visible = false;

            //_hoverTime.x=0;

            //trace(event);

        }

        

        function scrubClick(event:MouseEvent):void {

            //trace(event);

            var seekBarPosition:Number =  ((event.localX / _scrubTrack.width) *_mediaElement.duration())*_scrubTrack.scaleX;



            var tmp:Number = (_mediaElement.currentTime()/_mediaElement.duration())*_scrubTrack.width;

            var canSeekToPosition:Boolean = _scrubLoaded.scaleX > (seekBarPosition / _mediaElement.duration()) *_scrubTrack.scaleX;

            //var canSeekToPosition:Boolean = true;         

            

            /*

            amountLoaded = ns.bytesLoaded / ns.bytesTotal;

            loader.loadbar._width = amountLoaded * 208.9;

            loader.scrub._x = ns.time / duration * 208.9;

            */

            

            trace("seekBarPosition:"+seekBarPosition, "CanSeekToPosition: "+canSeekToPosition);

            

            if (seekBarPosition>0 && seekBarPosition<_mediaElement.duration() && canSeekToPosition) {

                    _mediaElement.setCurrentTime(seekBarPosition);

            }

        }

        

        function toggleVolume(event:MouseEvent):void {

            trace(event.currentTarget.name);

            switch(event.currentTarget.name) {

                case "muted_mc":

                    setMuted(false);

                    break;

                case "unmuted_mc":

                    setMuted(true);

                    break;

            }

        }

        

        function toggleVolumeIcons(volume:Number) {

            if(volume<=0) {

                _volumeMuted.visible = true;

                _volumeUnMuted.visible = false;

            } else {

                _volumeMuted.visible = false;

                _volumeUnMuted.visible = true;

            }

        }

        

        public function positionControls(forced:Boolean=false) {

            

            

            if ( _controlStyle.toUpperCase() == "FLOATING" && _isFullScreen) {



                trace("CONTROLS: floating");

                _hoverTime.y=(_hoverTime.height/2)+1;

                _hoverTime.x=0;

                _controlBarBg.width = 300;

                _controlBarBg.height = 93;

                //_controlBarBg.x = (stage.stageWidth/2) - (_controlBarBg.width/2);

                //_controlBarBg.y  = stage.stageHeight - 300;

                

                _pauseButton.scaleX = _playButton.scaleX=3.5;

                _pauseButton.scaleY= _playButton.scaleY=3.5;

                // center the play button and make it big and at the top

                _pauseButton.x = _playButton.x = (_controlBarBg.width/2)-(_playButton.width/2)+7;

                _pauseButton.y = _playButton.y = _controlBarBg.height-_playButton.height-(14)

                                

                _controlBar.x = (stage.stageWidth/2) -150;

                _controlBar.y = stage.stageHeight - _controlBar.height-100;

                

                

                // reposition the time and duration items

                

                _duration.x = _controlBarBg.width - _duration.width - 10;

                _duration.y = _controlBarBg.height - _duration.height -7;

                //_currentTime.x = _controlBarBg.width - _duration.width - 10 - _currentTime.width - 10;

                _currentTime.x = 5

                _currentTime.y= _controlBarBg.height - _currentTime.height-7;

                

                _fullscreenIcon.x = _controlBarBg.width - _fullscreenIcon.width - 7;

                _fullscreenIcon.y = 7;

                

                _volumeMuted.x = _volumeUnMuted.x = 7;

                _volumeMuted.y = _volumeUnMuted.y = 7;

                

                _scrubLoaded.x = _scrubBar.x = _scrubOverlay.x = _scrubTrack.x =_currentTime.x+_currentTime.width+7;

                _scrubLoaded.y = _scrubBar.y = _scrubOverlay.y = _scrubTrack.y=_controlBarBg.height-_scrubTrack.height-10;

                

                _scrubBar.width =  _scrubOverlay.width = _scrubTrack.width = (_duration.x-_duration.width-14);



                

            } else {

                trace("CONTROLS: normal, original");

                

                /*

                // Original style bottom display

                _hoverTime.y=(_hoverTime.height/2)+1;

                _hoverTime.x=0;

                _controlBarBg.width = stage.stageWidth;

                _controlBar.y = stage.stageHeight - _controlBar.height;

                _duration.x = stage.stageWidth - _duration.width - 10;

                //_currentTime.x = stage.stageWidth - _duration.width - 10 - _currentTime.width - 10;

                _currentTime.x = _playButton.x+_playButton.width;

                _scrubTrack.width = (_duration.x-_duration.width-10)-_duration.width+10;

                _scrubOverlay.width = _scrubTrack.width;

                _scrubBar.width = _scrubTrack.width;

                */

                

                // FLOATING MODE BOTTOM DISPLAY - similar to normal

                trace("THAT WAY!");

                _hoverTime.y=(_hoverTime.height/2)+1;

                _hoverTime.x=0;

                _controlBarBg.width = stage.stageWidth;

                _controlBarBg.height = 30;

                _controlBarBg.y=0;

                _controlBarBg.x=0;

                // _controlBarBg.x = 0;

                // _controlBarBg.y  = stage.stageHeight - _controlBar.height;

                

                _pauseButton.scaleX = _playButton.scaleX=1;

                _pauseButton.scaleY = _playButton.scaleY=1;

                

                _pauseButton.x = _playButton.x = 7;

                _pauseButton.y = _playButton.y = _controlBarBg.height-_playButton.height-2;

                

                

                //_currentTime.x = stage.stageWidth - _duration.width - 10 - _currentTime.width - 10;

                _currentTime.x = _playButton.x+_playButton.width;

                

                _fullscreenIcon.x = _controlBarBg.width - _fullscreenIcon.width - 7;

                _fullscreenIcon.y = 8;

                

                _volumeMuted.x = _volumeUnMuted.x = _fullscreenIcon.x - _volumeMuted.width - 10;

                _volumeMuted.y = _volumeUnMuted.y = 10;

                

                _duration.x = _volumeMuted.x - _volumeMuted.width - _duration.width + 5;

                _duration.y = _currentTime.y = _controlBarBg.height - _currentTime.height - 7;

                

                _scrubLoaded.x = _scrubBar.x = _scrubOverlay.x = _scrubTrack.x = _currentTime.x + _currentTime.width + 10;

                _scrubLoaded.y = _scrubBar.y = _scrubOverlay.y = _scrubTrack.y = _controlBarBg.height - _scrubTrack.height - 9;

                

                _scrubBar.width =  _scrubOverlay.width = _scrubTrack.width =  (_duration.x-_duration.width-10)-_duration.width+5;

                _controlBar.x = 0;

                _controlBar.y = stage.stageHeight - _controlBar.height;

                

            }

            

        }

        

        // END: Controls

        



        function stageClicked(e:MouseEvent):void {

            //_output.appendText("click: " + e.stageX.toString() +","+e.stageY.toString() + "\n");

            if (e.target == stage) {

                sendEvent("click", "");

            }

        }



        function resizeHandler(e:Event):void {

            //_video.scaleX = stage.stageWidth / _stageWidth;

            //_video.scaleY = stage.stageHeight / _stageHeight;

            //positionControls();

            

            repositionVideo();

        }



        // START: Fullscreen        

        function enterFullscreen() {

            

            _output.appendText("enterFullscreen()\n"); 

            

            var screenRectangle:Rectangle = new Rectangle(0, 0, flash.system.Capabilities.screenResolutionX, flash.system.Capabilities.screenResolutionY); 

            stage.fullScreenSourceRect = screenRectangle;

            

            stage.displayState = StageDisplayState.FULL_SCREEN;

            

            repositionVideo();

            positionControls();

            updateControls(HtmlMediaEvent.FULLSCREENCHANGE);

            

            _controlBar.visible = true;

            

            _isFullScreen = true;

        }

        

        function exitFullscreen() {

        

            stage.displayState = StageDisplayState.NORMAL;

                

            

            _controlBar.visible = false;

            

            _isFullScreen = false;  

        }



        function setFullscreen(gofullscreen:Boolean) {



            _output.appendText("setFullscreen: " + gofullscreen.toString() + "\n"); 



            try {

                //_fullscreenButton.visible = false;



                if (gofullscreen) {

                    enterFullscreen();



                } else {

                    exitFullscreen();

                }



            } catch (error:Error) {



                // show the button when the security error doesn't let it work

                //_fullscreenButton.visible = true;

                _fullscreenButton.alpha = 1;



                _isFullScreen = false;

                

                _output.appendText("error setting fullscreen: " + error.message.toString() + "\n");   

            }

        }

        

        // control bar button/icon 

        function fullScreenIconClick(e:MouseEvent) {

            try {

                _controlBar.visible = true;

                setFullscreen(!_isFullScreen);

                repositionVideo();

            } catch (error:Error) {

            }

        }



        // special floating fullscreen icon

        function fullscreenClick(e:MouseEvent) {

            //_fullscreenButton.visible = false;

            _fullscreenButton.alpha = 0



            try {

                _controlBar.visible = true;

                setFullscreen(true);

                repositionVideo();

                positionControls();

            } catch (error:Error) {

            }

        }

        

        

        function stageFullScreenChanged(e:FullScreenEvent) {

            _output.appendText("fullscreen event: " + e.fullScreen.toString() + "\n");   



            //_fullscreenButton.visible = false;

            _fullscreenButton.alpha = 0;

            _isFullScreen = e.fullScreen;

            

            sendEvent(HtmlMediaEvent.FULLSCREENCHANGE, "isFullScreen:" + e.fullScreen );



            if (!e.fullScreen) {

                _controlBar.visible = _alwaysShowControls;

            }

        }

        // END: Fullscreen



        // START: external interface 

        function playMedia() {

            _output.appendText("play\n");

            _mediaElement.play();

        }



        function loadMedia() {

            _output.appendText("load\n");

            _mediaElement.load();

        }



        function pauseMedia() {

            _output.appendText("pause\n");

            _mediaElement.pause();

        }



        function setSrc(url:String) {

            _output.appendText("setSrc: " + url + "\n");

            _mediaElement.setSrc(url);

        }



        function stopMedia() {

            _output.appendText("stop\n");

            _mediaElement.stop();

        }



        function setCurrentTime(time:Number) {

            _output.appendText("seek: " + time.toString() + "\n");

            _mediaElement.setCurrentTime(time);

        }



        function setVolume(volume:Number) {

            _output.appendText("volume: " + volume.toString() + "\n");

            _mediaElement.setVolume(volume);

            toggleVolumeIcons(volume);

        }



        function setMuted(muted:Boolean) {

            _output.appendText("muted: " + muted.toString() + "\n");

            _mediaElement.setMuted(muted);

            toggleVolumeIcons(_mediaElement.getVolume());

        }



        function setVideoSize(width:Number, height:Number) {

            _output.appendText("setVideoSize: " + width.toString() + "," + height.toString() + "\n");



            _stageWidth = width;

            _stageHeight = height;



            if (_video != null) {

                repositionVideo();

                positionControls();

                //_fullscreenButton.x = stage.stageWidth - _fullscreenButton.width - 10;

                _output.appendText("result: " + _video.width.toString() + "," + _video.height.toString() + "\n");

            }



            

        }

        

        function positionFullscreenButton(x:Number, y:Number, visibleAndAbove:Boolean ) {

            

            _output.appendText("position FS: " + x.toString() + "x" + y.toString() + "\n");

            

            // bottom corner

            /*

            _fullscreenButton.x = stage.stageWidth - _fullscreenButton.width

            _fullscreenButton.y = stage.stageHeight - _fullscreenButton.height;

            */

            

            // position just above

            if (visibleAndAbove) {

                _fullscreenButton.x = x+1;

                _fullscreenButton.y = y - _fullscreenButton.height+1;   

            } else {

                _fullscreenButton.x = x;

                _fullscreenButton.y = y;    

            }

            

            // check for oversizing

            if ((_fullscreenButton.x + _fullscreenButton.width) > stage.stageWidth)

                _fullscreenButton.x = stage.stageWidth - _fullscreenButton.width;

            

            // show it!

            if (visibleAndAbove) {

                _fullscreenButton.alpha = 1;

            }

        }

        

        function hideFullscreenButton() {

        

            //_fullscreenButton.visible = false;

            _fullscreenButton.alpha = 0;

        }       

        

        // END: external interface

        



        function repositionVideo():void {

            var fullscreen;

            if (stage.displayState == "fullScreen") {

                fullscreen = true;

            } else {

                fullscreen = false;

            }

            

            _output.appendText("positioning video "+stage.displayState+"\n");



            if (_mediaElement is VideoElement) {



                if (isNaN(_nativeVideoWidth) || isNaN(_nativeVideoHeight) || _nativeVideoWidth <= 0 || _nativeVideoHeight <= 0) {

                    _output.appendText("ERR: I dont' have the native dimension\n");

                    return;

                }

    

                // calculate ratios

                var stageRatio, nativeRatio;

                

                _video.x = 0;

                _video.y = 0;           

                

                if(fullscreen == true) {

                    stageRatio = flash.system.Capabilities.screenResolutionX/flash.system.Capabilities.screenResolutionY;

                    nativeRatio = _nativeVideoWidth/_nativeVideoHeight;



                    // adjust size and position

                    if (nativeRatio > stageRatio) {

                        _mediaElement.setSize(flash.system.Capabilities.screenResolutionX, _nativeVideoHeight * flash.system.Capabilities.screenResolutionX / _nativeVideoWidth);

                        _video.y = flash.system.Capabilities.screenResolutionY/2 - _video.height/2;

                    } else if (stageRatio > nativeRatio) {

                        _mediaElement.setSize(_nativeVideoWidth * flash.system.Capabilities.screenResolutionY / _nativeVideoHeight, flash.system.Capabilities.screenResolutionY);                   

                        _video.x = flash.system.Capabilities.screenResolutionX/2 - _video.width/2;

                    } else if (stageRatio == nativeRatio) {

                        _mediaElement.setSize(flash.system.Capabilities.screenResolutionX, flash.system.Capabilities.screenResolutionY);

                    }

                    

                } else {

                    stageRatio = _stageWidth/_stageHeight;

                    nativeRatio = _nativeVideoWidth/_nativeVideoHeight;

                

                    // adjust size and position

                    if (nativeRatio > stageRatio) {

                        _mediaElement.setSize(_stageWidth, _nativeVideoHeight * _stageWidth / _nativeVideoWidth);                   

                        _video.y = _stageHeight/2 - _video.height/2;

                    } else if (stageRatio > nativeRatio) {

                        _mediaElement.setSize( _nativeVideoWidth * _stageHeight / _nativeVideoHeight, _stageHeight);

                        _video.x = _stageWidth/2 - _video.width/2;

                    } else if (stageRatio == nativeRatio) {

                        _mediaElement.setSize(_stageWidth, _stageHeight);

                    }

                    

                }

                

            } else if (_mediaElement is YouTubeElement) {

                if(fullscreen == true) {

                    _mediaElement.setSize(flash.system.Capabilities.screenResolutionX, flash.system.Capabilities.screenResolutionY);

                

                } else {

                    _mediaElement.setSize(_stageWidth, _stageHeight);

                    

                }

            

            }



            positionControls();

        }



        // SEND events to JavaScript

        public function sendEvent(eventName:String, eventValues:String) {           



            // special video event

            if (eventName == HtmlMediaEvent.LOADEDMETADATA && _isVideo) {

                

                _output.appendText("METADATA RECEIVED: ");

                

                try {

                    if (_mediaElement is VideoElement) {

                        _nativeVideoWidth = (_mediaElement as VideoElement).videoWidth;

                        _nativeVideoHeight = (_mediaElement as VideoElement).videoHeight;

                    }

                } catch (e:Error) {

                    _output.appendText(e.toString() + "\n");

                }

                

                _output.appendText(_nativeVideoWidth.toString() + "x" + _nativeVideoHeight.toString() + "\n");

                



                if(stage.displayState == "fullScreen" ) {

                    setVideoSize(_nativeVideoWidth, _nativeVideoHeight);

                }

                repositionVideo();

                

            }



            updateControls(eventName);



            //trace((_mediaElement.duration()*1).toString() + " / " + (_mediaElement.currentTime()*1).toString());

            //trace("CurrentProgress:"+_mediaElement.currentProgress());

            

            if (ExternalInterface.objectID != null && ExternalInterface.objectID.toString() != "") {

                

                //_output.appendText("event:" + eventName + " : " + eventValues);

                //trace("event", eventName, eventValues);

    

                if (eventValues == null)

                    eventValues == "";



                if (_isVideo) {

                    eventValues += (eventValues != "" ? "," : "") + "isFullScreen:" + _isFullScreen;

                }



                eventValues = "{" + eventValues + "}";

    

                /*

                OLD DIRECT METHOD

                ExternalInterface.call(

                    "function(id, name) { mejs.MediaPluginBridge.fireEvent(id,name," + eventValues + "); }", 

                    ExternalInterface.objectID, 

                    eventName);

                */              

                

                // use set timeout for performance reasons

                //if (!_alwaysShowControls) {

                    ExternalInterface.call("setTimeout", "mejs.MediaPluginBridge.fireEvent('" + ExternalInterface.objectID + "','" + eventName + "'," + eventValues + ")",0);

                //}

            }

        }





        function updateControls(eventName:String):void {



            //trace("updating controls");

            

            try {

                // update controls

                switch (eventName) {

                    case "pause":

                    case "paused":

                    case "ended":

                        _playButton.visible = true;

                        _pauseButton.visible = false;

                        break;

                    case "play":

                    case "playing":

                        _playButton.visible = false;

                        _pauseButton.visible = true;

                        break;

                }

                

                if (eventName == HtmlMediaEvent.TIMEUPDATE ||

                    eventName == HtmlMediaEvent.PROGRESS || 

                    eventName == HtmlMediaEvent.FULLSCREENCHANGE) {

                

                    //_duration.text = (_mediaElement.duration()*1).toString(); 

                    _duration.text =  secondsToTimeCode(_mediaElement.duration());

                    //_currentTime.text = (_mediaElement.currentTime()*1).toString(); 

                    _currentTime.text =  secondsToTimeCode(_mediaElement.currentTime());

        

                    var pct:Number =  (_mediaElement.currentTime() / _mediaElement.duration()) *_scrubTrack.scaleX;

                    

                    _scrubBar.scaleX = pct;

                    _scrubLoaded.scaleX = (_mediaElement.currentProgress()*_scrubTrack.scaleX)/100;

                }

            } catch (error:Error) {

                trace("error: " + error.toString());

            

            }



        }



        // START: utility

        function secondsToTimeCode(seconds:Number):String {

            var timeCode:String = "";

            seconds = Math.round(seconds);

            var minutes:Number = Math.floor(seconds / 60);

            timeCode = (minutes >= 10) ? minutes.toString() : "0" + minutes.toString();

            seconds = Math.floor(seconds % 60);

            timeCode += ":" + ((seconds >= 10) ? seconds.toString() : "0" + seconds.toString());

            return timeCode; //minutes.toString() + ":" + seconds.toString();

        }

        

        function applyColor(item:Object, color:String):void {

            

            var myColor:ColorTransform = item.transform.colorTransform;

            myColor.color = Number(color);

            item.transform.colorTransform = myColor;

        }

        // END: utility



    }

  //END FlashMediaElement.as



}





    class HtmlMediaEvent {



        public static var LOADED_DATA:String = "loadeddata";

        public static var PROGRESS:String = "progress";

        public static var TIMEUPDATE:String = "timeupdate";

        public static var SEEKED:String = "seeked";

        public static var PLAY:String = "play";

        public static var PLAYING:String = "playing";

        public static var PAUSE:String = "pause";

        public static var LOADEDMETADATA:String = "loadedmetadata";

        public static var ENDED:String = "ended";

        public static var VOLUMECHANGE:String = "volumechange";

        public static var STOP:String = "stop";

        

        // new : 2/15/2011

        public static var LOADSTART:String = "loadstart";

        public static var CANPLAY:String = "canplay";

        // new : 3/3/2011

        public static var LOADEDDATA:String = "loadeddata";

        

        // new : 4/12/2011

        public static var SEEKING:String = "seeking";       

        

        // new : 1/2/2012

        public static var FULLSCREENCHANGE:String = "fullscreenchange";     

    }



    //START IMediaElement.as

    interface IMediaElement {



        function play():void;



        function pause():void;



        function load():void;



        function stop():void;



        function setSrc(url:String):void;

        

        function setSize(width:Number, height:Number):void;



        function setCurrentTime(pos:Number):void;



        function setVolume(vol:Number):void;

        

        function getVolume():Number;



        function setMuted(muted:Boolean):void;



        function duration():Number;



        function currentTime():Number;

        

        function currentProgress():Number;

        

    }

    //END IMediaElement.as



    //START AudioElement.as

    import flash.events.Event;

    import flash.events.IOErrorEvent;

    import flash.events.ProgressEvent;

    import flash.events.TimerEvent;

    import flash.media.ID3Info;

    import flash.media.Sound;

    import flash.media.SoundChannel;

    import flash.media.SoundLoaderContext;

    import flash.media.SoundTransform;

    import flash.net.URLRequest;

    import flash.utils.Timer;







    /**

    * ...

    * @author DefaultUser (Tools -> Custom Arguments...)

    */

    class AudioElement implements IMediaElement

    {



        private var _sound:Sound;

        private var _soundTransform:SoundTransform;

        private var _soundChannel:SoundChannel;

        private var _soundLoaderContext:SoundLoaderContext;



        private var _volume:Number = 1;

        private var _preMuteVolume:Number = 0;

        private var _isMuted:Boolean = false;

        private var _isPaused:Boolean = true;

        private var _isEnded:Boolean = false;

        private var _isLoaded:Boolean = false;

        private var _currentTime:Number = 0;

        private var _duration:Number = 0;

        private var _bytesLoaded:Number = 0;

        private var _bytesTotal:Number = 0;

        private var _bufferedTime:Number = 0;

        private var _bufferingChanged:Boolean = false;



        private var _currentUrl:String = "";

        private var _autoplay:Boolean = true;

        private var _preload:String = "";



        private var _element:FlashMediaElement;

        private var _timer:Timer;

        private var _firedCanPlay:Boolean = false;



        public function setSize(width:Number, height:Number):void {

            // do nothing!

        }



        public function duration():Number {

            return _duration;

        }



        public function currentTime():Number {

            return _currentTime;

        }

        

        public function currentProgress():Number {

                return Math.round(_bytesLoaded/_bytesTotal*100);

        }



        public function AudioElement(element:FlashMediaElement, autoplay:Boolean, preload:String, timerRate:Number, startVolume:Number) 

        {

            _element = element;

            _autoplay = autoplay;

            _volume = startVolume;

            _preload = preload;



            _timer = new Timer(timerRate);

            _timer.addEventListener(TimerEvent.TIMER, timerEventHandler);



            _soundTransform = new SoundTransform(_volume);

            _soundLoaderContext = new SoundLoaderContext();

        }



        // events

        function progressHandler(e:ProgressEvent):void {



            _bytesLoaded = e.bytesLoaded;

            _bytesTotal = e.bytesTotal;



            // this happens too much to send every time

            //sendEvent(HtmlMediaEvent.PROGRESS);

            

            // so now we just trigger a flag and send with the timer

            _bufferingChanged = true;

        }



        function id3Handler(e:Event):void {

            sendEvent(HtmlMediaEvent.LOADEDMETADATA);           

            

            try {

                var id3:ID3Info = _sound.id3;

                var obj = {

                    type:'id3',

                    album:id3.album,

                    artist:id3.artist,

                    comment:id3.comment,

                    genre:id3.genre,

                    songName:id3.songName,

                    track:id3.track,

                    year:id3.year

                }

            } catch (err:Error) {}

            

            

        }



        function timerEventHandler(e:TimerEvent) {

            _currentTime = _soundChannel.position/1000;



            // calculate duration

            var duration = Math.round(_sound.length * _sound.bytesTotal/_sound.bytesLoaded/100) / 10;



            // check to see if the estimated duration changed

            if (_duration != duration && !isNaN(duration)) {



                _duration = duration;

                sendEvent(HtmlMediaEvent.LOADEDMETADATA);

            }

            

            // check for progress

            if (_bufferingChanged) {

                

                sendEvent(HtmlMediaEvent.PROGRESS);

            

                _bufferingChanged = false;

            }



            // send timeupdate

            sendEvent(HtmlMediaEvent.TIMEUPDATE);



            // sometimes the ended event doesn't fire, here's a fake one

            if (_duration > 0 && _currentTime >= _duration-0.2) {

                handleEnded();

            }

        }



        function soundCompleteHandler(e:Event) {

            handleEnded();

        }



        function handleEnded():void {

            _timer.stop();

            _currentTime = 0;

            _isEnded = true;



            sendEvent(HtmlMediaEvent.ENDED);

        }



        //events





        // METHODS

        public function setSrc(url:String):void {

            _currentUrl = url;

            _isLoaded = false;

        }





        public function load():void {



            if (_currentUrl == "")

                return;



            _sound = new Sound();

            //sound.addEventListener(IOErrorEvent.IO_ERROR,errorHandler);

            _sound.addEventListener(ProgressEvent.PROGRESS,progressHandler);

            _sound.addEventListener(Event.ID3,id3Handler);

            _sound.load(new URLRequest(_currentUrl));

            _currentTime = 0;

            

            sendEvent(HtmlMediaEvent.LOADSTART);



            _isLoaded = true;

                        

            sendEvent(HtmlMediaEvent.LOADEDDATA);

            sendEvent(HtmlMediaEvent.CANPLAY);              

            _firedCanPlay = true;

            

            if (_playAfterLoading) {

                _playAfterLoading = false;

                play();

            }                       

        }



        private var _playAfterLoading:Boolean= false;



        public function play():void {



            if (!_isLoaded) {

                _playAfterLoading = true;

                load();

                return;

            }



            _timer.stop();



            _soundChannel = _sound.play(_currentTime*1000, 0, _soundTransform);

            _soundChannel.removeEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);

            _soundChannel.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);



            _timer.start();

            

            didStartPlaying();

        }



        public function pause():void {



            _timer.stop();

            if (_soundChannel != null) {

                _currentTime = _soundChannel.position/1000;

                _soundChannel.stop();           

            }



            _isPaused = true;

            sendEvent(HtmlMediaEvent.PAUSE);

        }





        public function stop():void {

            if (_timer != null) {

                _timer.stop();

            }

            if (_soundChannel != null) {

                _soundChannel.stop();

                _sound.close();

            }

            unload();

            sendEvent(HtmlMediaEvent.STOP);

        }



        public function setCurrentTime(pos:Number):void {

            sendEvent(HtmlMediaEvent.SEEKING);

            _timer.stop();

            _currentTime = pos;

            _soundChannel.stop();

            _sound.length

            _soundChannel = _sound.play(_currentTime * 1000, 0, _soundTransform);

            sendEvent(HtmlMediaEvent.SEEKED);



            _timer.start();

            

            didStartPlaying();

        }

        

        private function didStartPlaying():void {

            _isPaused = false;

            sendEvent(HtmlMediaEvent.PLAY);

            sendEvent(HtmlMediaEvent.PLAYING);

            if (!_firedCanPlay) {

                sendEvent(HtmlMediaEvent.LOADEDDATA);

                sendEvent(HtmlMediaEvent.CANPLAY);              

                _firedCanPlay = true;

            }

        }





        public function setVolume(volume:Number):void {



            _volume = volume;

            _soundTransform.volume = volume;



            if (_soundChannel != null) {

                _soundChannel.soundTransform = _soundTransform;

            }



            _isMuted = (_volume == 0);



            sendEvent(HtmlMediaEvent.VOLUMECHANGE);

        }

        

        public function getVolume():Number {

            if(_isMuted) {

                return 0;

            } else {

                return _volume;

            }

        }





        public function setMuted(muted:Boolean):void {



            // ignore if already set

            if ( (muted && _isMuted) || (!muted && !_isMuted))

                return;



            if (muted) {

                _preMuteVolume = _soundTransform.volume;

                setVolume(0);

            } else {

                setVolume(_preMuteVolume);

            }



            _isMuted = muted;

        }



        public function unload():void {

            _sound = null;

            _isLoaded = false;

        }



        private function sendEvent(eventName:String) {



            // calculate this to mimic HTML5

            _bufferedTime = _bytesLoaded / _bytesTotal * _duration;



            // build JSON

            var values:String = "duration:" + _duration + 

                            ",currentTime:" + _currentTime + 

                            ",muted:" + _isMuted + 

                            ",paused:" + _isPaused + 

                            ",ended:" + _isEnded + 

                            ",volume:" + _volume +

                            ",src:\"" + _currentUrl + "\"" +

                            ",bytesTotal:" + _bytesTotal +

                            ",bufferedBytes:" + _bytesLoaded +

                            ",bufferedTime:" + _bufferedTime +

                            "";



            _element.sendEvent(eventName, values);

        }



    }

    //END AudioElement.as



    //START VideoElement.as

    import flash.display.Sprite;

  import flash.events.*;

  import flash.net.NetConnection;

  import flash.net.NetStream;

  import flash.media.Video;

  import flash.media.SoundTransform;

  import flash.utils.Timer;





  class VideoElement extends Sprite implements IMediaElement

  {

    private var _currentUrl:String = "";

    private var _autoplay:Boolean = true;

    private var _preload:String = "";

    private var _isPreloading:Boolean = false;



    private var _connection:NetConnection;

    private var _stream:NetStream;

    private var _video:Video;

    private var _element:FlashMediaElement;

    private var _soundTransform;

    private var _oldVolume:Number = 1;



    // event values

    private var _duration:Number = 0;

    private var _framerate:Number;

    private var _isPaused:Boolean = true;

    private var _isEnded:Boolean = false;

    private var _volume:Number = 1;

    private var _isMuted:Boolean = false;



    private var _bytesLoaded:Number = 0;

    private var _bytesTotal:Number = 0;

    private var _bufferedTime:Number = 0;

    private var _bufferEmpty:Boolean = false;

    private var _bufferingChanged:Boolean = false;

    private var _seekOffset:Number = 0;





    private var _videoWidth:Number = -1;

    private var _videoHeight:Number = -1;



    private var _timer:Timer;



    private var _isRTMP:Boolean = false;

    private var _streamer:String = "";

    private var _isConnected:Boolean = false;

    private var _playWhenConnected:Boolean = false;

    private var _hasStartedPlaying:Boolean = false;



    private var _parentReference:Object;

    private var _pseudoStreamingEnabled:Boolean = false;

    private var _pseudoStreamingStartQueryParam:String = "start";



    public function setReference(arg:Object):void {

      _parentReference = arg;

    }



    public function setSize(width:Number, height:Number):void {

      _video.width = width;

      _video.height = height;

    }



    public function setPseudoStreaming(enablePseudoStreaming:Boolean):void {

      _pseudoStreamingEnabled = enablePseudoStreaming;

    }



    public function setPseudoStreamingStartParam(pseudoStreamingStartQueryParam:String):void {

      _pseudoStreamingStartQueryParam = pseudoStreamingStartQueryParam;

    }



    public function get video():Video {

      return _video;

    }



    public function get videoHeight():Number {

      return _videoHeight;

    }



    public function get videoWidth():Number {

      return _videoWidth;

    }





    public function duration():Number {

      return _duration;

    }



    public function currentProgress():Number {

      if(_stream != null) {

        return Math.round(_stream.bytesLoaded/_stream.bytesTotal*100);

      } else {

        return 0;

      }

    }



    public function currentTime():Number {

      var currentTime:Number = 0;

      if (_stream != null) {

        currentTime = _stream.time;

        if (_pseudoStreamingEnabled) {

          currentTime += _seekOffset;

        }

      }

      return currentTime;

    }





    // (1) load()

    // calls _connection.connect();

    // waits for NetConnection.Connect.Success

    // _stream gets created





    public function VideoElement(element:FlashMediaElement, autoplay:Boolean, preload:String, timerRate:Number, startVolume:Number, streamer:String)

    {

      _element = element;

      _autoplay = autoplay;

      _volume = startVolume;

      _preload = preload;

      _streamer = streamer;



      _video = new Video();

      addChild(_video);



      _connection = new NetConnection();

      _connection.client = { onBWDone: function():void{} };

      _connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);

      _connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);

      //_connection.connect(null);



      _timer = new Timer(timerRate);

      _timer.addEventListener("timer", timerHandler);



    }



    private function timerHandler(e:TimerEvent) {



      _bytesLoaded = _stream.bytesLoaded;

      _bytesTotal = _stream.bytesTotal;



      if (!_isPaused) {

        sendEvent(HtmlMediaEvent.TIMEUPDATE);

      }



      //trace("bytes", _bytesLoaded, _bytesTotal);



      if (_bytesLoaded < _bytesTotal)

        sendEvent(HtmlMediaEvent.PROGRESS);



    }



    // internal events

    private function netStatusHandler(event:NetStatusEvent):void {

      trace("netStatus", event.info.code);



      switch (event.info.code) {



        case "NetStream.Buffer.Empty":

          _bufferEmpty = true;

          _isEnded ? sendEvent(HtmlMediaEvent.ENDED) : null;

          break;



        case "NetStream.Buffer.Full":

          _bytesLoaded = _stream.bytesLoaded;

          _bytesTotal = _stream.bytesTotal;

          _bufferEmpty = false;



          sendEvent(HtmlMediaEvent.PROGRESS);

          break;



        case "NetConnection.Connect.Success":

          connectStream();

          break;

        case "NetStream.Play.StreamNotFound":

          trace("Unable to locate video");

          break;



        // STREAM

        case "NetStream.Play.Start":



          _isPaused = false;

          sendEvent(HtmlMediaEvent.LOADEDDATA);

          sendEvent(HtmlMediaEvent.CANPLAY);



          if (!_isPreloading) {



            sendEvent(HtmlMediaEvent.PLAY);

            sendEvent(HtmlMediaEvent.PLAYING);



          }



          _timer.start();



          break;



        case "NetStream.Seek.Notify":

          sendEvent(HtmlMediaEvent.SEEKED);

          break;



        case "NetStream.Pause.Notify":

          _isPaused = true;

          sendEvent(HtmlMediaEvent.PAUSE);

          break;



        case "NetStream.Play.Stop":

          _isEnded = true;

          _isPaused = false;

          _timer.stop();

          _bufferEmpty ? sendEvent(HtmlMediaEvent.ENDED) : null;

          break;



      }

    }





    private function securityErrorHandler(event:SecurityErrorEvent):void {

      trace("securityErrorHandler: " + event);

    }



    private function asyncErrorHandler(event:AsyncErrorEvent):void {

      // ignore AsyncErrorEvent events.

    }





    private function onMetaDataHandler(info:Object):void {

      // Only set the duration when we first load the video

      if (_duration == 0) {

        _duration = info.duration;

      }

      _framerate = info.framerate;

      _videoWidth = info.width;

      _videoHeight = info.height;





      // set size?



      sendEvent(HtmlMediaEvent.LOADEDMETADATA);







      if (_isPreloading) {



        _stream.pause();

        _isPaused = true;

        _isPreloading = false;



        sendEvent(HtmlMediaEvent.PROGRESS);

        sendEvent(HtmlMediaEvent.TIMEUPDATE);



      }

    }









    // interface members

    public function setSrc(url:String):void {

      if (_isConnected && _stream) {

        // stop and restart

        _stream.pause();

      }



      _currentUrl = url;

      _isRTMP = !!_currentUrl.match(/^rtmp(s|t|e|te)?\:\/\//) || _streamer != "";

      _isConnected = false;

      _hasStartedPlaying = false;

    }



    public function load():void {

      // disconnect existing stream and connection

      if (_isConnected && _stream) {

        _stream.pause();

        _stream.close();

        _connection.close();

      }

      _isConnected = false;

      _isPreloading = false;





      _isEnded = false;

      _bufferEmpty = false;



      // start new connection

      if (_isRTMP) {

        var rtmpInfo:Object = parseRTMP(_currentUrl);

        if (_streamer != "") {

          rtmpInfo.server = _streamer;

          rtmpInfo.stream = _currentUrl;



        }

        _connection.connect(rtmpInfo.server);

      } else {

        _connection.connect(null);

      }



      // in a few moments the "NetConnection.Connect.Success" event will fire

      // and call createConnection which finishes the "load" sequence

      sendEvent(HtmlMediaEvent.LOADSTART);

    }





    private function connectStream():void {

      trace("connectStream");

      _stream = new NetStream(_connection);



      // explicitly set the sound since it could have come before the connection was made

      _soundTransform = new SoundTransform(_volume);

      _stream.soundTransform = _soundTransform;



      // set the buffer to ensure nice playback

      _stream.bufferTime = 1;

      _stream.bufferTimeMax = 3;



      _stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); // same event as connection

      _stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);



      var customClient:Object = new Object();

      customClient.onMetaData = onMetaDataHandler;

      _stream.client = customClient;



      _video.attachNetStream(_stream);



      // start downloading without playing )based on preload and play() hasn't been called)

      // I wish flash had a load() command to make this less awkward

      if (_preload != "none" && !_playWhenConnected) {

        _isPaused = true;

        //stream.bufferTime = 20;

        _stream.play(getCurrentUrl(0), 0, 0);

        _stream.pause();



        _isPreloading = true;



        //_stream.pause();

        //

        //sendEvent(HtmlMediaEvent.PAUSE); // have to send this because the "playing" event gets sent via event handlers

      }



      _isConnected = true;



      if (_playWhenConnected && !_hasStartedPlaying) {

        play();

        _playWhenConnected = false;

      }



    }



    public function play():void {



      if (!_hasStartedPlaying && !_isConnected) {

        _playWhenConnected = true;

        load();

        return;

      }



      if (_hasStartedPlaying) {

        if (_isPaused) {

          _stream.resume();

          _timer.start();

          _isPaused = false;

          sendEvent(HtmlMediaEvent.PLAY);

          sendEvent(HtmlMediaEvent.PLAYING);

        }

      } else {



        if (_isRTMP) {

          var rtmpInfo:Object = parseRTMP(_currentUrl);

          _stream.play(rtmpInfo.stream);

        } else {

          _stream.play(getCurrentUrl(0));

        }

        _timer.start();

        _isPaused = false;

        _hasStartedPlaying = true;



        // don't toss play/playing events here, because we haven't sent a

        // canplay / loadeddata event yet. that'll be handled in the net

        // event listener

      }



    }



    public function pause():void {

      if (_stream == null)

        return;



      _stream.pause();

      _isPaused = true;



      if (_bytesLoaded == _bytesTotal) {

        _timer.stop();

      }



      _isPaused = true;

      sendEvent(HtmlMediaEvent.PAUSE);

    }



    public function stop():void {

      if (_stream == null)

        return;



      _stream.close();

      _isPaused = false;

      _timer.stop();

      sendEvent(HtmlMediaEvent.STOP);

    }





    public function setCurrentTime(pos:Number):void {

      if (_stream == null) {

        return;

      }



      // Calculate the position of the buffered video

      var bufferPosition:Number = _bytesLoaded / _bytesTotal * _duration;



      if (_pseudoStreamingEnabled) {

        sendEvent(HtmlMediaEvent.SEEKING);

        // Normal seek if it is in buffer and this is the first seek

        if (pos < bufferPosition && _seekOffset == 0) {

          _stream.seek(pos);

        }

        else {

          // Uses server-side pseudo-streaming to seek

          _stream.play(getCurrentUrl(pos));

          _seekOffset = pos;

        }

      }

      else {

        sendEvent(HtmlMediaEvent.SEEKING);

        _stream.seek(pos);

      }



      if (!_isEnded) {

        sendEvent(HtmlMediaEvent.TIMEUPDATE);

      }

    }



    public function setVolume(volume:Number):void {

      if (_stream != null) {

        _soundTransform = new SoundTransform(volume);

        _stream.soundTransform = _soundTransform;

      }



      _volume = volume;



      _isMuted = (_volume == 0);



      sendEvent(HtmlMediaEvent.VOLUMECHANGE);

    }



    public function getVolume():Number {

      if(_isMuted) {

        return 0;

      } else {

        return _volume;

      }

    }



    public function setMuted(muted:Boolean):void {



      if (_isMuted == muted)

        return;



      if (muted) {

        _oldVolume = (_stream == null) ? _oldVolume : _stream.soundTransform.volume;

        setVolume(0);

      } else {

        setVolume(_oldVolume);

      }



      _isMuted = muted;

    }





    private function sendEvent(eventName:String) {



      // calculate this to mimic HTML5

      _bufferedTime = _bytesLoaded / _bytesTotal * _duration;



      // build JSON

      var values:String =

        "duration:" + _duration +

          ",framerate:" + _framerate +

          ",currentTime:" + currentTime() +

          ",muted:" + _isMuted +

          ",paused:" + _isPaused +

          ",ended:" + _isEnded +

          ",volume:" + _volume +

          ",src:\"" + _currentUrl + "\"" +

          ",bytesTotal:" + _bytesTotal +

          ",bufferedBytes:" + _bytesLoaded +

          ",bufferedTime:" + _bufferedTime +

          ",videoWidth:" + _videoWidth +

          ",videoHeight:" + _videoHeight +

          "";



      _element.sendEvent(eventName, values);

    }



    private function parseRTMP(url:String) {

      var match:Array = url.match(/(.*)\/((flv|mp4|mp3):.*)/);

      var rtmpInfo:Object = {

        server: null,

        stream: null

      };



      if (match) {

        rtmpInfo.server = match[1];

        rtmpInfo.stream = match[2];

      }

      else {

        rtmpInfo.server = url.replace(/\/[^\/]+$/,"/");

        rtmpInfo.stream = url.split("/").pop();

      }



      trace("parseRTMP - server: " + rtmpInfo.server + " stream: " + rtmpInfo.stream);



      return rtmpInfo;

    }



    private function getCurrentUrl(pos:Number):String {

      var url:String = _currentUrl;

      if (_pseudoStreamingEnabled) {

        if (url.indexOf('?') > -1) {

          url = url + '&' + _pseudoStreamingStartQueryParam + '=' + pos;

        }

        else {

          url = url + '?' + _pseudoStreamingStartQueryParam + '=' + pos;

        }

      }

      return url;

    }

  }

  //END VideoElement.as



  //START YouTubeElement.as

  import flash.display.Sprite;

    import flash.events.*;

    import flash.net.NetConnection;

    import flash.net.NetStream;

    import flash.media.Video;

    import flash.media.SoundTransform;

    import flash.utils.Timer;

    import flash.net.URLLoader;

    import flash.net.URLRequest;

    import flash.net.URLVariables;

    import flash.net.URLRequestMethod;

    import flash.display.MovieClip;

     import flash.display.Loader;

     import flash.display.DisplayObject;







    class YouTubeElement extends Sprite implements IMediaElement 

    {

        private var _currentUrl:String = "";

        private var _autoplay:Boolean = true;

        private var _preload:String = "";

        

        private var _element:FlashMediaElement;



        // event values

        private var _currentTime:Number = 0;

        private var _duration:Number = 0;

        private var _framerate:Number;

        private var _isPaused:Boolean = true;

        private var _isEnded:Boolean = false;

        private var _volume:Number = 1;

        private var _isMuted:Boolean = false;



        private var _bytesLoaded:Number = 0;

        private var _bytesTotal:Number = 0;

        private var _bufferedTime:Number = 0;

        private var _bufferEmpty:Boolean = false;



        private var _videoWidth:Number = -1;

        private var _videoHeight:Number = -1;



        private var _timer:Timer;

        

        // YouTube stuff

        private var _playerLoader:Loader;

        private var _player:Object = null;

        private var _playerIsLoaded:Boolean = false;

        private var _youTubeId:String = "";

        

        //http://code.google.com/p/gdata-samples/source/browse/trunk/ytplayer/actionscript3/com/google/youtube/examples/AS3Player.as

        private static const WIDESCREEN_ASPECT_RATIO:String = "widescreen";

        private static const QUALITY_TO_PLAYER_WIDTH:Object = {

            small: 320,

            medium: 640,

            large: 854,

            hd720: 1280

        };

        private static const STATE_ENDED:Number = 0;

        private static const STATE_PLAYING:Number = 1;

        private static const STATE_PAUSED:Number = 2;

        private static const STATE_CUED:Number = 5;

        



        public function get player() {

            return _player;

        }

        

        public function setSize(width:Number, height:Number):void {

            if (_player != null) {

                _player.setSize(width, height);

            } else {

                initHeight = height;

                initWidth = width;

            }

        }       



        public function get videoHeight():Number {

            return _videoHeight;

        }



        public function get videoWidth():Number {

            return _videoWidth;

        }





        public function duration():Number {

            return _duration;

        }

        

        public function currentProgress():Number {

            if(_bytesTotal> 0) {

                return Math.round(_bytesLoaded/_bytesTotal*100);

            } else {

                return 0;

            }

        }



        public function currentTime():Number {

            return _currentTime;

        }





        public var initHeight:Number;

        public var initWidth:Number;



        // (1) load()

        // calls _connection.connect(); 

        // waits for NetConnection.Connect.Success

        // _stream gets created

        

        private var _isChromeless:Boolean = false;





        public function YouTubeElement(element:FlashMediaElement, autoplay:Boolean, preload:String, timerRate:Number, startVolume:Number) 

        {

            _element = element;

            _autoplay = autoplay;

            _volume = startVolume;

            _preload = preload;

            initHeight = 0;

            initWidth = 0;



            _playerLoader = new Loader();

            _playerLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, playerLoaderInitHandler);



            // chromeless

            if (_isChromeless) {

                _playerLoader.load(new URLRequest("//www.youtube.com/apiplayer?version=3&controls=1&rel=0&showinfo=0&iv_load_policy=1"));

            }

            

            

            _timer = new Timer(timerRate);

            _timer.addEventListener("timer", timerHandler);

            _timer.start();

        }

        

        private function playerLoaderInitHandler(event:Event):void {

            

            trace("yt player init");

            

            _element.addChild(_playerLoader.content);

            _element.setControlDepth();

            _playerLoader.content.addEventListener("onReady", onPlayerReady);

            _playerLoader.content.addEventListener("onError", onPlayerError);

            _playerLoader.content.addEventListener("onStateChange", onPlayerStateChange);

            _playerLoader.content.addEventListener("onPlaybackQualityChange", onVideoPlaybackQualityChange);

        }       

        

        private function onPlayerReady(event:Event):void {

            _playerIsLoaded = true;

            

            _player = _playerLoader.content;

            

            if (initHeight > 0 && initWidth > 0)

                _player.setSize(initWidth, initHeight);

            

            if (_youTubeId != "") { //  && _isChromeless) {

                if (_autoplay) {

                    player.loadVideoById(_youTubeId);

                } else {

                    player.cueVideoById(_youTubeId);

                }

                _timer.start();

            }

        }       

        

        private function onPlayerError(event:Event):void {

            // trace("Player error:", Object(event).data);

        }

        

        private function onPlayerStateChange(event:Event):void {

            trace("State is", Object(event).data);

            

            _duration = _player.getDuration();

            

            switch (Object(event).data) {

                case STATE_ENDED:

                    _isEnded = true;

                    _isPaused = false;

                    

                    sendEvent(HtmlMediaEvent.ENDED);

                    

                    break;

                

                case STATE_PLAYING:

                    _isEnded = false;

                    _isPaused = false;

                    

                    sendEvent(HtmlMediaEvent.PLAY);

                    sendEvent(HtmlMediaEvent.PLAYING);

                    break;

                

                case STATE_PAUSED:

                    _isEnded = false;

                    _isPaused = true;

                    

                    sendEvent(HtmlMediaEvent.PAUSE);

                    

                    break;

                

                case STATE_CUED:

                    sendEvent(HtmlMediaEvent.CANPLAY);

                    

                    // resize?

                    

                    break;

            }

        }

        

        private function onVideoPlaybackQualityChange(event:Event):void {

            trace("Current video quality:", Object(event).data);

            //resizePlayer(Object(event).data);

        }



        private function timerHandler(e:TimerEvent) {

            

            if (_playerIsLoaded) {

                _bytesLoaded = _player.getVideoBytesLoaded();

                _bytesTotal = _player.getVideoBytesTotal();

                _currentTime = player.getCurrentTime();

                

                if (!_isPaused)

                    sendEvent(HtmlMediaEvent.TIMEUPDATE);

    

                if (_bytesLoaded < _bytesTotal)

                    sendEvent(HtmlMediaEvent.PROGRESS);

            }



        }



        private function getYouTubeId(url:String):String {

            // http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0

            // http://www.youtube.com/v/VIDEO_ID?version=3

            // http://youtu.be/Djd6tPrxc08

            

            url = unescape(url);

            

            var youTubeId:String = "";

            

            if (url.indexOf("?") > 0) {

                // assuming: http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0

                youTubeId = getYouTubeIdFromParam(url);

                

                // if it's http://www.youtube.com/v/VIDEO_ID?version=3

                if (youTubeId == "") {

                    youTubeId = getYouTubeIdFromUrl(url);

                }

            } else {

                youTubeId = getYouTubeIdFromUrl(url);

            }

            

            return youTubeId;

        }

        

        // http://www.youtube.com/watch?feature=player_embedded&v=yyWWXSwtPP0

        private function getYouTubeIdFromParam(url:String):String {

            

            

            var youTubeId:String = "";

            var parts:Array = url.split('?');

            var parameters:Array = parts[1].split('&');

            

            for (var i:Number=0; i<parameters.length; i++) {

                var paramParts = parameters[i].split('=');

                if (paramParts[0] == "v") {

            

                    youTubeId = paramParts[1];

                    break;

                }

        

            }

            

            

            return youTubeId;

        }       

        

        

        // http://www.youtube.com/v/VIDEO_ID?version=3

        // http://youtu.be/Djd6tPrxc08

        private function getYouTubeIdFromUrl(url:String):String {

            

            

            var youTubeId:String = "";

            

            // remove any querystring elements

            var parts:Array = url.split('?');

            url = parts[0];

            

            youTubeId = url.substring(url.lastIndexOf("/")+1);

            

            return youTubeId;

        }           





        // interface members

        public function setSrc(url:String):void {

            trace("yt setSrc()" + url );

            

            _currentUrl = url;

            

            _youTubeId = getYouTubeId(url);

            

            if (!_playerIsLoaded && !_isChromeless) {

                _playerLoader.load(new URLRequest("//www.youtube.com/v/" + _youTubeId + "?version=3&controls=0&rel=0&showinfo=0&iv_load_policy=1"));

            }

        }

        

        

        



        public function load():void {

            // do nothing

            trace("yt load()");

                

            if (_playerIsLoaded) {

                player.loadVideoById(_youTubeId);

                _timer.start();

            }  else {

                /*

                if (!_isChromless && _youTubeId != "") {

                    _playerLoader.load(new URLRequest("http://www.youtube.com/v/" + _youTubeId + "?version=3&controls=0&rel=0&showinfo=0&iv_load_policy=1"));

                }

                */

            }

        }

        

        public function play():void {

            if (_playerIsLoaded) {

                _player.playVideo();

            }



        }



        public function pause():void {

            if (_playerIsLoaded) {

                _player.pauseVideo();

            }       

        }



        public function stop():void {

            if (_playerIsLoaded) {

                _player.pauseVideo();

            }   

        }



        public function setCurrentTime(pos:Number):void {

            //_player.seekTo(pos, false);

            _player.seekTo(pos, true); // works in all places now

        }



        public function setVolume(volume:Number):void {

            _player.setVolume(volume*100);

            _volume = volume;

        }



        public function getVolume():Number {

            return _player.getVolume()*100;

        }



        public function setMuted(muted:Boolean):void {

            if (muted) {

                _player.mute();

        

            } else {

                _player.unMute();

            }

            _isMuted = _player.isMuted();

            sendEvent(HtmlMediaEvent.VOLUMECHANGE);

        }





        private function sendEvent(eventName:String) {



            // calculate this to mimic HTML5

            _bufferedTime = _bytesLoaded / _bytesTotal * _duration;



            // build JSON

            var values:String = 

                            "duration:" + _duration + 

                            ",framerate:" + _framerate + 

                            ",currentTime:" + _currentTime + 

                            ",muted:" + _isMuted + 

                            ",paused:" + _isPaused + 

                            ",ended:" + _isEnded + 

                            ",volume:" + _volume +

                            ",src:\"" + _currentUrl + "\"" +

                            ",bytesTotal:" + _bytesTotal +

                            ",bufferedBytes:" + _bytesLoaded +

                            ",bufferedTime:" + _bufferedTime +

                            ",videoWidth:" + _videoWidth +

                            ",videoHeight:" + _videoHeight +

                            "";



            _element.sendEvent(eventName, values);

        }

    }

  //END YouTubeElement.as