package org.mangui.chromeless {
    import flash.net.URLStream;

    import org.mangui.hls.model.Level;
    import org.mangui.hls.*;
    import org.mangui.hls.utils.*;

    import flash.display.*;
    import flash.events.*;
    import flash.external.ExternalInterface;
    import flash.geom.Rectangle;
    import flash.media.Video;
    import flash.media.SoundTransform;
    import flash.media.StageVideo;
    import flash.media.StageVideoAvailability;
    import flash.utils.setTimeout;

    // import com.sociodox.theminer.*;
    public class ChromelessPlayer extends Sprite {
        /** reference to the framework. **/
        private var _hls : HLS;
        /** Sheet to place on top of the video. **/
        private var _sheet : Sprite;
        /** Reference to the stage video element. **/
        private var _stageVideo : StageVideo = null;
        /** Reference to the video element. **/
        private var _video : Video = null;
        /** Video size **/
        private var _videoWidth : int = 0;
        private var _videoHeight : int = 0;
        /** current media position */
        private var _media_position : Number;
        private var _duration : Number;
    /** URL autoload feature */
        private var _autoLoad : Boolean = false;

        /** Initialization. **/
        public function ChromelessPlayer() {
            // Set stage properties
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            stage.fullScreenSourceRect = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
            stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, _onStageVideoState);
            stage.addEventListener(Event.RESIZE, _onStageResize);
            // Draw sheet for catching clicks
            _sheet = new Sprite();
            _sheet.graphics.beginFill(0x000000, 0);
            _sheet.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
            _sheet.addEventListener(MouseEvent.CLICK, _clickHandler);
            _sheet.buttonMode = true;
            addChild(_sheet);
            // Connect getters to JS.
            ExternalInterface.addCallback("getLevel", _getLevel);
            ExternalInterface.addCallback("getLevels", _getLevels);
            ExternalInterface.addCallback("getAutoLevel", _getAutoLevel);
            ExternalInterface.addCallback("getMetrics", _getMetrics);
            ExternalInterface.addCallback("getDuration", _getDuration);
            ExternalInterface.addCallback("getPosition", _getPosition);
            ExternalInterface.addCallback("getPlaybackState", _getPlaybackState);
            ExternalInterface.addCallback("getSeekState", _getSeekState);
            ExternalInterface.addCallback("getType", _getType);
            ExternalInterface.addCallback("getmaxBufferLength", _getmaxBufferLength);
            ExternalInterface.addCallback("getminBufferLength", _getminBufferLength);
            ExternalInterface.addCallback("getlowBufferLength", _getlowBufferLength);
            ExternalInterface.addCallback("getbufferLength", _getbufferLength);
            ExternalInterface.addCallback("getLogDebug", _getLogDebug);
            ExternalInterface.addCallback("getLogDebug2", _getLogDebug2);
            ExternalInterface.addCallback("getCapLeveltoStage", _getCapLeveltoStage);
            ExternalInterface.addCallback("getflushLiveURLCache", _getflushLiveURLCache);
            ExternalInterface.addCallback("getstartFromLevel", _getstartFromLevel);
            ExternalInterface.addCallback("getseekFromLowestLevel", _getseekFromLevel);
            ExternalInterface.addCallback("getJSURLStream", _getJSURLStream);
            ExternalInterface.addCallback("getPlayerVersion", _getPlayerVersion);
            ExternalInterface.addCallback("getAudioTrackList", _getAudioTrackList);
            ExternalInterface.addCallback("getAudioTrackId", _getAudioTrackId);
            // Connect calls to JS.
            ExternalInterface.addCallback("playerLoad", _load);
            ExternalInterface.addCallback("playerPlay", _play);
            ExternalInterface.addCallback("playerPause", _pause);
            ExternalInterface.addCallback("playerResume", _resume);
            ExternalInterface.addCallback("playerSeek", _seek);
            ExternalInterface.addCallback("playerStop", _stop);
            ExternalInterface.addCallback("playerVolume", _volume);
            ExternalInterface.addCallback("playerSetLevel", _setLevel);
            ExternalInterface.addCallback("playerSmoothSetLevel", _smoothSetLevel);
            ExternalInterface.addCallback("playerSetmaxBufferLength", _setmaxBufferLength);
            ExternalInterface.addCallback("playerSetminBufferLength", _setminBufferLength);
            ExternalInterface.addCallback("playerSetlowBufferLength", _setlowBufferLength);
            ExternalInterface.addCallback("playerSetflushLiveURLCache", _setflushLiveURLCache);
            ExternalInterface.addCallback("playerSetstartFromLevel", _setstartFromLevel);
            ExternalInterface.addCallback("playerSetseekFromLevel", _setseekFromLevel);
            ExternalInterface.addCallback("playerSetLogDebug", _setLogDebug);
            ExternalInterface.addCallback("playerSetLogDebug2", _setLogDebug2);
            ExternalInterface.addCallback("playerCapLeveltoStage", _setCapLeveltoStage);
            ExternalInterface.addCallback("playerSetAudioTrack", _setAudioTrack);
            ExternalInterface.addCallback("playerSetJSURLStream", _setJSURLStream);

            setTimeout(_pingJavascript, 50);
        };

        /** Notify javascript the framework is ready. **/
        private function _pingJavascript() : void {
            ExternalInterface.call("onHLSReady", ExternalInterface.objectID);
        };

        /** Forward events from the framework. **/
        private function _completeHandler(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                ExternalInterface.call("onComplete");
            }
        };

        private function _errorHandler(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                var hlsError : HLSError = event.error;
                ExternalInterface.call("onError", hlsError.code, hlsError.url, hlsError.msg);
            }
        };

        private function _fragmentHandler(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                ExternalInterface.call("onFragment", event.metrics.bandwidth, event.metrics.level, stage.stageWidth);
            }
        };

        private function _manifestHandler(event : HLSEvent) : void {
            _duration = event.levels[_hls.startlevel].duration;

            if (_autoLoad) {
                _play();
            }

            if (ExternalInterface.available) {
                ExternalInterface.call("onManifest", _duration);
            }
        };

        private function _mediaTimeHandler(event : HLSEvent) : void {
            _duration = event.mediatime.duration;
            _media_position = event.mediatime.position;
            if (ExternalInterface.available) {
                ExternalInterface.call("onPosition", event.mediatime.position, event.mediatime.duration, event.mediatime.live_sliding,event.mediatime.buffer, event.mediatime.program_date);
            }

            var videoWidth : int = _video ? _video.videoWidth : _stageVideo.videoWidth;
            var videoHeight : int = _video ? _video.videoHeight : _stageVideo.videoHeight;

            if (videoWidth && videoHeight) {
                var changed : Boolean = _videoWidth != videoWidth || _videoHeight != videoHeight;
                if (changed) {
                    _videoHeight = videoHeight;
                    _videoWidth = videoWidth;
                    _resize();
                    if (ExternalInterface.available) {
                        ExternalInterface.call("onVideoSize", _videoWidth, _videoHeight);
                    }
                }
            }
        };

        private function _stateHandler(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                ExternalInterface.call("onState", event.state);
            }
        };

        private function _levelSwitchHandler(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                ExternalInterface.call("onSwitch", event.level);
            }
        };

        private function _audioTracksListChange(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                ExternalInterface.call("onAudioTracksListChange", _getAudioTrackList());
            }
        }

        private function _audioTrackChange(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                ExternalInterface.call("onAudioTrackChange", event.audioTrack);
            }
        }

        /** Javascript getters. **/
        private function _getLevel() : int {
            return _hls.level;
        };

        private function _getLevels() : Vector.<Level> {
            return _hls.levels;
        };

        private function _getAutoLevel() : Boolean {
            return _hls.autolevel;
        };

        private function _getMetrics() : Object {
            return _hls.metrics;
        };

        private function _getDuration() : Number {
            return _duration;
        };

        private function _getPosition() : Number {
            return _hls.position;
        };

        private function _getPlaybackState() : String {
            return _hls.playbackState;
        };

        private function _getSeekState() : String {
            return _hls.seekState;
        };

        private function _getType() : String {
            return _hls.type;
        };

        private function _getbufferLength() : Number {
            return _hls.bufferLength;
        };

        private function _getmaxBufferLength() : Number {
            return HLSSettings.maxBufferLength;
        };

        private function _getminBufferLength() : Number {
            return HLSSettings.minBufferLength;
        };

        private function _getlowBufferLength() : Number {
            return HLSSettings.lowBufferLength;
        };

        private function _getflushLiveURLCache() : Boolean {
            return HLSSettings.flushLiveURLCache;
        };

        private function _getstartFromLevel() : int {
            return HLSSettings.startFromLevel;
        };

        private function _getseekFromLevel() : int {
            return HLSSettings.seekFromLevel;
        };

        private function _getLogDebug() : Boolean {
            return HLSSettings.logDebug;
        };

        private function _getLogDebug2() : Boolean {
            return HLSSettings.logDebug2;
        };

        private function _getCapLeveltoStage() : Boolean {
            return HLSSettings.capLevelToStage;
        };

        private function _getJSURLStream() : Boolean {
            return (_hls.URLstream is JSURLStream);
        };

        private function _getPlayerVersion() : Number {
            return 2;
        };

        private function _getAudioTrackList() : Array {
            var list : Array = [];
            var vec : Vector.<HLSAudioTrack> = _hls.audioTracks;
            for (var i : Object in vec) {
                list.push(vec[i]);
            }
            return list;
        };

        private function _getAudioTrackId() : int {
            return _hls.audioTrack;
        };

        /** Javascript calls. **/
        private function _load(url : String) : void {
            _hls.load(url);
        };

        private function _play() : void {
            _hls.stream.play();
        };

        private function _pause() : void {
            _hls.stream.pause();
        };

        private function _resume() : void {
            _hls.stream.resume();
        };

        private function _seek(position : Number) : void {
            _hls.stream.seek(position);
        };

        private function _stop() : void {
            _hls.stream.close();
        };

        private function _volume(percent : Number) : void {
            _hls.stream.soundTransform = new SoundTransform(percent / 100);
        };

        private function _setLevel(level : int) : void {
            _smoothSetLevel(level);
            if (!isNaN(_media_position) && level != -1) {
                _hls.stream.seek(_media_position);
            }
        };

        private function _smoothSetLevel(level : int) : void {
            if (level != _hls.level) {
                _hls.level = level;
            }
        };

        private function _setmaxBufferLength(new_len : Number) : void {
            HLSSettings.maxBufferLength = new_len;
        };

        private function _setminBufferLength(new_len : Number) : void {
            HLSSettings.minBufferLength = new_len;
        };

        private function _setlowBufferLength(new_len : Number) : void {
            HLSSettings.lowBufferLength = new_len;
        };

        private function _setflushLiveURLCache(flushLiveURLCache : Boolean) : void {
            HLSSettings.flushLiveURLCache = flushLiveURLCache;
        };

        private function _setstartFromLevel(startFromLevel : int) : void {
            HLSSettings.startFromLevel = startFromLevel;
        };

        private function _setseekFromLevel(seekFromLevel : int) : void {
            HLSSettings.seekFromLevel = seekFromLevel;
        };

        private function _setLogDebug(debug : Boolean) : void {
            HLSSettings.logDebug = debug;
        };

        private function _setLogDebug2(debug2 : Boolean) : void {
            HLSSettings.logDebug2 = debug2;
        };

        private function _setCapLeveltoStage(value : Boolean) : void {
            HLSSettings.capLevelToStage = value;
        };

        private function _setJSURLStream(jsURLstream : Boolean) : void {
            if (jsURLstream) {
                _hls.URLstream = JSURLStream as Class;
            } else {
                _hls.URLstream = URLStream as Class;
            }
        };

        private function _setAudioTrack(val : int) : void {
            if (val == _hls.audioTrack) return;
            _hls.audioTrack = val;
            if (!isNaN(_media_position)) {
                _hls.stream.seek(_media_position);
            }
        };

        /** Mouse click handler. **/
        private function _clickHandler(event : MouseEvent) : void {
            if (stage.displayState == StageDisplayState.FULL_SCREEN_INTERACTIVE || stage.displayState == StageDisplayState.FULL_SCREEN) {
                stage.displayState = StageDisplayState.NORMAL;
            } else {
                stage.displayState = StageDisplayState.FULL_SCREEN;
            }
        };

        /** StageVideo detector. **/
        private function _onStageVideoState(event : StageVideoAvailabilityEvent) : void {
            var available : Boolean = (event.availability == StageVideoAvailability.AVAILABLE);
            _hls = new HLS();
            _hls.stage = stage;
            _hls.addEventListener(HLSEvent.PLAYBACK_COMPLETE, _completeHandler);
            _hls.addEventListener(HLSEvent.ERROR, _errorHandler);
            _hls.addEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentHandler);
            _hls.addEventListener(HLSEvent.MANIFEST_LOADED, _manifestHandler);
            _hls.addEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler);
            _hls.addEventListener(HLSEvent.PLAYBACK_STATE, _stateHandler);
            _hls.addEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler);
            _hls.addEventListener(HLSEvent.AUDIO_TRACKS_LIST_CHANGE, _audioTracksListChange);
            _hls.addEventListener(HLSEvent.AUDIO_TRACK_CHANGE, _audioTrackChange);

            if (available && stage.stageVideos.length > 0) {
                _stageVideo = stage.stageVideos[0];
                _stageVideo.viewPort = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
                _stageVideo.attachNetStream(_hls.stream);
            } else {
                _video = new Video(stage.stageWidth, stage.stageHeight);
                addChild(_video);
                _video.smoothing = true;
                _video.attachNetStream(_hls.stream);
            }
            stage.removeEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, _onStageVideoState);

            var autoLoadUrl : String = root.loaderInfo.parameters.url as String;
            if (autoLoadUrl != null) {
                _autoLoad = true;
                _load(autoLoadUrl);
            }
        };

        private function _onStageResize(event : Event) : void {
            stage.fullScreenSourceRect = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
            _sheet.width = stage.stageWidth;
            _sheet.height = stage.stageHeight;
            _resize();
        };

        private function _resize() : void {
            var rect : Rectangle;
            rect = ScaleVideo.resizeRectangle(_videoWidth, _videoHeight, stage.stageWidth, stage.stageHeight);
            // resize video
            if (_video) {
                _video.width = rect.width;
                _video.height = rect.height;
                _video.x = rect.x;
                _video.y = rect.y;
            } else if (_stageVideo) {
                _stageVideo.viewPort = rect;
            }
        }
    }
}

package org.mangui.chromeless {
    import flash.net.URLStream;

    import org.mangui.hls.model.Level;
    import org.mangui.hls.*;
    import org.mangui.hls.utils.*;

    import flash.display.*;
    import flash.events.*;
    import flash.external.ExternalInterface;
    import flash.geom.Rectangle;
    import flash.media.Video;
    import flash.media.SoundTransform;
    import flash.media.StageVideo;
    import flash.media.StageVideoAvailability;
    import flash.utils.setTimeout;

    // import com.sociodox.theminer.*;
    public class ChromelessPlayer extends Sprite {
        /** reference to the framework. **/
        protected var _hls : HLS;
        /** Sheet to place on top of the video. **/
        protected var _sheet : Sprite;
        /** Reference to the stage video element. **/
        protected var _stageVideo : StageVideo = null;
        /** Reference to the video element. **/
        protected var _video : Video = null;
        /** Video size **/
        protected var _videoWidth : int = 0;
        protected var _videoHeight : int = 0;
        /** current media position */
        protected var _media_position : Number;
        protected var _duration : Number;
    /** URL autoload feature */
        protected var _autoLoad : Boolean = false;

        /** Initialization. **/
        public function ChromelessPlayer() {
            // Set stage properties
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            stage.fullScreenSourceRect = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
            stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, _onStageVideoState);
            stage.addEventListener(Event.RESIZE, _onStageResize);
            // Draw sheet for catching clicks
            _sheet = new Sprite();
            _sheet.graphics.beginFill(0x000000, 0);
            _sheet.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
            _sheet.addEventListener(MouseEvent.CLICK, _clickHandler);
            _sheet.buttonMode = true;
            addChild(_sheet);
            // Connect getters to JS.
            ExternalInterface.addCallback("getLevel", _getLevel);
            ExternalInterface.addCallback("getLevels", _getLevels);
            ExternalInterface.addCallback("getAutoLevel", _getAutoLevel);
            ExternalInterface.addCallback("getMetrics", _getMetrics);
            ExternalInterface.addCallback("getDuration", _getDuration);
            ExternalInterface.addCallback("getPosition", _getPosition);
            ExternalInterface.addCallback("getPlaybackState", _getPlaybackState);
            ExternalInterface.addCallback("getSeekState", _getSeekState);
            ExternalInterface.addCallback("getType", _getType);
            ExternalInterface.addCallback("getmaxBufferLength", _getmaxBufferLength);
            ExternalInterface.addCallback("getminBufferLength", _getminBufferLength);
            ExternalInterface.addCallback("getlowBufferLength", _getlowBufferLength);
            ExternalInterface.addCallback("getbufferLength", _getbufferLength);
            ExternalInterface.addCallback("getLogDebug", _getLogDebug);
            ExternalInterface.addCallback("getLogDebug2", _getLogDebug2);
            ExternalInterface.addCallback("getCapLeveltoStage", _getCapLeveltoStage);
            ExternalInterface.addCallback("getflushLiveURLCache", _getflushLiveURLCache);
            ExternalInterface.addCallback("getstartFromLevel", _getstartFromLevel);
            ExternalInterface.addCallback("getseekFromLowestLevel", _getseekFromLevel);
            ExternalInterface.addCallback("getJSURLStream", _getJSURLStream);
            ExternalInterface.addCallback("getPlayerVersion", _getPlayerVersion);
            ExternalInterface.addCallback("getAudioTrackList", _getAudioTrackList);
            ExternalInterface.addCallback("getAudioTrackId", _getAudioTrackId);
            // Connect calls to JS.
            ExternalInterface.addCallback("playerLoad", _load);
            ExternalInterface.addCallback("playerPlay", _play);
            ExternalInterface.addCallback("playerPause", _pause);
            ExternalInterface.addCallback("playerResume", _resume);
            ExternalInterface.addCallback("playerSeek", _seek);
            ExternalInterface.addCallback("playerStop", _stop);
            ExternalInterface.addCallback("playerVolume", _volume);
            ExternalInterface.addCallback("playerSetLevel", _setLevel);
            ExternalInterface.addCallback("playerSmoothSetLevel", _smoothSetLevel);
            ExternalInterface.addCallback("playerSetmaxBufferLength", _setmaxBufferLength);
            ExternalInterface.addCallback("playerSetminBufferLength", _setminBufferLength);
            ExternalInterface.addCallback("playerSetlowBufferLength", _setlowBufferLength);
            ExternalInterface.addCallback("playerSetflushLiveURLCache", _setflushLiveURLCache);
            ExternalInterface.addCallback("playerSetstartFromLevel", _setstartFromLevel);
            ExternalInterface.addCallback("playerSetseekFromLevel", _setseekFromLevel);
            ExternalInterface.addCallback("playerSetLogDebug", _setLogDebug);
            ExternalInterface.addCallback("playerSetLogDebug2", _setLogDebug2);
            ExternalInterface.addCallback("playerCapLeveltoStage", _setCapLeveltoStage);
            ExternalInterface.addCallback("playerSetAudioTrack", _setAudioTrack);
            ExternalInterface.addCallback("playerSetJSURLStream", _setJSURLStream);

            setTimeout(_pingJavascript, 50);
        };

        /** Notify javascript the framework is ready. **/
        protected function _pingJavascript() : void {
            ExternalInterface.call("onHLSReady", ExternalInterface.objectID);
        };

        /** Forward events from the framework. **/
        protected function _completeHandler(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                ExternalInterface.call("onComplete");
            }
        };

        protected function _errorHandler(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                var hlsError : HLSError = event.error;
                ExternalInterface.call("onError", hlsError.code, hlsError.url, hlsError.msg);
            }
        };

        protected function _fragmentHandler(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                ExternalInterface.call("onFragment", event.metrics.bandwidth, event.metrics.level, stage.stageWidth);
            }
        };

        protected function _manifestHandler(event : HLSEvent) : void {
            _duration = event.levels[_hls.startlevel].duration;

            if (_autoLoad) {
                _play();
            }

            if (ExternalInterface.available) {
                ExternalInterface.call("onManifest", _duration);
            }
        };

        protected function _mediaTimeHandler(event : HLSEvent) : void {
            _duration = event.mediatime.duration;
            _media_position = event.mediatime.position;
            if (ExternalInterface.available) {
                ExternalInterface.call("onPosition", event.mediatime.position, event.mediatime.duration, event.mediatime.live_sliding,event.mediatime.buffer, event.mediatime.program_date);
            }

            var videoWidth : int = _video ? _video.videoWidth : _stageVideo.videoWidth;
            var videoHeight : int = _video ? _video.videoHeight : _stageVideo.videoHeight;

            if (videoWidth && videoHeight) {
                var changed : Boolean = _videoWidth != videoWidth || _videoHeight != videoHeight;
                if (changed) {
                    _videoHeight = videoHeight;
                    _videoWidth = videoWidth;
                    _resize();
                    if (ExternalInterface.available) {
                        ExternalInterface.call("onVideoSize", _videoWidth, _videoHeight);
                    }
                }
            }
        };

        protected function _stateHandler(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                ExternalInterface.call("onState", event.state);
            }
        };

        protected function _levelSwitchHandler(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                ExternalInterface.call("onSwitch", event.level);
            }
        };

        protected function _audioTracksListChange(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                ExternalInterface.call("onAudioTracksListChange", _getAudioTrackList());
            }
        }

        protected function _audioTrackChange(event : HLSEvent) : void {
            if (ExternalInterface.available) {
                ExternalInterface.call("onAudioTrackChange", event.audioTrack);
            }
        }

        /** Javascript getters. **/
        protected function _getLevel() : int {
            return _hls.level;
        };

        protected function _getLevels() : Vector.<Level> {
            return _hls.levels;
        };

        protected function _getAutoLevel() : Boolean {
            return _hls.autolevel;
        };

        protected function _getMetrics() : Object {
            return _hls.metrics;
        };

        protected function _getDuration() : Number {
            return _duration;
        };

        protected function _getPosition() : Number {
            return _hls.position;
        };

        protected function _getPlaybackState() : String {
            return _hls.playbackState;
        };

        protected function _getSeekState() : String {
            return _hls.seekState;
        };

        protected function _getType() : String {
            return _hls.type;
        };

        protected function _getbufferLength() : Number {
            return _hls.bufferLength;
        };

        protected function _getmaxBufferLength() : Number {
            return HLSSettings.maxBufferLength;
        };

        protected function _getminBufferLength() : Number {
            return HLSSettings.minBufferLength;
        };

        protected function _getlowBufferLength() : Number {
            return HLSSettings.lowBufferLength;
        };

        protected function _getflushLiveURLCache() : Boolean {
            return HLSSettings.flushLiveURLCache;
        };

        protected function _getstartFromLevel() : int {
            return HLSSettings.startFromLevel;
        };

        protected function _getseekFromLevel() : int {
            return HLSSettings.seekFromLevel;
        };

        protected function _getLogDebug() : Boolean {
            return HLSSettings.logDebug;
        };

        protected function _getLogDebug2() : Boolean {
            return HLSSettings.logDebug2;
        };

        protected function _getCapLeveltoStage() : Boolean {
            return HLSSettings.capLevelToStage;
        };

        protected function _getJSURLStream() : Boolean {
            return (_hls.URLstream is JSURLStream);
        };

        protected function _getPlayerVersion() : Number {
            return 2;
        };

        protected function _getAudioTrackList() : Array {
            var list : Array = [];
            var vec : Vector.<HLSAudioTrack> = _hls.audioTracks;
            for (var i : Object in vec) {
                list.push(vec[i]);
            }
            return list;
        };

        protected function _getAudioTrackId() : int {
            return _hls.audioTrack;
        };

        /** Javascript calls. **/
        protected function _load(url : String) : void {
            _hls.load(url);
        };

        protected function _play() : void {
            _hls.stream.play();
        };

        protected function _pause() : void {
            _hls.stream.pause();
        };

        protected function _resume() : void {
            _hls.stream.resume();
        };

        protected function _seek(position : Number) : void {
            _hls.stream.seek(position);
        };

        protected function _stop() : void {
            _hls.stream.close();
        };

        protected function _volume(percent : Number) : void {
            _hls.stream.soundTransform = new SoundTransform(percent / 100);
        };

        protected function _setLevel(level : int) : void {
            _smoothSetLevel(level);
            if (!isNaN(_media_position) && level != -1) {
                _hls.stream.seek(_media_position);
            }
        };

        protected function _smoothSetLevel(level : int) : void {
            if (level != _hls.level) {
                _hls.level = level;
            }
        };

        protected function _setmaxBufferLength(new_len : Number) : void {
            HLSSettings.maxBufferLength = new_len;
        };

        protected function _setminBufferLength(new_len : Number) : void {
            HLSSettings.minBufferLength = new_len;
        };

        protected function _setlowBufferLength(new_len : Number) : void {
            HLSSettings.lowBufferLength = new_len;
        };

        protected function _setflushLiveURLCache(flushLiveURLCache : Boolean) : void {
            HLSSettings.flushLiveURLCache = flushLiveURLCache;
        };

        protected function _setstartFromLevel(startFromLevel : int) : void {
            HLSSettings.startFromLevel = startFromLevel;
        };

        protected function _setseekFromLevel(seekFromLevel : int) : void {
            HLSSettings.seekFromLevel = seekFromLevel;
        };

        protected function _setLogDebug(debug : Boolean) : void {
            HLSSettings.logDebug = debug;
        };

        protected function _setLogDebug2(debug2 : Boolean) : void {
            HLSSettings.logDebug2 = debug2;
        };

        protected function _setCapLeveltoStage(value : Boolean) : void {
            HLSSettings.capLevelToStage = value;
        };

        protected function _setJSURLStream(jsURLstream : Boolean) : void {
            if (jsURLstream) {
                _hls.URLstream = JSURLStream as Class;
            } else {
                _hls.URLstream = URLStream as Class;
            }
        };

        protected function _setAudioTrack(val : int) : void {
            if (val == _hls.audioTrack) return;
            _hls.audioTrack = val;
            if (!isNaN(_media_position)) {
                _hls.stream.seek(_media_position);
            }
        };

        /** Mouse click handler. **/
        protected function _clickHandler(event : MouseEvent) : void {
            if (stage.displayState == StageDisplayState.FULL_SCREEN_INTERACTIVE || stage.displayState == StageDisplayState.FULL_SCREEN) {
                stage.displayState = StageDisplayState.NORMAL;
            } else {
                stage.displayState = StageDisplayState.FULL_SCREEN;
            }
        };

        /** StageVideo detector. **/
        protected function _onStageVideoState(event : StageVideoAvailabilityEvent) : void {
            var available : Boolean = (event.availability == StageVideoAvailability.AVAILABLE);
            _hls = new HLS();
            _hls.stage = stage;
            _hls.addEventListener(HLSEvent.PLAYBACK_COMPLETE, _completeHandler);
            _hls.addEventListener(HLSEvent.ERROR, _errorHandler);
            _hls.addEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentHandler);
            _hls.addEventListener(HLSEvent.MANIFEST_LOADED, _manifestHandler);
            _hls.addEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler);
            _hls.addEventListener(HLSEvent.PLAYBACK_STATE, _stateHandler);
            _hls.addEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler);
            _hls.addEventListener(HLSEvent.AUDIO_TRACKS_LIST_CHANGE, _audioTracksListChange);
            _hls.addEventListener(HLSEvent.AUDIO_TRACK_CHANGE, _audioTrackChange);

            if (available && stage.stageVideos.length > 0) {
                _stageVideo = stage.stageVideos[0];
                _stageVideo.viewPort = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
                _stageVideo.attachNetStream(_hls.stream);
            } else {
                _video = new Video(stage.stageWidth, stage.stageHeight);
                addChild(_video);
                _video.smoothing = true;
                _video.attachNetStream(_hls.stream);
            }
            stage.removeEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, _onStageVideoState);

            var autoLoadUrl : String = root.loaderInfo.parameters.url as String;
            if (autoLoadUrl != null) {
                _autoLoad = true;
                _load(autoLoadUrl);
            }
        };

        protected function _onStageResize(event : Event) : void {
            stage.fullScreenSourceRect = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
            _sheet.width = stage.stageWidth;
            _sheet.height = stage.stageHeight;
            _resize();
        };

        protected function _resize() : void {
            var rect : Rectangle;
            rect = ScaleVideo.resizeRectangle(_videoWidth, _videoHeight, stage.stageWidth, stage.stageHeight);
            // resize video
            if (_video) {
                _video.width = rect.width;
                _video.height = rect.height;
                _video.x = rect.x;
                _video.y = rect.y;
            } else if (_stageVideo) {
                _stageVideo.viewPort = rect;
            }
        }
    }
}

transform ChromelessPlayer functions to protected


package net.saqoosha.pv3d {

	import org.papervision3d.core.math.Quaternion;
	import org.papervision3d.objects.DisplayObject3D;

	public class Slerper {

		private var _target:DisplayObject3D;
		private var _start:Quaternion;
		private var _end:Quaternion;
		private var _current:Quaternion;
		private var _alpha:Number = 0;

		public function Slerper(target:DisplayObject3D, start:Quaternion = null, end:Quaternion = null) {
			this._target = target;
			this._start = start;
			this._end = end;
			this._current = this._start ? this._start.clone() : new Quaternion();
			this._alpha = 0;
		}

		public function get target():DisplayObject3D {
			return this._target;
		}

		public function set target(value:DisplayObject3D):void {
			this._target = value;
		}

		public function get start():Quaternion {
			return this._start;
		}

		public function set start(value:Quaternion):void {
			this._start = value;
		}

		public function get end():Quaternion {
			return this._end;
		}

		public function set end(value:Quaternion):void {
			this._end = value;
		}

		public function get alpha():Number {
			return this._alpha
		}

		private static var tmp:Quaternion;
		public function set alpha(value:Number):void {
			this._alpha = value;
			if (this._alpha == 0.0) {
				tmp = this._start;
			} else if (this._alpha == 1.0) {
				tmp = this._end;
			} else {
				tmp = this._current;
				slerp(this._start, this._end, this._alpha, this._current);
			}
			this._target.transform.copy3x3(tmp.matrix);
		}

		private static var __angle:Number;
		private static var __scale:Number;
		private static var __invscale:Number;
		private static var __theta:Number;
		private static var __invsintheta:Number;
		public static function slerp( qa:Quaternion, qb:Quaternion, alpha:Number, out:Quaternion = null ):Quaternion
		{
			__angle = qa.w * qb.w + qa.x * qb.x + qa.y * qb.y + qa.z * qb.z

	         if (__angle < 0.0)
	         {
	                 qa.x *= -1.0;
	                 qa.y *= -1.0;
	                 qa.z *= -1.0;
	                 qa.w *= -1.0;
	                 __angle *= -1.0;
	         }

	         if ((__angle + 1.0) > Quaternion.EPSILON) // Take the shortest path
	         {
	                 if ((1.0 - __angle) >= Quaternion.EPSILON)  // spherical interpolation
	                 {
	                         __theta = Math.acos(__angle);
	                         __invsintheta = 1.0 / Math.sin(__theta);
	                         __scale = Math.sin(__theta * (1.0-alpha)) * __invsintheta;
	                         __invscale = Math.sin(__theta * alpha) * __invsintheta;
	                 }
	                 else // linear interploation
	                 {
	                         __scale = 1.0 - alpha;
	                         __invscale = alpha;
	                 }
	         }
	         else // long way to go...
	         {
				 qb.y = -qa.y;
				 qb.x = qa.x;
				 qb.w = -qa.w;
				 qb.z = qa.z;

	             __scale = Math.sin(Math.PI * (0.5 - alpha));
	             __invscale = Math.sin(Math.PI * alpha);
	         }

	 		if (out) {
	 			out.x = __scale * qa.x + __invscale * qb.x;
				out.y = __scale * qa.y + __invscale * qb.y;
				out.z = __scale * qa.z + __invscale * qb.z;
				out.w = __scale * qa.w + __invscale * qb.w;
	 		} else {
				out =  new Quaternion(  __scale * qa.x + __invscale * qb.x,
										__scale * qa.y + __invscale * qb.y,
										__scale * qa.z + __invscale * qb.z,
										__scale * qa.w + __invscale * qb.w );
	 		}
	 		return out;
		}

	}

}

package net.saqoosha.pv3d.util {

	import org.papervision3d.core.math.Quaternion;
	import org.papervision3d.objects.DisplayObject3D;

	public class Slerper {

		private var _target:DisplayObject3D;
		private var _start:Quaternion;
		private var _end:Quaternion;
		private var _current:Quaternion;
		private var _alpha:Number = 0;

		public function Slerper(target:DisplayObject3D, start:Quaternion = null, end:Quaternion = null) {
			this._target = target;
			this._start = start;
			this._end = end;
			this._current = this._start ? this._start.clone() : new Quaternion();
			this._alpha = 0;
		}

		public function get target():DisplayObject3D {
			return this._target;
		}

		public function set target(value:DisplayObject3D):void {
			this._target = value;
		}

		public function get start():Quaternion {
			return this._start;
		}

		public function set start(value:Quaternion):void {
			this._start = value;
		}

		public function get end():Quaternion {
			return this._end;
		}

		public function set end(value:Quaternion):void {
			this._end = value;
		}

		public function get alpha():Number {
			return this._alpha
		}

		private static var tmp:Quaternion;
		public function set alpha(value:Number):void {
			this._alpha = value;
			if (this._alpha == 0.0) {
				tmp = this._start;
			} else if (this._alpha == 1.0) {
				tmp = this._end;
			} else {
				tmp = this._current;
				slerp(this._start, this._end, this._alpha, this._current);
			}
			this._target.transform.copy3x3(tmp.matrix);
		}

		private static var __angle:Number;
		private static var __scale:Number;
		private static var __invscale:Number;
		private static var __theta:Number;
		private static var __invsintheta:Number;
		public static function slerp( qa:Quaternion, qb:Quaternion, alpha:Number, out:Quaternion = null ):Quaternion
		{
			__angle = qa.w * qb.w + qa.x * qb.x + qa.y * qb.y + qa.z * qb.z

	         if (__angle < 0.0)
	         {
	                 qa.x *= -1.0;
	                 qa.y *= -1.0;
	                 qa.z *= -1.0;
	                 qa.w *= -1.0;
	                 __angle *= -1.0;
	         }

	         if ((__angle + 1.0) > Quaternion.EPSILON) // Take the shortest path
	         {
	                 if ((1.0 - __angle) >= Quaternion.EPSILON)  // spherical interpolation
	                 {
	                         __theta = Math.acos(__angle);
	                         __invsintheta = 1.0 / Math.sin(__theta);
	                         __scale = Math.sin(__theta * (1.0-alpha)) * __invsintheta;
	                         __invscale = Math.sin(__theta * alpha) * __invsintheta;
	                 }
	                 else // linear interploation
	                 {
	                         __scale = 1.0 - alpha;
	                         __invscale = alpha;
	                 }
	         }
	         else // long way to go...
	         {
				 qb.y = -qa.y;
				 qb.x = qa.x;
				 qb.w = -qa.w;
				 qb.z = qa.z;

	             __scale = Math.sin(Math.PI * (0.5 - alpha));
	             __invscale = Math.sin(Math.PI * alpha);
	         }

	 		if (out) {
	 			out.x = __scale * qa.x + __invscale * qb.x;
				out.y = __scale * qa.y + __invscale * qb.y;
				out.z = __scale * qa.z + __invscale * qb.z;
				out.w = __scale * qa.w + __invscale * qb.w;
	 		} else {
				out =  new Quaternion(  __scale * qa.x + __invscale * qb.x,
										__scale * qa.y + __invscale * qb.y,
										__scale * qa.z + __invscale * qb.z,
										__scale * qa.w + __invscale * qb.w );
	 		}
	 		return out;
		}

	}

}

fix package.

fix package.


//
// Flump - Copyright 2012 Three Rings Design

package flump.export {

import flash.display.Sprite;
import flash.filesystem.File;

import flump.SwfTexture;

public class Atlas
{
    // The empty border size around the right and bottom edges of each texture, to prevent bleeding
    public static const PADDING :int = 1;

    public var name :String;
    public var targetDevice :DeviceType;

    public function Atlas (name :String, targetDevice :DeviceType, w :int, h :int) {
        this.name = name;
        this.targetDevice = targetDevice;

        _root = new Node(0, 0, w, h);
    }

    // Try to place a texture in this atlas, return true if it fit
    public function place (texture :SwfTexture) :Boolean {
        var node :Node = _root.search(texture.w + PADDING, texture.h + PADDING);
        if (node == null) {
            return false;
        }

        node.texture = texture;
        return true;
    }

    public function get area () :int { return _root.bounds.width * _root.bounds.height; }

    public function get used () :int {
        var used :int = 0;
        _root.forEach(function (n :Node) :void { used += n.bounds.width * n.bounds.height; });
        return used;
    }

    public function publish (dir :File) :void {
        var constructed :Sprite = new Sprite();
        _root.forEach(function (node :Node) :void {
            var tex :SwfTexture = node.texture;
            var sprite :Sprite = new Sprite();
            sprite.scaleX = sprite.scaleY = tex.scale;
            constructed.addChild(tex.holder);
            tex.holder.x = node.bounds.x;
            tex.holder.y = node.bounds.y;
        });
        PngPublisher.publish(dir.resolvePath(name + targetDevice.extension + ".png"),
            _root.bounds.width, _root.bounds.height, constructed);
    }

    public function toJSON (_:*) :Object {
        var json :Object = {
            file: name + ".png",
            textures: []
        };
        _root.forEach(function (node :Node) :void {
            var tex :SwfTexture = node.texture;
            var textureJson :Object = {
                name: tex.symbol,
                offset: [ tex.offset.x, tex.offset.y ],
                rect: [ node.bounds.x, node.bounds.y, tex.w, tex.h ]
            };
            if (tex.md5 != null) {
                textureJson.md5 = tex.md5;
            }
            json.textures.push(textureJson);
        });
        return json;
    }

    public function toXML () :XML
    {
        var json :Object = toJSON(null);

        var xml :XML = <atlas
            file={json.file}
        />;
        for each (var tex :Object in json.textures) {
            var textureXml :XML = <texture
                name={tex.name}
                offset={tex.offset}
                rect={tex.rect}
            />;
            if (tex.md5 != null) {
                textureXml.@md5 = tex.md5;
            }
            xml.appendChild(textureXml);
        }
        return xml;
    }

    protected var _root :Node;
}
}

import flash.geom.Rectangle;

import flump.SwfTexture;

// A node in a k-d tree
class Node
{
    // The bounds of this node (and its children)
    public var bounds :Rectangle;

    // The texture that is placed here, if any. Implies that this is a leaf node
    public var texture :SwfTexture;

    // This node's two children, if any
    public var left :Node;
    public var right :Node;

    public function Node (x :int, y :int, w :int, h :int)
    {
        bounds = new Rectangle(x, y, w, h);
    }

    // Find a free node in this tree big enough to fit an area, or null
    public function search (w :int, h :int) :Node
    {
        if (texture != null) {
            // There's already a texture here, terminate
            return null;
        }

        if (left != null && right != null) {
            // Try to fit it into this node's children
            var descendent :Node = left.search(w, h);
            if (descendent == null) {
                descendent = right.search(w, h);
            }
            return descendent;

        } else {
            if (bounds.width == w && bounds.height == h) {
                // This node is a perfect size, no need to subdivide
                return this;
            }
            if (bounds.width < w || bounds.height < h) {
                // This will never fit, terminate
                return null;
            }

            var dw :Number = bounds.width - w;
            var dh :Number = bounds.height - h;

            if (dw > dh) {
                left = new Node(bounds.x, bounds.y, w, bounds.height);
                right = new Node(bounds.x + w, bounds.y, dw, bounds.height);

            } else {
                left = new Node(bounds.x, bounds.y, bounds.width, h);
                right = new Node(bounds.x, bounds.y + h, bounds.width, dh);
            }

            return left.search(w, h);
        }
    }

    // Iterate over all nodes with textures in this tree
    public function forEach (fn :Function /* Node -> void */) :void {
        if (texture != null) {
            fn(this);
        }

        if (left != null && right != null) {
            left.forEach(fn);
            right.forEach(fn);
        }
    }
}

//
// Flump - Copyright 2012 Three Rings Design

package flump.export {

import flash.display.Sprite;
import flash.filesystem.File;

import flump.SwfTexture;

public class Atlas
{
    // The empty border size around the right and bottom edges of each texture, to prevent bleeding
    public static const PADDING :int = 1;

    public var name :String;
    public var targetDevice :DeviceType;

    public function Atlas (name :String, targetDevice :DeviceType, w :int, h :int) {
        this.name = name;
        this.targetDevice = targetDevice;

        _root = new Node(0, 0, w, h);
    }

    // Try to place a texture in this atlas, return true if it fit
    public function place (texture :SwfTexture) :Boolean {
        var node :Node = _root.search(texture.w + PADDING, texture.h + PADDING);
        if (node == null) {
            return false;
        }

        node.texture = texture;
        return true;
    }

    public function get area () :int { return _root.bounds.width * _root.bounds.height; }

    public function get used () :int {
        var used :int = 0;
        _root.forEach(function (n :Node) :void { used += n.bounds.width * n.bounds.height; });
        return used;
    }

    public function publish (dir :File) :void {
        var constructed :Sprite = new Sprite();
        _root.forEach(function (node :Node) :void {
            var tex :SwfTexture = node.texture;
            var sprite :Sprite = new Sprite();
            sprite.scaleX = sprite.scaleY = tex.scale;
            constructed.addChild(tex.holder);
            tex.holder.x = node.bounds.x;
            tex.holder.y = node.bounds.y;
        });
        PngPublisher.publish(dir.resolvePath(name + targetDevice.extension + ".png"),
            _root.bounds.width, _root.bounds.height, constructed);
    }

    public function toJSON (_:*) :Object {
        var json :Object = {
            file: name + ".png",
            textures: []
        };
        _root.forEach(function (node :Node) :void {
            var tex :SwfTexture = node.texture;
            var textureJson :Object = {
                name: tex.symbol,
                rect: [ node.bounds.x, node.bounds.y, tex.w, tex.h ]
            };
            if (tex.offset.x != 0 || tex.offset.y != 0) {
                textureJson.offset = [ tex.offset.x, tex.offset.y ];
            }
            if (tex.md5 != null) {
                textureJson.md5 = tex.md5;
            }
            json.textures.push(textureJson);
        });
        return json;
    }

    public function toXML () :XML
    {
        var json :Object = toJSON(null);

        var xml :XML = <atlas
            file={json.file}
        />;
        for each (var tex :Object in json.textures) {
            var textureXml :XML = <texture
                name={tex.name}
                rect={tex.rect}
            />;
            if (tex.offset != null) {
                textureXml.@offset = tex.offset;
            }
            if (tex.md5 != null) {
                textureXml.@md5 = tex.md5;
            }
            xml.appendChild(textureXml);
        }
        return xml;
    }

    protected var _root :Node;
}
}

import flash.geom.Rectangle;

import flump.SwfTexture;

// A node in a k-d tree
class Node
{
    // The bounds of this node (and its children)
    public var bounds :Rectangle;

    // The texture that is placed here, if any. Implies that this is a leaf node
    public var texture :SwfTexture;

    // This node's two children, if any
    public var left :Node;
    public var right :Node;

    public function Node (x :int, y :int, w :int, h :int)
    {
        bounds = new Rectangle(x, y, w, h);
    }

    // Find a free node in this tree big enough to fit an area, or null
    public function search (w :int, h :int) :Node
    {
        if (texture != null) {
            // There's already a texture here, terminate
            return null;
        }

        if (left != null && right != null) {
            // Try to fit it into this node's children
            var descendent :Node = left.search(w, h);
            if (descendent == null) {
                descendent = right.search(w, h);
            }
            return descendent;

        } else {
            if (bounds.width == w && bounds.height == h) {
                // This node is a perfect size, no need to subdivide
                return this;
            }
            if (bounds.width < w || bounds.height < h) {
                // This will never fit, terminate
                return null;
            }

            var dw :Number = bounds.width - w;
            var dh :Number = bounds.height - h;

            if (dw > dh) {
                left = new Node(bounds.x, bounds.y, w, bounds.height);
                right = new Node(bounds.x + w, bounds.y, dw, bounds.height);

            } else {
                left = new Node(bounds.x, bounds.y, bounds.width, h);
                right = new Node(bounds.x, bounds.y + h, bounds.width, dh);
            }

            return left.search(w, h);
        }
    }

    // Iterate over all nodes with textures in this tree
    public function forEach (fn :Function /* Node -> void */) :void {
        if (texture != null) {
            fn(this);
        }

        if (left != null && right != null) {
            left.forEach(fn);
            right.forEach(fn);
        }
    }
}

Make the texture offset optional.

Make the texture offset optional.

@tconkling: This will need to be accounted for in Betwixt.


// vim: tabstop=4 shiftwidth=4

// Copyright (c) 2010 , NetEase.com,Inc. All rights reserved.
//
// Author: Yang Bo (pop.atry@gmail.com)
//
// Use, modification and distribution are subject to the "New BSD License"
// as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.

package com.netease.protobuf {
	import flash.utils.ByteArray
	public function stringToByteArray(s:String):ByteArray {
		const ba:ByteArray = new ByteArray
		for (var i:uint = 0; i < s.length; ++i) {
			ba.writeByte(s.charCodeAt(i))
		}
		return ba
	}
}

// vim: tabstop=4 shiftwidth=4

// Copyright (c) 2010 , NetEase.com,Inc. All rights reserved.
//
// Author: Yang Bo (pop.atry@gmail.com)
//
// Use, modification and distribution are subject to the "New BSD License"
// as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.

package com.netease.protobuf {
	import flash.utils.ByteArray
	public function stringToByteArray(s:String):ByteArray {
		const ba:ByteArray = new ByteArray
		ba.length = s.length
		for (var i:uint = 0; i < s.length; ++i) {
			ba[i] = s.charCodeAt(i)
		}
		return ba
	}
}

初始化ByteArray时position为0


package goplayer
{
  public class SkinnedPlayerView extends Component
    implements PlayerVideoUpdateListener, SkinBackend
  {
    private const missingSkinParts : Array = []

    private var skin : Skin
    private var video : PlayerVideo
    private var player : Player

    public function SkinnedPlayerView
      (skin : Skin, video : PlayerVideo, player : Player)
    {
      this.skin = skin
      this.video = video
      this.player = player

      skin.backend = this

      addChild(video)
      addChild(skin.frontend)

      video.addUpdateListener(this)
    }

    public function handlePlayerVideoUpdated() : void
    {
      video.visible = !player.finished
      skin.update()
    }

    // -----------------------------------------------------

    public function handleUserPlay() : void
    {
      if (player.started)
        player.paused = false
      else
        player.start()
    }

    public function handleUserPause() : void
    { player.paused = true }

    public function handleUserSeek(ratio : Number) : void
    { player.playheadRatio = ratio }

    public function handleUserMute() : void
    { player.mute() }

    public function handleUserUnmute() : void
    { player.unmute() }

    public function handleUserToggleFullscreen() : void
    { video.toggleFullscreen() }

    // -----------------------------------------------------

    public function get skinWidth() : Number
    { return video.dimensions.width }

    public function get skinHeight() : Number
    { return video.dimensions.height }

    public function get skinScale() : Number
    { return video.fullscreenEnabled ? 2 : 1 }

    public function get streamLengthSeconds() : Number
    { return player.streamLength.seconds }

    public function get playheadRatio() : Number
    { return player.playheadRatio }

    public function get bufferRatio() : Number
    { return player.bufferRatio }

    public function get bufferFillRatio() : Number
    { return player.bufferFillRatio }

    public function get playing() : Boolean
    { return player.playing }

    public function get buffering() : Boolean
    { return player.buffering }

    public function get volume() : Number
    { return player.volume }

    // -----------------------------------------------------

    public function handleSkinPartMissing(name : String) : void
    {
      if (missingSkinParts.indexOf(name) == -1)
        $handleSkinPartMissing(name)
    }

    private function $handleSkinPartMissing(name : String) : void
    {
      debug("Error: Skin part missing: " + name)
      missingSkinParts.push(name)
    }
  }
}

package goplayer
{
  import flash.display.Sprite
  import flash.events.Event
  import flash.events.MouseEvent
  import flash.utils.getTimer

  public class SkinnedPlayerView extends Component
    implements PlayerVideoUpdateListener, SkinBackend
  {
    private const IDLE_TIME_MS : uint = 2000

    private const missingSkinParts : Array = []
    private const skinContainer : Sprite = new Sprite

    private var skin : Skin
    private var video : PlayerVideo
    private var player : Player

    private var lastInteractionTime : uint = 0

    public function SkinnedPlayerView
      (skin : Skin, video : PlayerVideo, player : Player)
    {
      this.skin = skin
      this.video = video
      this.player = player

      skin.backend = this

      addChild(video)
      skinContainer.addChild(skin.frontend)
      addChild(skinContainer)

      video.addUpdateListener(this)

      addEventListener(Event.ADDED_TO_STAGE, handleAddedToStage)
    }

    private function handleAddedToStage(event : Event) : void
    {
      stage.addEventListener(MouseEvent.MOUSE_MOVE, handleStageMouseMove)
      stage.addEventListener(Event.MOUSE_LEAVE, handleStageMouseLeave)
    }

    private function handleStageMouseMove(event : MouseEvent) : void
    { lastInteractionTime = getTimer() }

    private function handleStageMouseLeave(event : Event) : void
    { lastInteractionTime = 0 }

    public function handlePlayerVideoUpdated() : void
    {
      video.visible = !player.finished
      skinContainer.visible = !userIdle
      skin.update()
    }

    private function get userIdle() : Boolean
    { return getTimer() - lastInteractionTime > IDLE_TIME_MS }

    // -----------------------------------------------------

    public function handleUserPlay() : void
    {
      if (player.started)
        player.paused = false
      else
        player.start()
    }

    public function handleUserPause() : void
    { player.paused = true }

    public function handleUserSeek(ratio : Number) : void
    { player.playheadRatio = ratio }

    public function handleUserMute() : void
    { player.mute() }

    public function handleUserUnmute() : void
    { player.unmute() }

    public function handleUserToggleFullscreen() : void
    { video.toggleFullscreen() }

    // -----------------------------------------------------

    public function get skinWidth() : Number
    { return video.dimensions.width }

    public function get skinHeight() : Number
    { return video.dimensions.height }

    public function get skinScale() : Number
    { return video.fullscreenEnabled ? 2 : 1 }

    public function get streamLengthSeconds() : Number
    { return player.streamLength.seconds }

    public function get playheadRatio() : Number
    { return player.playheadRatio }

    public function get bufferRatio() : Number
    { return player.bufferRatio }

    public function get bufferFillRatio() : Number
    { return player.bufferFillRatio }

    public function get playing() : Boolean
    { return player.playing }

    public function get buffering() : Boolean
    { return player.buffering }

    public function get volume() : Number
    { return player.volume }

    // -----------------------------------------------------

    public function handleSkinPartMissing(name : String) : void
    {
      if (missingSkinParts.indexOf(name) == -1)
        $handleSkinPartMissing(name)
    }

    private function $handleSkinPartMissing(name : String) : void
    {
      debug("Error: Skin part missing: " + name)
      missingSkinParts.push(name)
    }
  }
}

Hide skin when user is idle.

Hide skin when user is idle.


//
// $Id$
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.threerings.util {

/**
 * Equivalent to java.lang.Integer.
 */
// Unfortunately, I think this is necessary.
// I was going to remove this class and just make the streaming stuff
// autotranslate between int <--> java.lang.Integer and
// Number <--> java.lang.Double. However, a Number object that refers
// to an integer value is actually an int. Yes, it's totally fucked.
public class Integer
    implements Equalable, Wrapped
{
    public var value :int;

    public static function valueOf (val :int) :Integer
    {
        return new Integer(val);
    }

    public function Integer (value :int)
    {
        this.value = value;
    }

    // from Equalable
    public function equals (other :Object) :Boolean
    {
        return (other is Integer) && (value === (other as Integer).value);
    }

    // from Wrapped
    public function unwrap () :Object
    {
        return value;
    }

    /**
     * Compares to int values in an overflow safe manner.
     */
    public static function compare (val1 :int, val2 :int) :int
    {
        return (val1 > val2) ? 1 : (val1 == val2 ? 0 : -1);
    }
}
}

//
// $Id$
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.threerings.util {

/**
 * Equivalent to java.lang.Integer.
 */
// Unfortunately, I think this is necessary.
// I was going to remove this class and just make the streaming stuff
// autotranslate between int <--> java.lang.Integer and
// Number <--> java.lang.Double. However, a Number object that refers
// to an integer value is actually an int. Yes, it's totally fucked.
public class Integer
    implements Equalable, Wrapped
{
    public var value :int;

    public static function valueOf (val :int) :Integer
    {
        return new Integer(val);
    }

    public function Integer (value :int)
    {
        this.value = value;
    }

    // from Equalable
    public function equals (other :Object) :Boolean
    {
        return (other is Integer) && (value === (other as Integer).value);
    }

    // from Wrapped
    public function unwrap () :Object
    {
        return value;
    }

    // cannot use the override keyword on toString() because actionscript is stupid
    public function toString () :String
    {
        return value.toString();
    }

    /**
     * Compares to int values in an overflow safe manner.
     */
    public static function compare (val1 :int, val2 :int) :int
    {
        return (val1 > val2) ? 1 : (val1 == val2 ? 0 : -1);
    }
}
}

implement toString

implement toString

git-svn-id: a1a4b28b82a3276cc491891159dd9963a0a72fae@4678 542714f4-19e9-0310-aa3c-eee0fc999fb1


package aerys.minko.type.loader
{
	import aerys.minko.render.resource.texture.TextureResource;
	import aerys.minko.scene.node.AbstractSceneNode;
	import aerys.minko.scene.node.Group;
	import aerys.minko.scene.node.ISceneNode;
	import aerys.minko.type.Signal;
	import aerys.minko.type.loader.parser.IParser;
	import aerys.minko.type.loader.parser.ParserOptions;

	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import flash.utils.getQualifiedClassName;

	public class SceneLoader implements ILoader
	{
		private static const REGISTERED_PARSERS : Vector.<Class> = new <Class>[];

		private static const STATE_IDLE		: uint = 0;
		private static const STATE_LOADING	: uint = 1;
		private static const STATE_PARSING	: uint = 2;
		private static const STATE_COMPLETE	: uint = 3;

		private var _currentState			: int;

		private var _progress				: Signal;
		private var _complete				: Signal;
		private var _error					: Signal;

		private var _data					: ISceneNode;
		private var _parser					: IParser;
		private var _numDependencies		: uint;
		private var _dependencies			: Vector.<ILoader>;
		private var _parserOptions			: ParserOptions;

		private var _currentProgress		: Number;
		private var _currentProgressChanged : Boolean;
		private var _isComplete				: Boolean;

		public function get error() : Signal
		{
			return _error;
		}

		public function get progress() : Signal
		{
			return _progress;
		}

		public function get complete() : Signal
		{
			return _complete;
		}

		public function get isComplete() : Boolean
		{
			return _isComplete;
		}

		public function get data() : ISceneNode
		{
			return _data;
		}

		public static function registerParser(parserClass : Class) : void
		{
			if (REGISTERED_PARSERS.indexOf(parserClass) != -1)
				return;

			if (!(new parserClass(new ParserOptions()) is IParser))
				throw new Error('Parsers must implement the IParser interface.');

			REGISTERED_PARSERS.push(parserClass);
		}

		public function SceneLoader(parserOptions : ParserOptions)
		{
			_currentState	= STATE_IDLE;

			_progress		= new Signal('SceneLoader.progress');
			_complete		= new Signal('SceneLoader.complete');
			_data			= null;
			_isComplete		= false;

			_parserOptions	= parserOptions || new ParserOptions();
		}

		public function load(urlRequest : URLRequest) : void
		{
			if (_currentState != STATE_IDLE)
				throw new Error('This controller is already loading an asset.');

			_currentState = STATE_LOADING;

			var urlLoader : URLLoader = new URLLoader();
			urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
			urlLoader.addEventListener(ProgressEvent.PROGRESS, loadProgressHandler);
			urlLoader.addEventListener(Event.COMPLETE, loadCompleteHandler);
			urlLoader.load(urlRequest);
		}

		private function loadProgressHandler(e : ProgressEvent) : void
		{
			_progress.execute(this, 0.5 * e.bytesLoaded / e.bytesTotal);
		}

		private function loadCompleteHandler(e : Event) : void
		{
			_currentState = STATE_IDLE;

			loadBytes(URLLoader(e.currentTarget).data);
		}

		public function loadClass(classObject : Class) : void
		{
			loadBytes(new classObject());
		}

		public function loadBytes(byteArray : ByteArray) : void
		{
			var startPosition : uint = byteArray.position;

			if (_currentState != STATE_IDLE)
				throw new Error('This controller is already loading an asset.');

			_currentState = STATE_PARSING;
			_progress.execute(this, 0.5);

			if (_parserOptions != null && _parserOptions.parser != null)
			{
				_parser = new (_parserOptions.parser)(_parserOptions);
			}
			else
			{
				// search a parser by testing registered parsers.
				var numRegisteredParser : uint = REGISTERED_PARSERS.length;
				for (var parserId : uint = 0; parserId < numRegisteredParser; ++parserId)
				{
					_parser = new REGISTERED_PARSERS[parserId](_parserOptions);
					byteArray.position = startPosition;
					if (_parser.isParsable(byteArray))
						break;
				}

				if (parserId == numRegisteredParser)
					throw new Error('No parser could be found for this datatype');
			}

			byteArray.position = startPosition;

			_dependencies	 = _parser.getDependencies(byteArray);
			_numDependencies = 0;

			if (_dependencies != null)
				for each (var dependency : ILoader in _dependencies)
					if (!dependency.isComplete)
					{
						dependency.error.add(decrementDependencyCounter);
						dependency.complete.add(decrementDependencyCounter);

						_numDependencies++;
					}

			if (_numDependencies == 0)
				parse();
		}

		private function decrementDependencyCounter(...args) : void
		{
			--_numDependencies;

			if (_numDependencies == 0)
				parse();
		}

		private function parse() : void
		{
			_parser.error.add(onParseError);
			_parser.progress.add(onParseProgress);
			_parser.complete.add(onParseComplete);
			_parser.parse();
		}

		private function onParseError(parser : IParser) : void
		{
			_isComplete = true;
		}

		private function onParseProgress(parser : IParser, progress : Number) : void
		{
			_progress.execute(this, 0.5 * (1 + progress));
		}

		private function onParseComplete(parser : IParser, loadedData : ISceneNode) : void
		{
			_isComplete = true;
			_data = loadedData;
			_complete.execute(this, loadedData);
		}
	}
}

package aerys.minko.type.loader
{
	import aerys.minko.render.resource.texture.TextureResource;
	import aerys.minko.scene.node.AbstractSceneNode;
	import aerys.minko.scene.node.Group;
	import aerys.minko.scene.node.ISceneNode;
	import aerys.minko.type.Signal;
	import aerys.minko.type.loader.parser.IParser;
	import aerys.minko.type.loader.parser.ParserOptions;

	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import flash.utils.getQualifiedClassName;

	public class SceneLoader implements ILoader
	{
		private static const REGISTERED_PARSERS : Vector.<Class> = new <Class>[];

		private static const STATE_IDLE		: uint = 0;
		private static const STATE_LOADING	: uint = 1;
		private static const STATE_PARSING	: uint = 2;
		private static const STATE_COMPLETE	: uint = 3;

		private var _currentState			: int;

		private var _progress				: Signal;
		private var _complete				: Signal;
		private var _error					: Signal;

		private var _data					: ISceneNode;
		private var _parser					: IParser;
		private var _numDependencies		: uint;
		private var _dependencies			: Vector.<ILoader>;
		private var _parserOptions			: ParserOptions;

		private var _currentProgress		: Number;
		private var _currentProgressChanged : Boolean;
		private var _isComplete				: Boolean;

		public function get error() : Signal
		{
			return _error;
		}

		public function get progress() : Signal
		{
			return _progress;
		}

		public function get complete() : Signal
		{
			return _complete;
		}

		public function get isComplete() : Boolean
		{
			return _isComplete;
		}

		public function get data() : ISceneNode
		{
			return _data;
		}

		public static function registerParser(parserClass : Class) : void
		{
			if (REGISTERED_PARSERS.indexOf(parserClass) != -1)
				return;

			if (!(new parserClass(new ParserOptions()) is IParser))
				throw new Error('Parsers must implement the IParser interface.');

			REGISTERED_PARSERS.push(parserClass);
		}

		public function SceneLoader(parserOptions : ParserOptions)
		{
			_currentState	= STATE_IDLE;

			_progress		= new Signal('SceneLoader.progress');
			_complete		= new Signal('SceneLoader.complete');
			_data			= null;
			_isComplete		= false;

			_parserOptions	= parserOptions || new ParserOptions();
		}

		public function load(urlRequest : URLRequest) : void
		{
			if (_currentState != STATE_IDLE)
				throw new Error('This controller is already loading an asset.');

			_currentState = STATE_LOADING;

			var urlLoader : URLLoader = new URLLoader();
			urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
			urlLoader.addEventListener(ProgressEvent.PROGRESS, loadProgressHandler);
			urlLoader.addEventListener(Event.COMPLETE, loadCompleteHandler);
			urlLoader.load(urlRequest);
		}

		private function loadProgressHandler(e : ProgressEvent) : void
		{
			_progress.execute(this, 0.5 * e.bytesLoaded / e.bytesTotal);
		}

		private function loadCompleteHandler(e : Event) : void
		{
			_currentState = STATE_IDLE;

			loadBytes(URLLoader(e.currentTarget).data);
		}

		public function loadClass(classObject : Class) : void
		{
			loadBytes(new classObject());
		}

		public function loadBytes(byteArray : ByteArray) : void
		{
			var startPosition : uint = byteArray.position;

			if (_currentState != STATE_IDLE)
				throw new Error('This loader is already loading an asset.');

			_currentState = STATE_PARSING;
			_progress.execute(this, 0.5);

			if (_parserOptions != null && _parserOptions.parser != null)
			{
				_parser = new (_parserOptions.parser)(_parserOptions);
			}
			else
			{
				// search a parser by testing registered parsers.
				var numRegisteredParser : uint = REGISTERED_PARSERS.length;
				for (var parserId : uint = 0; parserId < numRegisteredParser; ++parserId)
				{
					_parser = new REGISTERED_PARSERS[parserId](_parserOptions);
					byteArray.position = startPosition;
					if (_parser.isParsable(byteArray))
						break;
				}

				if (parserId == numRegisteredParser)
					throw new Error('No parser could be found for this datatype');
			}

			byteArray.position = startPosition;

			_dependencies	 = _parser.getDependencies(byteArray);
			_numDependencies = 0;

			if (_dependencies != null)
				for each (var dependency : ILoader in _dependencies)
					if (!dependency.isComplete)
					{
						dependency.error.add(decrementDependencyCounter);
						dependency.complete.add(decrementDependencyCounter);

						_numDependencies++;
					}

			if (_numDependencies == 0)
				parse();
		}

		private function decrementDependencyCounter(...args) : void
		{
			--_numDependencies;

			if (_numDependencies == 0)
				parse();
		}

		private function parse() : void
		{
			_parser.error.add(onParseError);
			_parser.progress.add(onParseProgress);
			_parser.complete.add(onParseComplete);
			_parser.parse();
		}

		private function onParseError(parser : IParser) : void
		{
			_isComplete = true;
		}

		private function onParseProgress(parser : IParser, progress : Number) : void
		{
			_progress.execute(this, 0.5 * (1 + progress));
		}

		private function onParseComplete(parser : IParser, loadedData : ISceneNode) : void
		{
			_isComplete = true;
			_data = loadedData;
			_complete.execute(this, loadedData);
		}
	}
}

Fix error message

Fix error message


package goplayer
{
  import flash.display.DisplayObject
  import flash.display.InteractiveObject
  import flash.display.Sprite
  import flash.text.TextField

	public class StandardSkin extends AbstractStandardSkin
  {
    private var _seekBarWidth : Number

    override public function update() : void
    {
      super.update()

      setPosition(largePlayButton, dimensions.center)
      setPosition(bufferingIndicator, dimensions.center)

      setDimensions(largePlayButton, dimensions.halved.innerSquare)

      upperPanel.x = 0
      upperPanel.y = 0

      packLeft
        (upperPanelLeft,
         [upperPanelMiddle, setUpperPanelWidth],
         upperPanelRight)

      controlBar.x = 0
      controlBar.y = dimensions.height

      packLeft
        (showPlayPauseButton ? playPausePart : null,
         beforeLeftTimePart,
         showElapsedTime ? leftTimePart : null,
         [seekBar, setSeekBarWidth],
         showTotalTime ? rightTimePart : null,
         afterRightTimePart,
         showVolumeControl ? volumePart : null,
         showFullscreenButton ? fullscreenPart : null)

      playPausePart.visible = showPlayPauseButton
      leftTimePart.visible = showElapsedTime
      seekBar.visible = showSeekBar
      rightTimePart.visible = showTotalTime
      volumePart.visible = showVolumeControl
      fullscreenPart.visible = showFullscreenButton
    }

    private function packLeft(... items : Array) : void
    { Packer.$packLeft(dimensions.width, items) }

    private function setUpperPanelWidth(value : Number) : void
    {
      upperPanelMiddleBackground.width = value
      titleField.width = value
    }

    private function setSeekBarWidth(value : Number) : void
    { _seekBarWidth = value }

    override protected function get seekBarWidth() : Number
    { return _seekBarWidth }

    override protected function get upperPanel() : Sprite
    { return lookup("chrome.upperPanel") }
    private function get upperPanelLeft() : Sprite
    { return lookup("chrome.upperPanel.left") }
    private function get upperPanelMiddle() : Sprite
    { return lookup("chrome.upperPanel.middle") }
    private function get upperPanelMiddleBackground() : Sprite
    { return lookup("chrome.upperPanel.middle.background") }
    private function get upperPanelRight() : Sprite
    { return lookup("chrome.upperPanel.right") }

    override protected function get largePlayButton() : InteractiveObject
    { return lookup("largePlayButton") }
    override protected function get bufferingIndicator() : InteractiveObject
    { return lookup("bufferingIndicator") }

    override protected function get chrome() : Sprite
    { return lookup("chrome") }

    override protected function get titleField() : TextField
    { return lookup("chrome.upperPanel.middle.titleField") }

    override protected function get controlBar() : Sprite
    { return lookup("chrome.controlBar") }

    private function get playPausePart() : DisplayObject
    { return lookup("chrome.controlBar.playPause") }
    override protected function get playButton() : DisplayObject
    { return lookup("chrome.controlBar.playPause.playButton") }
    override protected function get pauseButton() : DisplayObject
    { return lookup("chrome.controlBar.playPause.pauseButton") }

    private function get beforeLeftTimePart() : DisplayObject
    { return lookup("chrome.controlBar.beforeLeftTime") }

    private function get leftTimePart() : TextField
    { return lookup("chrome.controlBar.leftTime") }
    override protected function get leftTimeField() : TextField
    { return lookup("chrome.controlBar.leftTime.field") }

    override protected function get seekBar() : Sprite
    { return lookup("chrome.controlBar.seekBar") }
    override protected function get seekBarBackground() : DisplayObject
    { return lookup("chrome.controlBar.seekBar.background") }
    override protected function get seekBarBuffer() : DisplayObject
    { return lookup("chrome.controlBar.seekBar.buffer") }
    override protected function get seekBarPlayhead() : DisplayObject
    { return lookup("chrome.controlBar.seekBar.playhead") }
    override protected function get seekBarTooltip() : DisplayObject
    { return lookup("chrome.controlBar.seekBar.tooltip") }
    override protected function get seekBarTooltipField() : TextField
    { return lookup("chrome.controlBar.seekBar.tooltip.field") }

    private function get rightTimePart() : DisplayObject
    { return lookup("chrome.controlBar.rightTime") }
    override protected function get rightTimeField() : TextField
    { return lookup("chrome.controlBar.rightTime.field") }

    private function get afterRightTimePart() : DisplayObject
    { return lookup("chrome.controlBar.afterRightTime") }

    private function get volumePart() : DisplayObject
    { return lookup("chrome.controlBar.volume") }
    override protected function get muteButton() : DisplayObject
    { return lookup("chrome.controlBar.volume.muteButton") }
    override protected function get unmuteButton() : DisplayObject
    { return lookup("chrome.controlBar.volume.unmuteButton") }
    override protected function get volumeSlider() : Sprite
    { return lookup("chrome.controlBar.volume.slider") }
    override protected function get volumeSliderThumb() : DisplayObject
    { return lookup("chrome.controlBar.volume.slider.thumb") }
    override protected function get volumeSliderThumbGuide() : DisplayObject
    { return lookup("chrome.controlBar.volume.slider.thumbGuide") }
    override protected function get volumeSliderFill() : DisplayObject
    { return lookup("chrome.controlBar.volume.slider.fill") }

    private function get fullscreenPart() : DisplayObject
    { return lookup("chrome.controlBar.fullscreen") }
    override protected function get enableFullscreenButton() : DisplayObject
    { return lookup("chrome.controlBar.fullscreen.enableButton") }

    override protected function lookup(name : String) : *
    { return super.lookup("skinContent." + name) }
	}
}

package goplayer
{
  import flash.display.DisplayObject
  import flash.display.InteractiveObject
  import flash.display.Sprite
  import flash.text.TextField

	public class StandardSkin extends AbstractStandardSkin
  {
    private var _seekBarWidth : Number

    override public function update() : void
    {
      super.update()

      setPosition(largePlayButton, dimensions.center)
      setPosition(bufferingIndicator, dimensions.center)

      setDimensions(largePlayButton, dimensions.halved.innerSquare)

      upperPanel.x = 0
      upperPanel.y = 0

      packLeft
        (upperPanelLeft,
         [upperPanelMiddle, setUpperPanelWidth],
         upperPanelRight)

      controlBar.x = 0
      controlBar.y = dimensions.height

      packLeft
        (showPlayPauseButton ? playPausePart : null,
         beforeLeftTimePart,
         showElapsedTime ? leftTimeBackgroundPart : null,
         afterLeftTimePart,
         [seekBar, setSeekBarWidth],
         beforeRightTimePart,
         showTotalTime ? rightTimeBackgroundPart : null,
         afterRightTimePart,
         showVolumeControl ? volumePart : null,
         showFullscreenButton ? fullscreenPart : null)

      leftTimeFieldPart.x = beforeLeftTimePart.x
      rightTimeFieldPart.x = beforeRightTimePart.x

      playPausePart.visible = showPlayPauseButton
      leftTimeBackgroundPart.visible = showElapsedTime
      leftTimeFieldPart.visible = showElapsedTime
      seekBar.visible = showSeekBar
      rightTimeBackgroundPart.visible = showTotalTime
      rightTimeFieldPart.visible = showTotalTime
      volumePart.visible = showVolumeControl
      fullscreenPart.visible = showFullscreenButton
    }

    private function packLeft(... items : Array) : void
    { Packer.$packLeft(dimensions.width, items) }

    private function setUpperPanelWidth(value : Number) : void
    {
      upperPanelMiddleBackground.width = value
      titleField.width = value
    }

    private function setSeekBarWidth(value : Number) : void
    { _seekBarWidth = value }

    override protected function get seekBarWidth() : Number
    { return _seekBarWidth }

    override protected function get upperPanel() : Sprite
    { return lookup("chrome.upperPanel") }
    private function get upperPanelLeft() : Sprite
    { return lookup("chrome.upperPanel.left") }
    private function get upperPanelMiddle() : Sprite
    { return lookup("chrome.upperPanel.middle") }
    private function get upperPanelMiddleBackground() : Sprite
    { return lookup("chrome.upperPanel.middle.background") }
    private function get upperPanelRight() : Sprite
    { return lookup("chrome.upperPanel.right") }

    override protected function get largePlayButton() : InteractiveObject
    { return lookup("largePlayButton") }
    override protected function get bufferingIndicator() : InteractiveObject
    { return lookup("bufferingIndicator") }

    override protected function get chrome() : Sprite
    { return lookup("chrome") }

    override protected function get titleField() : TextField
    { return lookup("chrome.upperPanel.middle.titleField") }

    override protected function get controlBar() : Sprite
    { return lookup("chrome.controlBar") }

    private function get playPausePart() : DisplayObject
    { return lookup("chrome.controlBar.playPause") }
    override protected function get playButton() : DisplayObject
    { return lookup("chrome.controlBar.playPause.playButton") }
    override protected function get pauseButton() : DisplayObject
    { return lookup("chrome.controlBar.playPause.pauseButton") }

    private function get beforeLeftTimePart() : DisplayObject
    { return lookup("chrome.controlBar.beforeLeftTime") }

    private function get leftTimeBackgroundPart() : DisplayObject
    { return lookup("chrome.controlBar.leftTimeBackground") }
    private function get leftTimeFieldPart() : DisplayObject
    { return lookup("chrome.controlBar.leftTime") }
    override protected function get leftTimeField() : TextField
    { return lookup("chrome.controlBar.leftTime.field") }

    private function get afterLeftTimePart() : DisplayObject
    { return lookup("chrome.controlBar.afterLeftTime") }

    override protected function get seekBar() : Sprite
    { return lookup("chrome.controlBar.seekBar") }
    override protected function get seekBarBackground() : DisplayObject
    { return lookup("chrome.controlBar.seekBar.background") }
    override protected function get seekBarBuffer() : DisplayObject
    { return lookup("chrome.controlBar.seekBar.buffer") }
    override protected function get seekBarPlayhead() : DisplayObject
    { return lookup("chrome.controlBar.seekBar.playhead") }
    override protected function get seekBarTooltip() : DisplayObject
    { return lookup("chrome.controlBar.seekBar.tooltip") }
    override protected function get seekBarTooltipField() : TextField
    { return lookup("chrome.controlBar.seekBar.tooltip.field") }

    private function get beforeRightTimePart() : DisplayObject
    { return lookup("chrome.controlBar.beforeRightTime") }

    private function get rightTimeBackgroundPart() : DisplayObject
    { return lookup("chrome.controlBar.rightTimeBackground") }
    private function get rightTimeFieldPart() : DisplayObject
    { return lookup("chrome.controlBar.rightTime") }
    override protected function get rightTimeField() : TextField
    { return lookup("chrome.controlBar.rightTime.field") }

    private function get afterRightTimePart() : DisplayObject
    { return lookup("chrome.controlBar.afterRightTime") }

    private function get volumePart() : DisplayObject
    { return lookup("chrome.controlBar.volume") }
    override protected function get muteButton() : DisplayObject
    { return lookup("chrome.controlBar.volume.muteButton") }
    override protected function get unmuteButton() : DisplayObject
    { return lookup("chrome.controlBar.volume.unmuteButton") }
    override protected function get volumeSlider() : Sprite
    { return lookup("chrome.controlBar.volume.slider") }
    override protected function get volumeSliderThumb() : DisplayObject
    { return lookup("chrome.controlBar.volume.slider.thumb") }
    override protected function get volumeSliderThumbGuide() : DisplayObject
    { return lookup("chrome.controlBar.volume.slider.thumbGuide") }
    override protected function get volumeSliderFill() : DisplayObject
    { return lookup("chrome.controlBar.volume.slider.fill") }

    private function get fullscreenPart() : DisplayObject
    { return lookup("chrome.controlBar.fullscreen") }
    override protected function get enableFullscreenButton() : DisplayObject
    { return lookup("chrome.controlBar.fullscreen.enableButton") }

    override protected function lookup(name : String) : *
    { return super.lookup("skinContent." + name) }
	}
}

Split left/right time parts into several pieces.