package aerys.minko.render.shader
{
	import aerys.minko.ns.minko;
	import aerys.minko.render.renderer.state.RendererState;
	import aerys.minko.render.resource.ShaderResource;
	import aerys.minko.render.resource.TextureResource;
	import aerys.minko.render.shader.compiler.Compiler;
	import aerys.minko.render.shader.compiler.allocator.ParameterAllocation;
	import aerys.minko.render.shader.compiler.register.RegisterLimit;
	import aerys.minko.render.shader.node.INode;
	import aerys.minko.render.shader.node.leaf.AbstractParameter;
	import aerys.minko.render.shader.node.leaf.StyleParameter;
	import aerys.minko.render.shader.node.leaf.TransformParameter;
	import aerys.minko.render.shader.node.leaf.WorldParameter;
	import aerys.minko.scene.data.LocalData;
	import aerys.minko.scene.data.StyleStack;
	import aerys.minko.scene.data.ViewportData;
	import aerys.minko.type.math.Matrix4x4;
	import aerys.minko.type.math.Vector4;
	import aerys.minko.type.stream.format.VertexComponent;

	import flash.utils.ByteArray;
	import flash.utils.Dictionary;

	public class Shader
	{
		use namespace minko;

		protected var _resource					: ShaderResource;

		protected var _lastFrameId				: uint;
		protected var _lastStyleStackVersion	: uint;
		protected var _lastTransformVersion		: uint;

		protected var _vsConstData				: Vector.<Number>;
		protected var _fsConstData				: Vector.<Number>;
		protected var _vsParams					: Vector.<ParameterAllocation>;
		protected var _fsParams					: Vector.<ParameterAllocation>;
		protected var _samplers					: Vector.<int>;

		public function get resource() : ShaderResource
		{
			return _resource;
		}

		public static function create(outputPosition	: INode,
									  outputColor		: INode) : Shader
		{
			var compiler : Compiler = new Compiler();

			compiler.load(outputPosition, outputColor);

			return compiler.compileShader();
		}

		public function Shader(vertexShader				: ByteArray,
							   fragmentShader			: ByteArray,
							   vertexInputComponents	: Vector.<VertexComponent>,
							   vertexInputIndices		: Vector.<uint>,
							   samplers					: Vector.<int>,
							   vertexConstantData		: Vector.<Number>,
							   fragmentConstantData		: Vector.<Number>,
							   vertexParameters			: Vector.<ParameterAllocation>,
							   fragmentParameters		: Vector.<ParameterAllocation>)
		{
			_lastStyleStackVersion	= uint.MAX_VALUE;
			_lastTransformVersion	= uint.MAX_VALUE;

			_vsConstData	= vertexConstantData;
			_fsConstData	= fragmentConstantData;
			_vsParams		= vertexParameters;
			_fsParams		= fragmentParameters;
			_samplers		= samplers;

			_resource 		= new ShaderResource(vertexShader, fragmentShader, vertexInputComponents, vertexInputIndices);
		}

		public function fillRenderState(state		: RendererState,
										styleStack	: StyleStack,
										local		: LocalData,
										world		: Dictionary) : Boolean
		{
			if (_lastFrameId != world[ViewportData].frameId)
			{
				_lastFrameId			= world[ViewportData].frameId;
				_lastStyleStackVersion	= uint.MAX_VALUE;
				_lastTransformVersion	= uint.MAX_VALUE;
			}

			setTextures(state, styleStack, local, world);
			setConstants(state, styleStack, local, world);

			state.shader = _resource;

			_lastStyleStackVersion	= styleStack.version;
			_lastTransformVersion	= styleStack.version;

			return true;
		}

		protected function setTextures(state		: RendererState,
									   styleStack	: StyleStack,
								   	   localData	: LocalData,
									   worldData	: Object) : void
		{
			var texture 		: TextureResource	= null;
			var samplerStyleId 	: int				= 0;
			var samplerCount 	: uint 				= _samplers.length;

			for (var i : int = 0; i < samplerCount; ++i)
			{
				samplerStyleId	= _samplers[i];
				texture			= styleStack.get(samplerStyleId) as TextureResource;

				state.setTextureAt(i, texture);
			}
		}

		protected function setConstants(state		: RendererState,
									    styleStack	: StyleStack,
										local		: LocalData,
										world		: Dictionary) : void
		{
			updateConstData(_vsConstData, _vsParams, styleStack, local, world);
			updateConstData(_fsConstData, _fsParams, styleStack, local, world);

			state.setVertexConstants(_vsConstData);
			state.setFragmentConstants(_fsConstData);
		}

		protected function updateConstData(constData	: Vector.<Number>,
										   paramsAllocs	: Vector.<ParameterAllocation>,
										   styleStack	: StyleStack,
										   local		: LocalData,
										   world		: Dictionary) : void
		{
			var paramLength	: int = paramsAllocs.length;

			for (var i : int = 0; i < paramLength; ++i)
			{
				var paramAlloc	: ParameterAllocation	= paramsAllocs[i];
				var param		: AbstractParameter		= paramAlloc._parameter;

				if ((param is StyleParameter && styleStack.version == _lastStyleStackVersion) ||
					(param is TransformParameter && local.version == _lastTransformVersion))
					continue;

				var data : Object = getParameterData(param, styleStack, local, world);

				loadParameterData(paramAlloc, constData, data);
			}
		}

		private function getParameterData(param			: AbstractParameter,
										  styleStack	: StyleStack,
										  local			: LocalData,
										  world			: Dictionary) : Object
		{
			if (param is StyleParameter)
			{
				if (param._index != -1)
					return styleStack.get(param._key as int).getItem(param._index)[param._field];
				else if (param._field != null)
					return styleStack.get(param._key as int)[param._field];
				else
					return styleStack.get(param._key as int, null);
			}
			else if (param is WorldParameter)
			{
				var paramClass : Class = WorldParameter(param)._class;

				if (param._index != -1)
					return world[paramClass].getItem(param._index)[param._field];
				else if (param._field != null)
					return world[paramClass][param._field];
				else
					return world[paramClass];
			}
			else if (param is TransformParameter)
			{
				return local[param._key];
			}
			else
				throw new Error('Unknown parameter type');
		}

		private function loadParameterData(paramAlloc	: ParameterAllocation,
										   constData	: Vector.<Number>,
										   data			: Object) : void
		{
			var offset	: uint	= paramAlloc._offset;
			var size	: uint	= paramAlloc._parameter._size;

			if (data is int)
			{
				var intData : int = data as int;

				if (size == 1)
				{
					constData[offset] = intData;
				}
				else if (size == 2)
				{
					constData[offset] = ((intData & 0xFFFF0000) >>> 16) / Number(0xffff);
					constData[int(offset + 2)] = (intData & 0x0000FFFF) / Number(0xffff);
				}
				else if (size == 3)
				{
					constData[offset] = ((intData & 0xFF0000) >>> 16) / 255.;
					constData[int(offset + 1)] = ((intData & 0x00FF00) >>> 8) / 255.;
					constData[int(offset + 2)] = (intData & 0x0000FF) / 255.;
				}
				else if (size == 4)
				{

					constData[offset] = ((intData & 0xFF000000) >>> 24) / 255.;
					constData[int(offset + 1)] = ((intData & 0x00FF0000) >>> 16) / 255.;
					constData[int(offset + 2)] = ((intData & 0x0000FF00) >>> 8) / 255.;
					constData[int(offset + 3)] = ((intData & 0x000000FF)) / 255.;
				}
			}
			else if (data is uint)
			{
				var uintData : uint = data as uint;

				if (size == 1)
				{
					constData[offset] = uintData;
				}
				else if (size == 2)
				{
					constData[offset] = ((uintData & 0xFFFF0000) >>> 16) / Number(0xffff);
					constData[int(offset + 2)] = (uintData & 0x0000FFFF) / Number(0xffff);
				}
				else if (size == 3)
				{
					constData[offset] = ((uintData & 0xFF0000) >>> 16) / 255.;
					constData[int(offset + 1)] = ((uintData & 0x00FF00) >>> 8) / 255.;
					constData[int(offset + 2)] = (uintData & 0x0000FF) / 255.;
				}
				else if (size == 4)
				{

					constData[offset] = ((uintData & 0xFF000000) >>> 24) / 255.;
					constData[int(offset + 1)] = ((uintData & 0x00FF0000) >>> 16) / 255.;
					constData[int(offset + 2)] = ((uintData & 0x0000FF00) >>> 8) / 255.;
					constData[int(offset + 3)] = ((uintData & 0x000000FF)) / 255.;
				}
			}
			else if (data is Number)
			{
				if (size != 1)
					throw new Error('Parameter ' + paramAlloc.toString() + ' is ' +
						'defined as size=' + size + ' but only a Number was found');

				constData[offset] = data as Number;
			}
			else if (data is Vector4)
			{
				var vectorData : Vector4 = data as Vector4;

				constData[offset] = vectorData.x;
				size >= 2 && (constData[int(offset + 1)] = vectorData.y);
				size >= 3 && (constData[int(offset + 2)] = vectorData.z);
				size >= 4 && (constData[int(offset + 3)] = vectorData.w);
			}
			else if (data is Matrix4x4)
			{
				(data as Matrix4x4).getRawData(constData, offset, true);
			}
			else if (data is Vector.<Vector4>)
			{
				var vectorVectorData		: Vector.<Vector4>	= data as Vector.<Vector4>;
				var vectorVectorDataLength	: uint				= vectorVectorData.length;

				for (var j : uint = 0; j < vectorVectorDataLength; ++j)
				{
					vectorData = vectorVectorData[j];

					constData[offset + 4 * j] = vectorData.x;
					constData[int(offset + 4 * j + 1)] = vectorData.y;
					constData[int(offset + 4 * j + 2)] = vectorData.z;
					constData[int(offset + 4 * j + 3)] = vectorData.w;
				}
			}
			else if (data is Vector.<Matrix4x4>)
			{
				var matrixVectorData		: Vector.<Matrix4x4>	= data as Vector.<Matrix4x4>;
				var matrixVectorDataLength	: uint					= matrixVectorData.length;

				for (var i : uint = 0; i < matrixVectorDataLength; ++i)
				{
					matrixVectorData[i].getRawData(constData, offset + i * 16, true);
				}
			}
			else if (data == null)
			{
				throw new Error('Parameter ' + paramAlloc.toString() + ' is ' +
					'null and required by automatic shader');
			}
			else
			{
				throw new Error('Parameter ' + paramAlloc.toString() + ' is ' +
					'neither a int, a Number, a Vector4 or a Matrix4x4. Unable to ' +
					'map it to a shader constant.');
			}
		}
	}
}

package aerys.minko.render.shader
{
	import aerys.minko.ns.minko;
	import aerys.minko.render.renderer.state.RendererState;
	import aerys.minko.render.resource.ShaderResource;
	import aerys.minko.render.resource.TextureResource;
	import aerys.minko.render.shader.compiler.Compiler;
	import aerys.minko.render.shader.compiler.allocator.ParameterAllocation;
	import aerys.minko.render.shader.compiler.register.RegisterLimit;
	import aerys.minko.render.shader.node.INode;
	import aerys.minko.render.shader.node.leaf.AbstractParameter;
	import aerys.minko.render.shader.node.leaf.StyleParameter;
	import aerys.minko.render.shader.node.leaf.TransformParameter;
	import aerys.minko.render.shader.node.leaf.WorldParameter;
	import aerys.minko.scene.data.LocalData;
	import aerys.minko.scene.data.StyleStack;
	import aerys.minko.scene.data.ViewportData;
	import aerys.minko.type.math.Matrix4x4;
	import aerys.minko.type.math.Vector4;
	import aerys.minko.type.stream.format.VertexComponent;

	import flash.utils.ByteArray;
	import flash.utils.Dictionary;

	public class Shader
	{
		use namespace minko;

		protected var _resource					: ShaderResource;

		protected var _lastFrameId				: uint;
		protected var _lastStyleStackVersion	: uint;
		protected var _lastTransformVersion		: uint;

		protected var _vsConstData				: Vector.<Number>;
		protected var _fsConstData				: Vector.<Number>;
		protected var _vsParams					: Vector.<ParameterAllocation>;
		protected var _fsParams					: Vector.<ParameterAllocation>;
		protected var _samplers					: Vector.<int>;

		public function get resource() : ShaderResource
		{
			return _resource;
		}

		public static function create(outputPosition	: INode,
									  outputColor		: INode) : Shader
		{
			var compiler : Compiler = new Compiler();

			compiler.load(outputPosition, outputColor);

			return compiler.compileShader();
		}

		public function Shader(vertexShader				: ByteArray,
							   fragmentShader			: ByteArray,
							   vertexInputComponents	: Vector.<VertexComponent>,
							   vertexInputIndices		: Vector.<uint>,
							   samplers					: Vector.<int>,
							   vertexConstantData		: Vector.<Number>,
							   fragmentConstantData		: Vector.<Number>,
							   vertexParameters			: Vector.<ParameterAllocation>,
							   fragmentParameters		: Vector.<ParameterAllocation>)
		{
			_lastFrameId			= uint.MAX_VALUE;
			_lastStyleStackVersion	= uint.MAX_VALUE;
			_lastTransformVersion	= uint.MAX_VALUE;

			_vsConstData	= vertexConstantData;
			_fsConstData	= fragmentConstantData;
			_vsParams		= vertexParameters;
			_fsParams		= fragmentParameters;
			_samplers		= samplers;

			_resource 		= new ShaderResource(vertexShader, fragmentShader, vertexInputComponents, vertexInputIndices);
		}

		public function fillRenderState(state		: RendererState,
										styleStack	: StyleStack,
										local		: LocalData,
										world		: Dictionary) : Boolean
		{
			if (_lastFrameId != world[ViewportData].frameId)
			{
				_lastFrameId			= world[ViewportData].frameId;
				_lastStyleStackVersion	= uint.MAX_VALUE;
				_lastTransformVersion	= uint.MAX_VALUE;
			}

			setTextures(state, styleStack, local, world);
			setConstants(state, styleStack, local, world);

			state.shader = _resource;
			_lastStyleStackVersion	= styleStack.version;
			_lastTransformVersion	= local.version;

			return true;
		}

		protected function setTextures(state		: RendererState,
									   styleStack	: StyleStack,
								   	   localData	: LocalData,
									   worldData	: Object) : void
		{
			var texture 		: TextureResource	= null;
			var samplerStyleId 	: int				= 0;
			var samplerCount 	: uint 				= _samplers.length;

			for (var i : int = 0; i < samplerCount; ++i)
			{
				samplerStyleId	= _samplers[i];
				texture			= styleStack.get(samplerStyleId) as TextureResource;

				state.setTextureAt(i, texture);
			}
		}

		protected function setConstants(state		: RendererState,
									    styleStack	: StyleStack,
										local		: LocalData,
										world		: Dictionary) : void
		{
			updateConstData(_vsConstData, _vsParams, styleStack, local, world);
			updateConstData(_fsConstData, _fsParams, styleStack, local, world);

			state.setVertexConstants(_vsConstData);
			state.setFragmentConstants(_fsConstData);
		}

		protected function updateConstData(constData	: Vector.<Number>,
										   paramsAllocs	: Vector.<ParameterAllocation>,
										   styleStack	: StyleStack,
										   local		: LocalData,
										   world		: Dictionary) : void
		{
			var paramLength	: int = paramsAllocs.length;

			for (var i : int = 0; i < paramLength; ++i)
			{
				var paramAlloc	: ParameterAllocation	= paramsAllocs[i];
				var param		: AbstractParameter		= paramAlloc._parameter;

				if ((param is StyleParameter && styleStack.version == _lastStyleStackVersion) ||
					(param is TransformParameter && local.version == _lastTransformVersion))
					continue;

				var data : Object = getParameterData(param, styleStack, local, world);
				loadParameterData(paramAlloc, constData, data);
			}
		}

		private function getParameterData(param			: AbstractParameter,
										  styleStack	: StyleStack,
										  local			: LocalData,
										  world			: Dictionary) : Object
		{
			if (param is StyleParameter)
			{
				if (param._index != -1)
					return styleStack.get(param._key as int).getItem(param._index)[param._field];
				else if (param._field != null)
					return styleStack.get(param._key as int)[param._field];
				else
					return styleStack.get(param._key as int, null);
			}
			else if (param is WorldParameter)
			{
				var paramClass : Class = WorldParameter(param)._class;

				if (param._index != -1)
					return world[paramClass].getItem(param._index)[param._field];
				else if (param._field != null)
					return world[paramClass][param._field];
				else
					return world[paramClass];
			}
			else if (param is TransformParameter)
			{
				return local[param._key];
			}
			else
				throw new Error('Unknown parameter type');
		}

		private function loadParameterData(paramAlloc	: ParameterAllocation,
										   constData	: Vector.<Number>,
										   data			: Object) : void
		{
			var offset	: uint	= paramAlloc._offset;
			var size	: uint	= paramAlloc._parameter._size;

			if (data is int)
			{
				var intData : int = data as int;

				if (size == 1)
				{
					constData[offset] = intData;
				}
				else if (size == 2)
				{
					constData[offset] = ((intData & 0xFFFF0000) >>> 16) / Number(0xffff);
					constData[int(offset + 2)] = (intData & 0x0000FFFF) / Number(0xffff);
				}
				else if (size == 3)
				{
					constData[offset] = ((intData & 0xFF0000) >>> 16) / 255.;
					constData[int(offset + 1)] = ((intData & 0x00FF00) >>> 8) / 255.;
					constData[int(offset + 2)] = (intData & 0x0000FF) / 255.;
				}
				else if (size == 4)
				{

					constData[offset] = ((intData & 0xFF000000) >>> 24) / 255.;
					constData[int(offset + 1)] = ((intData & 0x00FF0000) >>> 16) / 255.;
					constData[int(offset + 2)] = ((intData & 0x0000FF00) >>> 8) / 255.;
					constData[int(offset + 3)] = ((intData & 0x000000FF)) / 255.;
				}
			}
			else if (data is uint)
			{
				var uintData : uint = data as uint;

				if (size == 1)
				{
					constData[offset] = uintData;
				}
				else if (size == 2)
				{
					constData[offset] = ((uintData & 0xFFFF0000) >>> 16) / Number(0xffff);
					constData[int(offset + 2)] = (uintData & 0x0000FFFF) / Number(0xffff);
				}
				else if (size == 3)
				{
					constData[offset] = ((uintData & 0xFF0000) >>> 16) / 255.;
					constData[int(offset + 1)] = ((uintData & 0x00FF00) >>> 8) / 255.;
					constData[int(offset + 2)] = (uintData & 0x0000FF) / 255.;
				}
				else if (size == 4)
				{

					constData[offset] = ((uintData & 0xFF000000) >>> 24) / 255.;
					constData[int(offset + 1)] = ((uintData & 0x00FF0000) >>> 16) / 255.;
					constData[int(offset + 2)] = ((uintData & 0x0000FF00) >>> 8) / 255.;
					constData[int(offset + 3)] = ((uintData & 0x000000FF)) / 255.;
				}
			}
			else if (data is Number)
			{
				if (size != 1)
					throw new Error('Parameter ' + paramAlloc.toString() + ' is ' +
						'defined as size=' + size + ' but only a Number was found');

				constData[offset] = data as Number;
			}
			else if (data is Vector4)
			{
				var vectorData : Vector4 = data as Vector4;

				constData[offset] = vectorData.x;
				size >= 2 && (constData[int(offset + 1)] = vectorData.y);
				size >= 3 && (constData[int(offset + 2)] = vectorData.z);
				size >= 4 && (constData[int(offset + 3)] = vectorData.w);
			}
			else if (data is Matrix4x4)
			{
				(data as Matrix4x4).getRawData(constData, offset, true);
			}
			else if (data is Vector.<Vector4>)
			{
				var vectorVectorData		: Vector.<Vector4>	= data as Vector.<Vector4>;
				var vectorVectorDataLength	: uint				= vectorVectorData.length;

				for (var j : uint = 0; j < vectorVectorDataLength; ++j)
				{
					vectorData = vectorVectorData[j];

					constData[offset + 4 * j] = vectorData.x;
					constData[int(offset + 4 * j + 1)] = vectorData.y;
					constData[int(offset + 4 * j + 2)] = vectorData.z;
					constData[int(offset + 4 * j + 3)] = vectorData.w;
				}
			}
			else if (data is Vector.<Matrix4x4>)
			{
				var matrixVectorData		: Vector.<Matrix4x4>	= data as Vector.<Matrix4x4>;
				var matrixVectorDataLength	: uint					= matrixVectorData.length;

				for (var i : uint = 0; i < matrixVectorDataLength; ++i)
				{
					matrixVectorData[i].getRawData(constData, offset + i * 16, true);
				}
			}
			else if (data == null)
			{
				throw new Error('Parameter ' + paramAlloc.toString() + ' is ' +
					'null and required by automatic shader');
			}
			else
			{
				throw new Error('Parameter ' + paramAlloc.toString() + ' is ' +
					'neither a int, a Number, a Vector4 or a Matrix4x4. Unable to ' +
					'map it to a shader constant.');
			}
		}
	}
}

Fix minor bug in Shader

Fix minor bug in Shader


/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 *   Marc Alcaraz <ekameleon@gmail.com>.
 */

package com.google.analytics
{
    import com.google.analytics.core.Buffer;
    import com.google.analytics.core.Ecommerce;
    import com.google.analytics.core.EventTracker;
    import com.google.analytics.core.GIFRequest;
    import com.google.analytics.core.IdleTimer;
    import com.google.analytics.core.ServerOperationMode;
    import com.google.analytics.core.TrackerCache;
    import com.google.analytics.core.TrackerMode;
    import com.google.analytics.core.ga_internal;
    import com.google.analytics.debug.DebugConfiguration;
    import com.google.analytics.debug.Layout;
    import com.google.analytics.events.AnalyticsEvent;
    import com.google.analytics.external.AdSenseGlobals;
    import com.google.analytics.external.HTMLDOM;
    import com.google.analytics.external.JavascriptProxy;
    import com.google.analytics.utils.Environment;
    import com.google.analytics.v4.Bridge;
    import com.google.analytics.v4.Configuration;
    import com.google.analytics.v4.GoogleAnalyticsAPI;
    import com.google.analytics.v4.Tracker;

    import core.version;

    import flash.display.DisplayObject;
    import flash.events.Event;
    import flash.events.EventDispatcher;

    EventTracker;
    ServerOperationMode;

    /**
     * Dispatched after the factory has built the tracker object.
     * @eventType com.google.analytics.events.AnalyticsEvent.READY
     */
    [Event(name="ready", type="com.google.analytics.events.AnalyticsEvent")]

    /**
     * Google Analytic Tracker Code (GATC)'s code-only component.
     */
    public class GATracker implements AnalyticsTracker
    {
        private var _ready:Boolean = false;

        private var _display:DisplayObject;
        private var _eventDispatcher:EventDispatcher;
        private var _tracker:GoogleAnalyticsAPI;

        //factory
        private var _config:Configuration;
        private var _debug:DebugConfiguration;
        private var _env:Environment;
        private var _buffer:Buffer;
        private var _gifRequest:GIFRequest;
        private var _jsproxy:JavascriptProxy;
        private var _dom:HTMLDOM;
        private var _adSense:AdSenseGlobals;
        private var _idleTimer:IdleTimer;
        private var _ecom:Ecommerce;

        //object properties
        private var _account:String;
        private var _mode:String;
        private var _visualDebug:Boolean;

        /**
         * Indicates if the tracker is automatically build.
         */
        public static var autobuild:Boolean = true;

        /**
         * The version of the tracker.
         */
        public static var version:core.version = API.version;

        /**
         * Creates a new GATracker instance.
         *
Note: the GATracker need to be instancied and added to the Stage or at least
         * being placed in a display list.

         */
        public function GATracker( display:DisplayObject, account:String,
                                   mode:String = "AS3", visualDebug:Boolean = false,
                                   config:Configuration = null, debug:DebugConfiguration = null )
        {
            _display = display;
            _eventDispatcher = new EventDispatcher( this ) ;
            _tracker = new TrackerCache();

            this.account     = account;
            this.mode        = mode;
            this.visualDebug = visualDebug;

            if( !debug )
            {
                this.debug = new DebugConfiguration();
            }

            if( !config )
            {
                this.config = new Configuration( debug );
            }
            else
            {
            	this.config = config;
            }

            if( autobuild )
            {
                _factory();
            }
        }

        /**
         * @private
         * Factory to build the different trackers
         */
        private function _factory():void
        {
            _jsproxy = new JavascriptProxy( debug );

            if( visualDebug )
            {
                debug.layout = new Layout( debug, _display );
                debug.active = visualDebug;
            }

            var activeTracker:GoogleAnalyticsAPI;
            var cache:TrackerCache = _tracker as TrackerCache;

            switch( mode )
            {
                case TrackerMode.BRIDGE :
                {
                    activeTracker = _bridgeFactory();
                    break;
                }

                case TrackerMode.AS3 :
                default:
                {
                    activeTracker = _trackerFactory();
                }
            }

            if( !cache.isEmpty() )
            {
                cache.tracker = activeTracker;
                cache.flush();
            }

            _tracker = activeTracker;

            _ready = true;
            dispatchEvent( new AnalyticsEvent( AnalyticsEvent.READY, this ) );
        }

        /**
        * @private
        * Factory method for returning a Tracker object.
        *
        * @return {GoogleAnalyticsAPI}
        */
        private function _trackerFactory():GoogleAnalyticsAPI
        {
            debug.info( "GATracker (AS3) v" + version +"\naccount: " + account );

            /* note:
               for unit testing and to avoid 2 different branches AIR/Flash
               here we will detect if we are in the Flash Player or AIR
               and pass the infos to the LocalInfo

               By default we will define "Flash" for our local tests
            */

            _adSense    = new AdSenseGlobals( debug );

            _dom        = new HTMLDOM( debug );
            _dom.cacheProperties();

            _env        = new Environment( "", "", "", debug, _dom );

            _buffer     = new Buffer( config, debug, false );
            _gifRequest = new GIFRequest( config, debug, _buffer, _env );
            _idleTimer  = new IdleTimer( config, debug, _display, _buffer );
            _ecom       = new Ecommerce ( _debug );

            /* note:
               To be able to obtain the URL of the main SWF containing the GA API
               we need to be able to access the stage property of a DisplayObject,
               here we open the internal namespace to be able to set that reference
               at instanciation-time.

               We keep the implementation internal to be able to change it if required later.
            */
            use namespace ga_internal;
            _env.url = _display.stage.loaderInfo.url;

            return new Tracker( account, config, debug, _env, _buffer, _gifRequest, _adSense, _ecom );
        }

        /**
        * @private
        * Factory method for returning a Bridge object.
        *
        * @return {GoogleAnalyticsAPI}
        */
        private function _bridgeFactory():GoogleAnalyticsAPI
        {
            debug.info( "GATracker (Bridge) v" + version +"\naccount: " + account );
            return new Bridge( account, _debug, _jsproxy );
        }

        /**
         * Indicates the account value of the tracking.
         */
        public function get account():String
        {
            return _account;
        }

        /**
         * @private
         */
        public function set account( value:String ):void
        {
            _account = value;
        }

        /**
         * Determinates the Configuration object of the tracker.
         */
        public function get config():Configuration
        {
            return _config;
        }

        /**
         * @private
         */
        public function set config( value:Configuration ):void
        {
            _config = value;
        }

        /**
         * Determinates the DebugConfiguration of the tracker.
         */
        public function get debug():DebugConfiguration
        {
            return _debug;
        }

        /**
         * @private
         */
        public function set debug( value:DebugConfiguration ):void
        {
            _debug = value;
        }

        /**
         * Indicates if the tracker is ready to use.
         */
        public function isReady():Boolean
        {
            return _ready;
        }

        /**
         * Indicates the mode of the tracking "AS3" or "Bridge".
         */
        public function get mode():String
        {
            return _mode;
        }

        /**
         * @private
         */
        public function set mode( value:String ):void
        {
            _mode = value ;
        }

        /**
         * Indicates if the tracker use a visual debug.
         */
        public function get visualDebug():Boolean
        {
            return _visualDebug;
        }

        /**
         * @private
         */
        public function set visualDebug( value:Boolean ):void
        {
            _visualDebug = value;
        }

        /**
         * Builds the tracker.
         */
        public function build():void
        {
            if( !isReady() )
            {
                _factory();
            }
        }

        // IEventDispatcher implementation

        /**
         * Allows the registration of event listeners on the event target.
         * @param type A string representing the event type to listen for. If eventName value is "ALL" addEventListener use addGlobalListener
         * @param listener The Function that receives a notification when an event of the specified type occurs.
         * @param useCapture Determinates if the event flow use capture or not.
         * @param priority Determines the priority level of the event listener.
         * @param useWeakReference Indicates if the listener is a weak reference.
         */
        public function addEventListener( type:String, listener:Function, useCapture:Boolean = false, priority:int = 0,
                                          useWeakReference:Boolean = false):void
        {
            _eventDispatcher.addEventListener( type, listener, useCapture, priority, useWeakReference );
        }

        /**
         * Dispatches an event into the event flow.
         * @param event The Event object that is dispatched into the event flow.
         * @return true if the Event is dispatched.
         */
        public function dispatchEvent( event:Event ):Boolean
        {
            return _eventDispatcher.dispatchEvent( event );
        }

        /**
         * Checks whether the EventDispatcher object has any listeners registered for a specific type of event.
         * This allows you to determine where altered handling of an event type has been introduced in the event flow heirarchy by an EventDispatcher object.
         */
        public function hasEventListener( type:String ):Boolean
        {
            return _eventDispatcher.hasEventListener( type );
        }

        /**
         * Removes a listener from the EventDispatcher object.
         * If there is no matching listener registered with the EventDispatcher object, then calling this method has no effect.
         * @param type Specifies the type of event.
         * @param listener The Function that receives a notification when an event of the specified type occurs.
         * @param useCapture Determinates if the event flow use capture or not.
         */
        public function removeEventListener( type:String, listener:Function, useCapture:Boolean = false ):void
        {
            _eventDispatcher.removeEventListener( type, listener, useCapture );
        }

        /**
         * Checks whether an event listener is registered with this EventDispatcher object or any of its ancestors for the specified event type.
         * This method returns true if an event listener is triggered during any phase of the event flow when an event of the specified type is dispatched to this EventDispatcher object or any of its descendants.
         * @return A value of true if a listener of the specified type will be triggered; false otherwise.
         */
        public function willTrigger( type:String ):Boolean
        {
            return _eventDispatcher.willTrigger( type );
        }

        include "common.txt"

    }
}

/*
 * Copyright 2008 Adobe Systems Inc., 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributor(s):
 *   Zwetan Kjukov <zwetan@gmail.com>.
 *   Marc Alcaraz <ekameleon@gmail.com>.
 */

package com.google.analytics
{
    import com.google.analytics.core.Buffer;
    import com.google.analytics.core.Ecommerce;
    import com.google.analytics.core.EventTracker;
    import com.google.analytics.core.GIFRequest;
    import com.google.analytics.core.ServerOperationMode;
    import com.google.analytics.core.TrackerCache;
    import com.google.analytics.core.TrackerMode;
    import com.google.analytics.core.ga_internal;
    import com.google.analytics.debug.DebugConfiguration;
    import com.google.analytics.debug.Layout;
    import com.google.analytics.events.AnalyticsEvent;
    import com.google.analytics.external.AdSenseGlobals;
    import com.google.analytics.external.HTMLDOM;
    import com.google.analytics.external.JavascriptProxy;
    import com.google.analytics.utils.Environment;
    import com.google.analytics.v4.Bridge;
    import com.google.analytics.v4.Configuration;
    import com.google.analytics.v4.GoogleAnalyticsAPI;
    import com.google.analytics.v4.Tracker;

    import core.version;

    import flash.display.DisplayObject;
    import flash.events.Event;
    import flash.events.EventDispatcher;

    EventTracker;
    ServerOperationMode;

    /**
     * Dispatched after the factory has built the tracker object.
     * @eventType com.google.analytics.events.AnalyticsEvent.READY
     */
    [Event(name="ready", type="com.google.analytics.events.AnalyticsEvent")]

    /**
     * Google Analytic Tracker Code (GATC)'s code-only component.
     */
    public class GATracker implements AnalyticsTracker
    {
        private var _ready:Boolean = false;

        private var _display:DisplayObject;
        private var _eventDispatcher:EventDispatcher;
        private var _tracker:GoogleAnalyticsAPI;

        //factory
        private var _config:Configuration;
        private var _debug:DebugConfiguration;
        private var _env:Environment;
        private var _buffer:Buffer;
        private var _gifRequest:GIFRequest;
        private var _jsproxy:JavascriptProxy;
        private var _dom:HTMLDOM;
        private var _adSense:AdSenseGlobals;
        private var _ecom:Ecommerce;

        //object properties
        private var _account:String;
        private var _mode:String;
        private var _visualDebug:Boolean;

        /**
         * Indicates if the tracker is automatically build.
         */
        public static var autobuild:Boolean = true;

        /**
         * The version of the tracker.
         */
        public static var version:core.version = API.version;

        /**
         * Creates a new GATracker instance.
         *
Note: the GATracker need to be instancied and added to the Stage or at least
         * being placed in a display list.

         */
        public function GATracker( display:DisplayObject, account:String,
                                   mode:String = "AS3", visualDebug:Boolean = false,
                                   config:Configuration = null, debug:DebugConfiguration = null )
        {
            _display = display;
            _eventDispatcher = new EventDispatcher( this ) ;
            _tracker = new TrackerCache();

            this.account     = account;
            this.mode        = mode;
            this.visualDebug = visualDebug;

            if( !debug )
            {
                this.debug = new DebugConfiguration();
            }

            if( !config )
            {
                this.config = new Configuration( debug );
            }
            else
            {
            	this.config = config;
            }

            if( autobuild )
            {
                _factory();
            }
        }

        /**
         * @private
         * Factory to build the different trackers
         */
        private function _factory():void
        {
            _jsproxy = new JavascriptProxy( debug );

            if( visualDebug )
            {
                debug.layout = new Layout( debug, _display );
                debug.active = visualDebug;
            }

            var activeTracker:GoogleAnalyticsAPI;
            var cache:TrackerCache = _tracker as TrackerCache;

            switch( mode )
            {
                case TrackerMode.BRIDGE :
                {
                    activeTracker = _bridgeFactory();
                    break;
                }

                case TrackerMode.AS3 :
                default:
                {
                    activeTracker = _trackerFactory();
                }
            }

            if( !cache.isEmpty() )
            {
                cache.tracker = activeTracker;
                cache.flush();
            }

            _tracker = activeTracker;

            _ready = true;
            dispatchEvent( new AnalyticsEvent( AnalyticsEvent.READY, this ) );
        }

        /**
        * @private
        * Factory method for returning a Tracker object.
        *
        * @return {GoogleAnalyticsAPI}
        */
        private function _trackerFactory():GoogleAnalyticsAPI
        {
            debug.info( "GATracker (AS3) v" + version +"\naccount: " + account );

            /* note:
               for unit testing and to avoid 2 different branches AIR/Flash
               here we will detect if we are in the Flash Player or AIR
               and pass the infos to the LocalInfo

               By default we will define "Flash" for our local tests
            */

            _adSense    = new AdSenseGlobals( debug );

            _dom        = new HTMLDOM( debug );
            _dom.cacheProperties();

            _env        = new Environment( "", "", "", debug, _dom );

            _buffer     = new Buffer( config, debug, false );
            _gifRequest = new GIFRequest( config, debug, _buffer, _env );
            _ecom       = new Ecommerce ( _debug );

            /* note:
               To be able to obtain the URL of the main SWF containing the GA API
               we need to be able to access the stage property of a DisplayObject,
               here we open the internal namespace to be able to set that reference
               at instanciation-time.

               We keep the implementation internal to be able to change it if required later.
            */
            use namespace ga_internal;
            _env.url = _display.stage.loaderInfo.url;

            return new Tracker( account, config, debug, _env, _buffer, _gifRequest, _adSense, _ecom );
        }

        /**
        * @private
        * Factory method for returning a Bridge object.
        *
        * @return {GoogleAnalyticsAPI}
        */
        private function _bridgeFactory():GoogleAnalyticsAPI
        {
            debug.info( "GATracker (Bridge) v" + version +"\naccount: " + account );
            return new Bridge( account, _debug, _jsproxy );
        }

        /**
         * Indicates the account value of the tracking.
         */
        public function get account():String
        {
            return _account;
        }

        /**
         * @private
         */
        public function set account( value:String ):void
        {
            _account = value;
        }

        /**
         * Determinates the Configuration object of the tracker.
         */
        public function get config():Configuration
        {
            return _config;
        }

        /**
         * @private
         */
        public function set config( value:Configuration ):void
        {
            _config = value;
        }

        /**
         * Determinates the DebugConfiguration of the tracker.
         */
        public function get debug():DebugConfiguration
        {
            return _debug;
        }

        /**
         * @private
         */
        public function set debug( value:DebugConfiguration ):void
        {
            _debug = value;
        }

        /**
         * Indicates if the tracker is ready to use.
         */
        public function isReady():Boolean
        {
            return _ready;
        }

        /**
         * Indicates the mode of the tracking "AS3" or "Bridge".
         */
        public function get mode():String
        {
            return _mode;
        }

        /**
         * @private
         */
        public function set mode( value:String ):void
        {
            _mode = value ;
        }

        /**
         * Indicates if the tracker use a visual debug.
         */
        public function get visualDebug():Boolean
        {
            return _visualDebug;
        }

        /**
         * @private
         */
        public function set visualDebug( value:Boolean ):void
        {
            _visualDebug = value;
        }

        /**
         * Builds the tracker.
         */
        public function build():void
        {
            if( !isReady() )
            {
                _factory();
            }
        }

        // IEventDispatcher implementation

        /**
         * Allows the registration of event listeners on the event target.
         * @param type A string representing the event type to listen for. If eventName value is "ALL" addEventListener use addGlobalListener
         * @param listener The Function that receives a notification when an event of the specified type occurs.
         * @param useCapture Determinates if the event flow use capture or not.
         * @param priority Determines the priority level of the event listener.
         * @param useWeakReference Indicates if the listener is a weak reference.
         */
        public function addEventListener( type:String, listener:Function, useCapture:Boolean = false, priority:int = 0,
                                          useWeakReference:Boolean = false):void
        {
            _eventDispatcher.addEventListener( type, listener, useCapture, priority, useWeakReference );
        }

        /**
         * Dispatches an event into the event flow.
         * @param event The Event object that is dispatched into the event flow.
         * @return true if the Event is dispatched.
         */
        public function dispatchEvent( event:Event ):Boolean
        {
            return _eventDispatcher.dispatchEvent( event );
        }

        /**
         * Checks whether the EventDispatcher object has any listeners registered for a specific type of event.
         * This allows you to determine where altered handling of an event type has been introduced in the event flow heirarchy by an EventDispatcher object.
         */
        public function hasEventListener( type:String ):Boolean
        {
            return _eventDispatcher.hasEventListener( type );
        }

        /**
         * Removes a listener from the EventDispatcher object.
         * If there is no matching listener registered with the EventDispatcher object, then calling this method has no effect.
         * @param type Specifies the type of event.
         * @param listener The Function that receives a notification when an event of the specified type occurs.
         * @param useCapture Determinates if the event flow use capture or not.
         */
        public function removeEventListener( type:String, listener:Function, useCapture:Boolean = false ):void
        {
            _eventDispatcher.removeEventListener( type, listener, useCapture );
        }

        /**
         * Checks whether an event listener is registered with this EventDispatcher object or any of its ancestors for the specified event type.
         * This method returns true if an event listener is triggered during any phase of the event flow when an event of the specified type is dispatched to this EventDispatcher object or any of its descendants.
         * @return A value of true if a listener of the specified type will be triggered; false otherwise.
         */
        public function willTrigger( type:String ):Boolean
        {
            return _eventDispatcher.willTrigger( type );
        }

        include "common.txt"

    }
}

remove idle timer instanciation

remove idle timer instanciation


package aerys.minko.type.binding
{
	import aerys.minko.type.Signal;
	import aerys.minko.type.enum.DataProviderUsage;

	import flash.utils.Dictionary;
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;

	public dynamic class DataProvider extends Proxy implements IDynamicDataProvider
	{
		private var _usage				: uint;
		private var _name				: String;
		private var _descriptor			: Object;

		private var _propertyChanged	: Signal;
		private var _propertyAdded		: Signal;
		private var _propertyRemoved	: Signal;

		private var _nameToProperty		: Object;
		private var _propertyToNames	: Dictionary;

		public function get usage() : uint
		{
			return _usage;
		}

		public function get dataDescriptor() : Object
		{
			return _descriptor;
		}

		public function get propertyChanged() : Signal
		{
			return _propertyChanged;
		}

		public function get propertyAdded() : Signal
		{
			return _propertyAdded;
		}

		public function get propertyRemoved() : Signal
		{
			return _propertyRemoved;
		}

		public function get name() : String
		{
			return _name;
		}

		public function set name(v : String) : void
		{
			_name = v;
		}

		public function DataProvider(properties	: Object	= null,
									 name		: String	= null,
									 usage		: uint		= 1)
		{
			_name	= name;
			_usage	= usage;

			initialize(properties);
		}

		private function initialize(properties : Object) : void
		{
			_descriptor = {};
			_propertyChanged = new Signal('DataProvider.changed');
			_propertyAdded = new Signal('DataProvider.propertyAdded');
			_propertyRemoved = new Signal('DataProvider.propertyRemoved');
			_nameToProperty = {};
			_propertyToNames = new Dictionary();

			var propertyName : String = null;

			if (properties is DataProvider)
			{
				var provider : DataProvider = properties as DataProvider;

				for each (propertyName in provider.dataDescriptor)
					setProperty(propertyName, provider[propertyName]);
			}
			else if (properties is Object)
			{
				for (propertyName in properties)
					setProperty(propertyName, properties[propertyName]);
			}
		}

		override flash_proxy function getProperty(name : *) : *
		{
			return getProperty(String(name));
		}

		override flash_proxy function setProperty(name : *, value : *) : void
		{
			setProperty(String(name), value);
		}

		override flash_proxy function deleteProperty(name : *) : Boolean
		{
			removeProperty(String(name));

			return true;
		}

		public function getProperty(name : String) : *
		{
			return _nameToProperty[name];
		}

		public function setProperty(name : String, newValue : Object) : DataProvider
		{
			var oldValue 			: Object			= _nameToProperty[name];
			var oldMonitoredValue	: IWatchable		= oldValue as IWatchable;
			var newMonitoredValue	: IWatchable		= newValue as IWatchable;
			var oldPropertyNames	: Vector.<String>	= _propertyToNames[oldMonitoredValue];
			var newPropertyNames	: Vector.<String>	= _propertyToNames[newMonitoredValue];

			if (oldMonitoredValue != null)
			{
				if (oldPropertyNames.length == 1)
				{
					oldMonitoredValue.changed.remove(propertyChangedHandler);
					delete _propertyToNames[oldMonitoredValue];
				}
				else
					oldPropertyNames.splice(oldPropertyNames.indexOf(name), 1);
			}

			if (newMonitoredValue != null)
				watchProperty(name, newMonitoredValue);

			var propertyAdded : Boolean = !_descriptor.hasOwnProperty(name);

			_descriptor[name]		= name;
			_nameToProperty[name]	= newValue;

			if (propertyAdded)
				_propertyAdded.execute(this, name, name, newValue);
			else
				_propertyChanged.execute(this, name);

			return this;
		}

		public function setProperties(properties : Object) : DataProvider
		{
			for (var propertyName : String in properties)
				setProperty(propertyName, properties[propertyName]);

			return this;
		}

		protected function watchProperty(name : String, property : IWatchable) : void
		{
			if (property != null)
			{
				var newPropertyNames : Vector.<String> = _propertyToNames[property] as Vector.<String>;

				if (newPropertyNames == null)
				{
					_propertyToNames[property] = newPropertyNames = new <String>[name];
					property.changed.add(propertyChangedHandler);
				}
				else
					newPropertyNames.push(name);
			}
		}

		public function removeProperty(name : String) : DataProvider
		{
			if (_descriptor.hasOwnProperty(name))
			{
				var oldMonitoredValue	: IWatchable		= _nameToProperty[name] as IWatchable;
				var oldPropertyNames	: Vector.<String>	= _propertyToNames[oldMonitoredValue];
				var bindingName			: String			= _descriptor[name];

				delete _descriptor[name];
				delete _nameToProperty[name];

				if (oldMonitoredValue != null)
				{
					if (oldPropertyNames.length == 1)
					{
						oldMonitoredValue.changed.remove(propertyChangedHandler);
						delete _propertyToNames[oldMonitoredValue];
					}
					else
						oldPropertyNames.splice(oldPropertyNames.indexOf(name), 1);
				}

	//			_changed.execute(this, 'dataDescriptor');
				_propertyRemoved.execute(this, name, bindingName, oldMonitoredValue);
			}

			return this;
		}

		public function removeAllProperties() : DataProvider
		{
			for (var propertyName : String in _nameToProperty)
				removeProperty(propertyName);

			return this;
		}

		public function propertyExists(name : String) : Boolean
		{
			return _descriptor.hasOwnProperty(name);
		}

		public function invalidate() : DataProvider
		{
			_propertyChanged.execute(this, null);

			return this;
		}

		public function clone() : IDataProvider
		{
			switch (_usage)
			{
				case DataProviderUsage.EXCLUSIVE:
					return new DataProvider(_nameToProperty, _name + '_cloned', _usage);
				case DataProviderUsage.SHARED:
					return this;
				case DataProviderUsage.MANAGED:
					throw new Error('This dataprovider is managed, and must not be cloned');

				default:
					throw new Error('Unkown usage value');
			}
		}

		private function propertyChangedHandler(source : IWatchable) : void
		{
			var names		: Vector.<String>	= _propertyToNames[source];
			var numNames	: uint				= names.length;

			for (var nameId : uint = 0; nameId < numNames; ++nameId)
				_propertyChanged.execute(this, names[nameId]);
		}
	}
}

package aerys.minko.type.binding
{
	import aerys.minko.type.Signal;
	import aerys.minko.type.enum.DataProviderUsage;

	import flash.utils.Dictionary;
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;

	public dynamic class DataProvider extends Proxy implements IDynamicDataProvider
	{
		private var _usage				: uint;
		private var _name				: String;
		private var _descriptor			: Object;

		private var _propertyChanged	: Signal;
		private var _propertyAdded		: Signal;
		private var _propertyRemoved	: Signal;

		private var _nameToProperty		: Object;
		private var _propertyToNames	: Dictionary;

		public function get usage() : uint
		{
			return _usage;
		}

		public function get dataDescriptor() : Object
		{
			return _descriptor;
		}

		public function get propertyChanged() : Signal
		{
			return _propertyChanged;
		}

		public function get propertyAdded() : Signal
		{
			return _propertyAdded;
		}

		public function get propertyRemoved() : Signal
		{
			return _propertyRemoved;
		}

		public function get name() : String
		{
			return _name;
		}

		public function set name(v : String) : void
		{
			_name = v;
		}

		public function DataProvider(properties	: Object	= null,
									 name		: String	= null,
									 usage		: uint		= 1)
		{
			_name	= name;
			_usage	= usage;

			initialize(properties);
		}

		private function initialize(properties : Object) : void
		{
			_descriptor = {};
			_propertyChanged = new Signal('DataProvider.changed');
			_propertyAdded = new Signal('DataProvider.propertyAdded');
			_propertyRemoved = new Signal('DataProvider.propertyRemoved');
			_nameToProperty = {};
			_propertyToNames = new Dictionary();

			var propertyName : String = null;

			if (properties is DataProvider)
			{
				var provider : DataProvider = properties as DataProvider;

				for each (propertyName in provider.dataDescriptor)
					setProperty(propertyName, provider[propertyName]);
			}
			else if (properties is Object)
			{
				for (propertyName in properties)
					setProperty(propertyName, properties[propertyName]);
			}
		}

		override flash_proxy function getProperty(name : *) : *
		{
			return getProperty(String(name));
		}

		override flash_proxy function setProperty(name : *, value : *) : void
		{
			setProperty(String(name), value);
		}

		override flash_proxy function deleteProperty(name : *) : Boolean
		{
			removeProperty(String(name));

			return true;
		}

		public function getProperty(name : String) : *
		{
			return _nameToProperty[name];
		}

		public function setProperty(name : String, newValue : Object) : DataProvider
		{
			var oldValue 			: Object			= _nameToProperty[name];
			var oldWatchedValue	    : IWatchable		= oldValue as IWatchable;
			var newWatchedValue	    : IWatchable		= newValue as IWatchable;
			var oldPropertyNames	: Vector.<String>	= _propertyToNames[oldWatchedValue];
			var newPropertyNames	: Vector.<String>	= _propertyToNames[newWatchedValue];

            if (newWatchedValue != oldWatchedValue)
            {
    			if (oldWatchedValue != null)
    			    unwatchProperty(name, oldWatchedValue);

    			if (newWatchedValue != null)
    				watchProperty(name, newWatchedValue);
            }

			var propertyAdded : Boolean = !_descriptor.hasOwnProperty(name);

			_descriptor[name]		= name;
			_nameToProperty[name]	= newValue;

			if (propertyAdded)
				_propertyAdded.execute(this, name, name, newValue);
			else
				_propertyChanged.execute(this, name);

			return this;
		}

		public function setProperties(properties : Object) : DataProvider
		{
			for (var propertyName : String in properties)
				setProperty(propertyName, properties[propertyName]);

			return this;
		}

		protected function watchProperty(name : String, property : IWatchable) : void
		{
			if (property != null)
			{
				var newPropertyNames : Vector.<String> = _propertyToNames[property] as Vector.<String>;

				if (newPropertyNames == null)
				{
					_propertyToNames[property] = newPropertyNames = new <String>[name];
					property.changed.add(propertyChangedHandler);
				}
				else
					newPropertyNames.push(name);
			}
		}

        protected function unwatchProperty(name : String, property : IWatchable) : void
        {
            var oldPropertyNames	: Vector.<String>	= _propertyToNames[property];

            if (oldPropertyNames.length == 1)
            {
                property.changed.remove(propertyChangedHandler);
                delete _propertyToNames[property];
            }
            else
            {
                var numPropertyNames : uint = oldPropertyNames.length - 1;

                oldPropertyNames[oldPropertyNames.indexOf(name)] = oldPropertyNames[numPropertyNames];
                oldPropertyNames.length = numPropertyNames;
            }
        }

		public function removeProperty(name : String) : DataProvider
		{
			if (_descriptor.hasOwnProperty(name))
			{
				var oldMonitoredValue	: IWatchable		= _nameToProperty[name] as IWatchable;
				var oldPropertyNames	: Vector.<String>	= _propertyToNames[oldMonitoredValue];
				var bindingName			: String			= _descriptor[name];

				delete _descriptor[name];
				delete _nameToProperty[name];

				if (oldMonitoredValue != null)
					unwatchProperty(name, oldMonitoredValue);

	//			_changed.execute(this, 'dataDescriptor');
				_propertyRemoved.execute(this, name, bindingName, oldMonitoredValue);
			}

			return this;
		}

		public function removeAllProperties() : DataProvider
		{
			for (var propertyName : String in _nameToProperty)
				removeProperty(propertyName);

			return this;
		}

		public function propertyExists(name : String) : Boolean
		{
			return _descriptor.hasOwnProperty(name);
		}

		public function invalidate() : DataProvider
		{
			_propertyChanged.execute(this, null);

			return this;
		}

		public function clone() : IDataProvider
		{
			switch (_usage)
			{
				case DataProviderUsage.EXCLUSIVE:
					return new DataProvider(_nameToProperty, _name + '_cloned', _usage);
				case DataProviderUsage.SHARED:
					return this;
				case DataProviderUsage.MANAGED:
					throw new Error('This dataprovider is managed, and must not be cloned');

				default:
					throw new Error('Unkown usage value');
			}
		}

		private function propertyChangedHandler(source : IWatchable) : void
		{
			var names		: Vector.<String>	= _propertyToNames[source];
			var numNames	: uint				= names.length;

			for (var nameId : uint = 0; nameId < numNames; ++nameId)
				_propertyChanged.execute(this, names[nameId]);
		}
	}
}

add DataProvider.unwatchProperty() protected method to unwatch a property and refactor other methods to use it


package org.mangui.jwplayer.media {
    import org.mangui.HLS.parsing.Level;
    import org.mangui.HLS.*;
    import org.mangui.HLS.utils.Log;
    import org.mangui.HLS.utils.ScaleVideo;

    import com.longtailvideo.jwplayer.events.MediaEvent;
    import com.longtailvideo.jwplayer.model.PlayerConfig;
    import com.longtailvideo.jwplayer.model.PlaylistItem;
    import com.longtailvideo.jwplayer.media.*;
    import com.longtailvideo.jwplayer.player.PlayerState;
    import com.longtailvideo.jwplayer.utils.RootReference;

    import flash.display.DisplayObject;
    import flash.geom.Rectangle;
    import flash.media.SoundTransform;
    import flash.media.Video;
    import flash.media.StageVideo;
    import flash.system.Capabilities;
    import flash.events.Event;

    /** JW Player provider for hls streaming. **/
    public class HLSProvider extends MediaProvider {
        /** Reference to the framework. **/
        protected var _hls : HLS;
        /** Current quality level. **/
        protected var _level : Number;
        /** Reference to the quality levels. **/
        protected var _levels : Vector.<Level>;
        /** Reference to the video object. **/
        private var _video : Video;
        /** Reference to the stage video element. **/
        private var _stageVideo : StageVideo;
        /** Whether or not StageVideo is enabled (not working with JW5) **/
        protected var _stageEnabled : Boolean = false;
        /** current position **/
        protected var _media_position : Number;
        /** Video Original size **/
        private var _videoWidth : Number = 0;
        private var _videoHeight : Number = 0;
        private var _seekInLiveDurationThreshold : Number = 60;

        public function HLSProvider() {
            super('hls');
        };

        /** Forward completes from the framework. **/
        private function _completeHandler(event : HLSEvent) : void {
            complete();
        };

        /** Forward playback errors from the framework. **/
        private function _errorHandler(event : HLSEvent) : void {
            super.error(event.error.msg);
        };

        /** Forward QOS metrics on fragment load. **/
        protected function _fragmentHandler(event : HLSEvent) : void {
            _level = event.metrics.level;
            sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata:{bandwidth:Math.round(event.metrics.bandwidth / 1024), droppedFrames:_hls.stream.info.droppedFrames, currentLevel:(_level + 1) + ' of ' + _levels.length + ' (' + Math.round(_levels[_level].bitrate / 1024) + 'kbps, ' + _levels[_level].width + 'px)', width:_videoWidth}});
        };

        /** Update video A/R on manifest load. **/
        private function _manifestHandler(event : HLSEvent) : void {
            _levels = event.levels;
            // only report position/duration/buffer for VOD playlist and live playlist with duration > _seekInLiveDurationThreshold
            if (_hls.type == HLSTypes.VOD || _levels[0].duration > _seekInLiveDurationThreshold) {
                item.duration = _levels[0].duration;
            } else {
                item.duration = -1;
            }
            sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_TIME, {position:0, duration:item.duration});
            _hls.addEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler);
            /* start playback on manifest load */
            if (item.start != 0) {
                _hls.stream.seek(item.start);
            } else {
                _hls.stream.play();
            }
        };

        /** Update playback position. **/
        private function _mediaTimeHandler(event : HLSEvent) : void {
            // only report position/duration/buffer for VOD playlist and live playlist with duration > _seekInLiveDurationThreshold
            if (_hls.type == HLSTypes.VOD || event.mediatime.duration > _seekInLiveDurationThreshold) {
                item.duration = event.mediatime.duration;
                _media_position = Math.max(0, event.mediatime.position);
                var _bufferPercent : Number = 100 * (_media_position + event.mediatime.buffer) / event.mediatime.duration;
                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_TIME, {bufferPercent:_bufferPercent, offset:0, position:_media_position, duration:event.mediatime.duration});
            }
            var videoWidth : Number;
            var videoHeight : Number;
            if (_stageVideo) {
                videoWidth = _stageVideo.videoWidth;
                videoHeight = _stageVideo.videoHeight;
            } else {
                videoWidth = _video.videoWidth;
                videoHeight = _video.videoHeight;
            }

            if (videoWidth && videoHeight) {
                if (_videoWidth != videoWidth || _videoHeight != videoHeight) {
                    _videoHeight = videoHeight;
                    _videoWidth = videoWidth;
                    Log.info("video size changed to " + _videoWidth + "/" + _videoHeight);
                    // force resize to adjust video A/R
                    resize(videoWidth, _videoHeight);
                }
            }
        };

        /** Forward state changes from the framework. **/
        private function _stateHandler(event : HLSEvent) : void {
            switch(event.state) {
                case HLSPlayStates.IDLE:
                    setState(PlayerState.IDLE);
                    break;
                case HLSPlayStates.PLAYING_BUFFERING:
                case HLSPlayStates.PAUSED_BUFFERING:
                    setState(PlayerState.BUFFERING);
                    break;
                case HLSPlayStates.PLAYING:
                    _video.visible = true;
                    setState(PlayerState.PLAYING);
                    break;
                case HLSPlayStates.PAUSED:
                    setState(PlayerState.PAUSED);
                    break;
            }
        };

        private function _audioHandler(e : Event) : void {
            media = null;
            // sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_LOADED);
            // dispatchEvent(new MediaEvent(MediaEvent.JWPLAYER_MEDIA_LOADED));
        }

        /** Set the volume on init. **/
        override public function initializeMediaProvider(cfg : PlayerConfig) : void {
            super.initializeMediaProvider(cfg);
            _hls = new HLS();
            _hls.stage = RootReference.stage;
            _hls.stream.soundTransform = new SoundTransform(cfg.volume / 100);
            _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.PLAYBACK_STATE, _stateHandler);
            _hls.addEventListener(HLSEvent.AUDIO_ONLY, _audioHandler);

            // Allow stagevideo to be disabled by user config
            if (cfg.hasOwnProperty('stagevideo') && cfg['stagevideo'].toString() == "false") {
                _stageEnabled = false;
            }
            _video = new Video(320, 240);
            _video.smoothing = true;
            // Use stageVideo when available
            if (_stageEnabled && RootReference.stage.stageVideos.length > 0) {
                _stageVideo = RootReference.stage.stageVideos[0];
                _stageVideo.viewPort = new Rectangle(0, 0, 320, 240);
                _stageVideo.attachNetStream(_hls.stream);
                Log.info("stage video enabled");
            } else {
                _video.attachNetStream(_hls.stream);
            }

            _level = 0;
            var value : Object;

            // parse configuration parameters
            value = cfg.hls_debug;
            if (value != null) {
                Log.info("hls_debug:" + value);
                Log.LOG_DEBUG_ENABLED = value as Boolean;
            }

            value = cfg.hls_debug2;
            if (value != null) {
                Log.info("hls_debug2:" + value);
                Log.LOG_DEBUG2_ENABLED = value as Boolean;
            }

            value = cfg.hls_minbufferlength;
            if (value != null) {
                Log.info("hls_minbufferlength:" + value);
                _hls.minBufferLength = value as Number;
            }

            value = cfg.hls_maxbufferlength;
            if (value != null) {
                Log.info("hls_maxbufferlength:" + value);
                _hls.maxBufferLength = value as Number;
            }

            value = cfg.hls_lowbufferlength;
            if (value != null) {
                Log.info("hls_lowbufferlength:" + value);
                _hls.lowBufferLength = value as Number;
            }

            value = cfg.hls_startfromlowestlevel;
            if (value != null) {
                Log.info("hls_startfromlowestlevel:" + value);
                _hls.startFromLowestLevel = value as Boolean;
            }

            value = cfg.hls_seekfromlowestlevel;
            if (value != null) {
                Log.info("hls_seekfromlowestlevel:" + value);
                _hls.seekFromLowestLevel = value as Boolean;
            }

            value = cfg.hls_live_flushurlcache;
            if (value != null) {
                Log.info("hls_live_flushurlcache:" + value);
                _hls.flushLiveURLCache = value as Boolean;
            }

            value = cfg.hls_live_seekdurationthreshold;
            if (value != null) {
                Log.info("hls_live_seekdurationthreshold:" + value);
                _seekInLiveDurationThreshold = value as Number;
            }

            value = cfg.hls_seekmode;
            if (value != null) {
                Log.info("hls_seekmode:" + value);
                _hls.seekMode = value as String;
            }
            value = cfg.hls_fragmentloadmaxretry;
            if (value != null) {
                Log.info("hls_fragmentloadmaxretry:" + value);
                _hls.fragmentLoadMaxRetry = value as Number;
            }

            value = cfg.hls_manifestloadmaxretry;
            if (value != null) {
                Log.info("hls_manifestloadmaxretry:" + value);
                _hls.manifestLoadMaxRetry = value as Number;
            }

            value = cfg.hls_capleveltostage;
            if (value != null) {
                Log.info("hls_capleveltostage:" + value);
                if (value as Boolean == true) {
                    _hls.capLeveltoStage = true;
                }
            }
            mute(cfg.mute);
        };

        /** Check that Flash Player version is sufficient (10.1 or above) **/
        private function _checkVersion() : Number {
            var versionStr : String = Capabilities.version;
            var verArray : Array = versionStr.split(/\s|,/);
            var versionNum : Number = Number(String(verArray[1] + "." + verArray[2]));
            return versionNum;
        }

        /** Load a new playlist item **/
        override public function load(itm : PlaylistItem) : void {
            // Check flash player version
            var ver : Number = _checkVersion();
            var minVersion : Number = 10.1;
            if ( ver < minVersion ) {
                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_ERROR, {message:"HLS streaming requires Flash Player 10.1 at mimimum"});
            } else {
                super.load(itm);
                play();
            }
        };

        /** Get the video object. **/
        override public function get display() : DisplayObject {
            return _video;
        };

        /** Resume playback of a paused item. **/
        override public function play() : void {
            if (state == PlayerState.PAUSED) {
                _hls.stream.resume();
            } else {
                setState(PlayerState.BUFFERING);
                _hls.load(item.file);
            }
        };

        /** Pause a playing item. **/
        override public function pause() : void {
            _hls.stream.pause();
        };

        /** Do a resize on the video. **/
        override public function resize(width : Number, height : Number) : void {
            Log.info("resize video from [" + _videoWidth + "," + _videoHeight + "]" + "to [" + width + "," + height + "]");
            _width = width;
            _height = height;
            if (_videoWidth && _videoHeight) {
                var rect : Rectangle = ScaleVideo.resizeRectangle(_videoWidth, _videoHeight, width, height);
                if (_stageVideo) {
                    _stageVideo.viewPort = rect;
                } else {
                    _video.x = rect.x;
                    _video.y = rect.y;
                    _video.width = rect.width;
                    _video.height = rect.height;
                }
            }
        };

        /** Seek to a certain position in the item. **/
        override public function seek(pos : Number) : void {
            _hls.stream.seek(pos);
        };

        /** Change the playback volume of the item. **/
        override public function setVolume(vol : Number) : void {
            _hls.stream.soundTransform = new SoundTransform(vol / 100);
            super.setVolume(vol);
        };

        /** Stop playback. **/
        override public function stop() : void {
            _hls.stream.close();
            super.stop();
            _hls.removeEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler);
            _level = 0;
        };
    }
}

package org.mangui.jwplayer.media {
    import org.mangui.HLS.parsing.Level;
    import org.mangui.HLS.*;
    import org.mangui.HLS.utils.Log;
    import org.mangui.HLS.utils.ScaleVideo;

    import com.longtailvideo.jwplayer.events.MediaEvent;
    import com.longtailvideo.jwplayer.model.PlayerConfig;
    import com.longtailvideo.jwplayer.model.PlaylistItem;
    import com.longtailvideo.jwplayer.media.*;
    import com.longtailvideo.jwplayer.player.PlayerState;
    import com.longtailvideo.jwplayer.utils.RootReference;

    import flash.display.DisplayObject;
    import flash.geom.Rectangle;
    import flash.media.SoundTransform;
    import flash.media.Video;
    import flash.media.StageVideo;
    import flash.system.Capabilities;
    import flash.events.Event;

    /** JW Player provider for hls streaming. **/
    public class HLSProvider extends MediaProvider {
        /** Reference to the framework. **/
        protected var _hls : HLS;
        /** Current quality level. **/
        protected var _level : Number;
        /** Reference to the quality levels. **/
        protected var _levels : Vector.<Level>;
        /** Reference to the video object. **/
        private var _video : Video;
        /** Reference to the stage video element. **/
        private var _stageVideo : StageVideo;
        /** Whether or not StageVideo is enabled (not working with JW5) **/
        protected var _stageEnabled : Boolean = false;
        /** current position **/
        protected var _media_position : Number;
        /** Video Original size **/
        private var _videoWidth : Number = 0;
        private var _videoHeight : Number = 0;
        private var _seekInLiveDurationThreshold : Number = 60;

        public function HLSProvider() {
            super('hls');
        };

        /** Forward completes from the framework. **/
        private function _completeHandler(event : HLSEvent) : void {
            complete();
        };

        /** Forward playback errors from the framework. **/
        private function _errorHandler(event : HLSEvent) : void {
            super.error(event.error.msg);
        };

        /** Forward QOS metrics on fragment load. **/
        protected function _fragmentHandler(event : HLSEvent) : void {
            _level = event.metrics.level;
            sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata:{bandwidth:Math.round(event.metrics.bandwidth / 1024), droppedFrames:_hls.stream.info.droppedFrames, currentLevel:(_level + 1) + ' of ' + _levels.length + ' (' + Math.round(_levels[_level].bitrate / 1024) + 'kbps, ' + _levels[_level].width + 'px)', width:_videoWidth}});
        };

        /** Update video A/R on manifest load. **/
        private function _manifestHandler(event : HLSEvent) : void {
            _levels = event.levels;
            // only report position/duration/buffer for VOD playlist and live playlist with duration > _seekInLiveDurationThreshold
            if (_hls.type == HLSTypes.VOD || _levels[0].duration > _seekInLiveDurationThreshold) {
                item.duration = _levels[0].duration;
            } else {
                item.duration = -1;
            }
            sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_TIME, {position:0, duration:item.duration});
            _hls.addEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler);
            /* start playback on manifest load */
            if (item.start != 0) {
                _hls.stream.seek(item.start);
            } else {
                _hls.stream.play();
            }
        };

        /** Update playback position. **/
        private function _mediaTimeHandler(event : HLSEvent) : void {
            // only report position/duration/buffer for VOD playlist and live playlist with duration > _seekInLiveDurationThreshold
            if (_hls.type == HLSTypes.VOD || event.mediatime.duration > _seekInLiveDurationThreshold) {
                item.duration = event.mediatime.duration;
                _media_position = Math.max(0, event.mediatime.position);
                var _bufferPercent : Number = 100 * (_media_position + event.mediatime.buffer) / event.mediatime.duration;
                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_TIME, {bufferPercent:_bufferPercent, offset:0, position:_media_position, duration:event.mediatime.duration});
            }
            var videoWidth : Number;
            var videoHeight : Number;
            if (_stageVideo) {
                videoWidth = _stageVideo.videoWidth;
                videoHeight = _stageVideo.videoHeight;
            } else {
                videoWidth = _video.videoWidth;
                videoHeight = _video.videoHeight;
            }

            if (videoWidth && videoHeight) {
                if (_videoWidth != videoWidth || _videoHeight != videoHeight) {
                    _videoHeight = videoHeight;
                    _videoWidth = videoWidth;
                    Log.info("video size changed to " + _videoWidth + "/" + _videoHeight);
                    // force resize to adjust video A/R
                    resize(videoWidth, _videoHeight);
                }
            }
        };

        /** Forward state changes from the framework. **/
        private function _stateHandler(event : HLSEvent) : void {
            switch(event.state) {
                case HLSPlayStates.IDLE:
                    setState(PlayerState.IDLE);
                    break;
                case HLSPlayStates.PLAYING_BUFFERING:
                case HLSPlayStates.PAUSED_BUFFERING:
                    setState(PlayerState.BUFFERING);
                    break;
                case HLSPlayStates.PLAYING:
                    _video.visible = true;
                    setState(PlayerState.PLAYING);
                    break;
                case HLSPlayStates.PAUSED:
                    setState(PlayerState.PAUSED);
                    break;
            }
        };

        private function _audioHandler(e : Event) : void {
            media = null;
            // sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_LOADED);
            // dispatchEvent(new MediaEvent(MediaEvent.JWPLAYER_MEDIA_LOADED));
        }

        /** Set the volume on init. **/
        override public function initializeMediaProvider(cfg : PlayerConfig) : void {
            super.initializeMediaProvider(cfg);
            _hls = new HLS();
            _hls.stage = RootReference.stage;
            _hls.stream.soundTransform = new SoundTransform(cfg.volume / 100);
            _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.PLAYBACK_STATE, _stateHandler);
            _hls.addEventListener(HLSEvent.AUDIO_ONLY, _audioHandler);

            // Allow stagevideo to be disabled by user config
            if (cfg.hasOwnProperty('stagevideo') && cfg['stagevideo'].toString() == "false") {
                _stageEnabled = false;
            }
            _video = new Video(320, 240);
            _video.smoothing = true;
            // Use stageVideo when available
            if (_stageEnabled && RootReference.stage.stageVideos.length > 0) {
                _stageVideo = RootReference.stage.stageVideos[0];
                _stageVideo.viewPort = new Rectangle(0, 0, 320, 240);
                _stageVideo.attachNetStream(_hls.stream);
                Log.info("stage video enabled");
            } else {
                _video.attachNetStream(_hls.stream);
            }

            _level = 0;
            var value : Object;

            // parse configuration parameters
            value = cfg.hls_debug;
            if (value != null) {
                Log.info("hls_debug:" + value);
                Log.LOG_DEBUG_ENABLED = value as Boolean;
            }

            value = cfg.hls_debug2;
            if (value != null) {
                Log.info("hls_debug2:" + value);
                Log.LOG_DEBUG2_ENABLED = value as Boolean;
            }

            value = cfg.hls_minbufferlength;
            if (value != null) {
                Log.info("hls_minbufferlength:" + value);
                _hls.minBufferLength = value as Number;
            }

            value = cfg.hls_maxbufferlength;
            if (value != null) {
                Log.info("hls_maxbufferlength:" + value);
                _hls.maxBufferLength = value as Number;
            }

            value = cfg.hls_lowbufferlength;
            if (value != null) {
                Log.info("hls_lowbufferlength:" + value);
                _hls.lowBufferLength = value as Number;
            }

            value = cfg.hls_startfromlowestlevel;
            if (value != null) {
                Log.info("hls_startfromlowestlevel:" + value);
                _hls.startFromLowestLevel = value as Boolean;
            }

            value = cfg.hls_seekfromlowestlevel;
            if (value != null) {
                Log.info("hls_seekfromlowestlevel:" + value);
                _hls.seekFromLowestLevel = value as Boolean;
            }

            value = cfg.hls_live_flushurlcache;
            if (value != null) {
                Log.info("hls_live_flushurlcache:" + value);
                _hls.flushLiveURLCache = value as Boolean;
            }

            value = cfg.hls_live_seekdurationthreshold;
            if (value != null) {
                Log.info("hls_live_seekdurationthreshold:" + value);
                _seekInLiveDurationThreshold = value as Number;
            }

            value = cfg.hls_seekmode;
            if (value != null) {
                Log.info("hls_seekmode:" + value);
                _hls.seekMode = value as String;
            }
            value = cfg.hls_fragmentloadmaxretry;
            if (value != null) {
                Log.info("hls_fragmentloadmaxretry:" + value);
                _hls.fragmentLoadMaxRetry = value as Number;
            }

            value = cfg.hls_manifestloadmaxretry;
            if (value != null) {
                Log.info("hls_manifestloadmaxretry:" + value);
                _hls.manifestLoadMaxRetry = value as Number;
            }

            value = cfg.hls_capleveltostage;
            if (value != null) {
                Log.info("hls_capleveltostage:" + value);
                if (value as Boolean == true) {
                    _hls.capLeveltoStage = true;
                }
            }
            mute(cfg.mute);
        };

        /** Check that Flash Player version is sufficient (10.1 or above) **/
        private function _checkVersion() : Number {
            var versionStr : String = Capabilities.version;
            var verArray : Array = versionStr.split(/\s|,/);
            var versionNum : Number = Number(String(verArray[1] + "." + verArray[2]));
            return versionNum;
        }

        /** Load a new playlist item **/
        override public function load(itm : PlaylistItem) : void {
            // Check flash player version
            var ver : Number = _checkVersion();
            var minVersion : Number = 11.6;
            if ( ver < minVersion ) {
                sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_ERROR, {message:"This application requires Flash Player 11.6 at mimimum"});
            } else {
                super.load(itm);
                play();
            }
        };

        /** Get the video object. **/
        override public function get display() : DisplayObject {
            return _video;
        };

		public override function getRawMedia():DisplayObject
		{
			return display;

		}

        /** Resume playback of a paused item. **/
        override public function play() : void {
            if (state == PlayerState.PAUSED) {
                _hls.stream.resume();
            } else {
                setState(PlayerState.BUFFERING);
                _hls.load(item.file);
            }
        };

        /** Pause a playing item. **/
        override public function pause() : void {
            _hls.stream.pause();
        };

        /** Do a resize on the video. **/
        override public function resize(width : Number, height : Number) : void {
            Log.info("resize video from [" + _videoWidth + "," + _videoHeight + "]" + "to [" + width + "," + height + "]");
            _width = width;
            _height = height;
            if (_videoWidth && _videoHeight) {
                var rect : Rectangle = ScaleVideo.resizeRectangle(_videoWidth, _videoHeight, width, height);
                if (_stageVideo) {
                    _stageVideo.viewPort = rect;
                } else {
                    _video.x = rect.x;
                    _video.y = rect.y;
                    _video.width = rect.width;
                    _video.height = rect.height;
                }
            }
        };

        /** Seek to a certain position in the item. **/
        override public function seek(pos : Number) : void {
            _hls.stream.seek(pos);
        };

        /** Change the playback volume of the item. **/
        override public function setVolume(vol : Number) : void {
            _hls.stream.soundTransform = new SoundTransform(vol / 100);
            super.setVolume(vol);
        };

        /** Stop playback. **/
        override public function stop() : void {
            _hls.stream.close();
            super.stop();
            _hls.removeEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler);
            _level = 0;
        };
    }
}

Add missing getRawMedia overriding super method.