package aerys.minko.scene.node.mesh
{
	import aerys.minko.render.effect.Effect;
	import aerys.minko.render.effect.basic.BasicShader;
	import aerys.minko.scene.controller.AbstractController;
	import aerys.minko.scene.controller.mesh.MeshVisibilityController;
	import aerys.minko.scene.node.AbstractSceneNode;
	import aerys.minko.scene.node.ISceneNode;
	import aerys.minko.scene.node.Scene;
	import aerys.minko.scene.node.mesh.geometry.Geometry;
	import aerys.minko.type.Signal;
	import aerys.minko.type.bounding.FrustumCulling;
	import aerys.minko.type.data.DataBindings;
	import aerys.minko.type.data.DataProvider;
	import aerys.minko.type.enum.DataProviderUsage;

	/**
	 * Mesh objects are a visible instance of a Geometry rendered using a specific
	 * Effect with specific rendering properties.
	 *
	 *

	 * Those rendering properties are stored in a DataBindings object so they can
	 * be directly used by the shaders in the rendering API.
	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Mesh extends AbstractSceneNode
	{
		public static const DEFAULT_EFFECT	: Effect	= new Effect(
			new BasicShader()
		);

		private var _geometry			: Geometry					= null;
		private var _effect				: Effect					= null;
		private var _properties			: DataProvider				= null;
		private var _material			: DataProvider				= null;
		private var _bindings			: DataBindings				= null;

		private var _visibility			: MeshVisibilityController	= new MeshVisibilityController();

		private var _frame				: uint						= 0;

		private var _cloned				: Signal 					= new Signal('Mesh.clones');
		private var _effectChanged		: Signal					= new Signal('Mesh.effectChanged');
		private var _frameChanged		: Signal					= new Signal('Mesh.frameChanged');
		private var _geometryChanged	: Signal					= new Signal('Mesh.geometryChanged');

		/**
		 * A DataProvider object already bound to the Mesh bindings.
		 *
		 *

		 * // set the "diffuseColor" property to 0x0000ffff
		 * mesh.properties.diffuseColor = 0x0000ffff;
		 *
		 * // animate the "diffuseColor" property
		 * mesh.addController(
		 *   new AnimationController(
		 * 	  new <ITimeline>[new ColorTimeline(
		 * 	    "dataProvider.diffuseColor",
		 * 	    5000,
		 * 	    new <uint>[0xffffffff, 0xffffff00, 0xffffffff]
		 *    )]
		 *   )
		 * );
		 *

		 *
		 * @return
		 *
		 */
		public function get properties() : DataProvider
		{
			return _properties;
		}

		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get material() : DataProvider
		{
			return _material;
		}
		public function set material(value : DataProvider) : void
		{
			if (_material != value)
			{
				if (_material)
					_bindings.removeProvider(_material);

				_material = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		/**
		 * The rendering properties provided to the shaders to customize
		 * how the mesh will appear on screen.
		 *
		 * @return
		 *
		 */
		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The Effect used for rendering.
		 * @return
		 *
		 */
		public function get effect() : Effect
		{
			return _effect;
		}

		public function set effect(value : Effect) : void
		{
			if (_effect == value)
				return ;

			if (value == null)
				throw new Error();

			var oldEffect : Effect = _effect;

			_effect = value;

			_effectChanged.execute(this, oldEffect, value);
		}

		/**
		 * The Geometry of the mesh.
		 * @return
		 *
		 */
		public function get geometry() : Geometry
		{
			return _geometry;
		}

		public function set geometry(value : Geometry) : void
		{
			if (_geometry != value)
			{
				var oldGeometry	: Geometry = _geometry;

				_geometry = value;
				_geometryChanged.execute(this, oldGeometry, value);
			}
		}

		/**
		 * Whether the mesh is visible or not.
		 *
		 * @return
		 *
		 */
		public function get visibility() : MeshVisibilityController
		{
			return _visibility;
		}

		public function get cloned() : Signal
		{
			return _cloned;
		}

		public function get effectChanged() : Signal
		{
			return _effectChanged;
		}

		public function get frameChanged() : Signal
		{
			return _frameChanged;
		}

		public function get geometryChanged() : Signal
		{
			return _geometryChanged;
		}

		public function get frame() : uint
		{
			return _frame;
		}
		public function set frame(value : uint) : void
		{
			if (_frame != value)
			{
				var oldFrame : uint = _frame;

				_frame = value;
				_frameChanged.execute(this, oldFrame, value);
			}
		}

		public function Mesh(geometry	: Geometry	= null,
							 properties	: Object	= null,
							 effect		: Effect	= null,
							 ...controllers)
		{
			super();

			initialize(geometry, properties, effect, controllers);
		}

		private function initialize(geometry	: Geometry,
									properties	: Object,
									effect		: Effect,
									controllers	: Array) : void
		{
			this.properties = new DataProvider(properties, 'meshProperties', DataProviderUsage.EXCLUSIVE);

			_bindings = new DataBindings(this);

			_geometry = geometry;
			this.effect = effect || DEFAULT_EFFECT;

			_visibility.frustumCulling = FrustumCulling.ENABLED;
			addController(_visibility);

			while (controllers && !(controllers[0] is AbstractController))
				controllers = controllers[0];

			if (controllers)
				for each (var ctrl : AbstractController in controllers)
					addController(ctrl);
		}

		override public function clone(cloneControllers : Boolean = false) : ISceneNode
		{
			var clone : Mesh = new Mesh();

			clone.copyFrom(this, true, cloneControllers);

			return clone;
		}

		override protected function addedToSceneHandler(child : ISceneNode, scene : Scene) : void
		{
			super.addedToSceneHandler(child, scene);

			if (child === this)
				_bindings.addProvider(transformData);
		}

		override protected function removedFromSceneHandler(child : ISceneNode, scene : Scene) : void
		{
			super.removedFromSceneHandler(child, scene);

			if (child === this)
				_bindings.removeProvider(transformData);
		}

		protected function copyFrom(source 				: Mesh,
									withBindings 		: Boolean,
									cloneControllers 	: Boolean) : void
		{
			var numControllers : uint = source.numControllers;

			name 		= source.name;

			geometry 	= source._geometry;
			properties	= DataProvider(source._properties.clone());

			_visibility = source._visibility.clone() as MeshVisibilityController;

			_bindings.copySharedProvidersFrom(source._bindings);

			copyControllersFrom(source, this, cloneControllers);
			transform.copyFrom(source.transform);
			effect = source._effect;

			source.cloned.execute(this, source);
		}
	}
}

package aerys.minko.scene.node.mesh
{
	import aerys.minko.render.effect.Effect;
	import aerys.minko.render.effect.basic.BasicShader;
	import aerys.minko.scene.controller.AbstractController;
	import aerys.minko.scene.controller.mesh.MeshVisibilityController;
	import aerys.minko.scene.node.AbstractSceneNode;
	import aerys.minko.scene.node.ISceneNode;
	import aerys.minko.scene.node.Scene;
	import aerys.minko.scene.node.mesh.geometry.Geometry;
	import aerys.minko.type.Signal;
	import aerys.minko.type.bounding.FrustumCulling;
	import aerys.minko.type.data.DataBindings;
	import aerys.minko.type.data.DataProvider;
	import aerys.minko.type.enum.DataProviderUsage;

	/**
	 * Mesh objects are a visible instance of a Geometry rendered using a specific
	 * Effect with specific rendering properties.
	 *
	 *

	 * Those rendering properties are stored in a DataBindings object so they can
	 * be directly used by the shaders in the rendering API.
	 *

	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public class Mesh extends AbstractSceneNode
	{
		public static const DEFAULT_EFFECT	: Effect	= new Effect(
			new BasicShader()
		);

		private var _geometry			: Geometry					= null;
		private var _effect				: Effect					= null;
		private var _properties			: DataProvider				= null;
		private var _material			: DataProvider				= null;
		private var _bindings			: DataBindings				= null;

		private var _visibility			: MeshVisibilityController	= new MeshVisibilityController();

		private var _frame				: uint						= 0;

		private var _cloned				: Signal 					= new Signal('Mesh.clones');
		private var _effectChanged		: Signal					= new Signal('Mesh.effectChanged');
		private var _frameChanged		: Signal					= new Signal('Mesh.frameChanged');
		private var _geometryChanged	: Signal					= new Signal('Mesh.geometryChanged');

		/**
		 * A DataProvider object already bound to the Mesh bindings.
		 *
		 *

		 * // set the "diffuseColor" property to 0x0000ffff
		 * mesh.properties.diffuseColor = 0x0000ffff;
		 *
		 * // animate the "diffuseColor" property
		 * mesh.addController(
		 *   new AnimationController(
		 * 	  new <ITimeline>[new ColorTimeline(
		 * 	    "dataProvider.diffuseColor",
		 * 	    5000,
		 * 	    new <uint>[0xffffffff, 0xffffff00, 0xffffffff]
		 *    )]
		 *   )
		 * );
		 *

		 *
		 * @return
		 *
		 */
		public function get properties() : DataProvider
		{
			return _properties;
		}

		public function set properties(value : DataProvider) : void
		{
			if (_properties != value)
			{
				if (_properties)
					_bindings.removeProvider(_properties);

				_properties = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		public function get material() : DataProvider
		{
			return _material;
		}
		public function set material(value : DataProvider) : void
		{
			if (_material != value)
			{
				if (_material)
					_bindings.removeProvider(_material);

				_material = value;

				if (value)
					_bindings.addProvider(value);
			}
		}

		/**
		 * The rendering properties provided to the shaders to customize
		 * how the mesh will appear on screen.
		 *
		 * @return
		 *
		 */
		public function get bindings() : DataBindings
		{
			return _bindings;
		}

		/**
		 * The Effect used for rendering.
		 * @return
		 *
		 */
		public function get effect() : Effect
		{
			return _effect;
		}

		public function set effect(value : Effect) : void
		{
			if (_effect == value)
				return ;

			if (value == null)
				throw new Error();

			var oldEffect : Effect = _effect;

			_effect = value;

			_effectChanged.execute(this, oldEffect, value);
		}

		/**
		 * The Geometry of the mesh.
		 * @return
		 *
		 */
		public function get geometry() : Geometry
		{
			return _geometry;
		}

		public function set geometry(value : Geometry) : void
		{
			if (_geometry != value)
			{
				var oldGeometry	: Geometry = _geometry;

				_geometry = value;
				_geometryChanged.execute(this, oldGeometry, value);
			}
		}

		/**
		 * Whether the mesh is visible or not.
		 *
		 * @return
		 *
		 */
		public function get visibility() : MeshVisibilityController
		{
			return _visibility;
		}

		public function get cloned() : Signal
		{
			return _cloned;
		}

		public function get effectChanged() : Signal
		{
			return _effectChanged;
		}

		public function get frameChanged() : Signal
		{
			return _frameChanged;
		}

		public function get geometryChanged() : Signal
		{
			return _geometryChanged;
		}

		public function get frame() : uint
		{
			return _frame;
		}
		public function set frame(value : uint) : void
		{
			if (_frame != value)
			{
				var oldFrame : uint = _frame;

				_frame = value;
				_frameChanged.execute(this, oldFrame, value);
			}
		}

		public function Mesh(geometry	: Geometry	= null,
							 properties	: Object	= null,
							 effect		: Effect	= null,
							 ...controllers)
		{
			super();

			initialize(geometry, properties, effect, controllers);
		}

		private function initialize(geometry	: Geometry,
									properties	: Object,
									effect		: Effect,
									controllers	: Array) : void
		{
			_bindings = new DataBindings(this);

			this.properties = new DataProvider(properties, 'meshProperties', DataProviderUsage.EXCLUSIVE);

			_geometry = geometry;
			this.effect = effect || DEFAULT_EFFECT;

			_visibility.frustumCulling = FrustumCulling.ENABLED;
			addController(_visibility);

			while (controllers && !(controllers[0] is AbstractController))
				controllers = controllers[0];

			if (controllers)
				for each (var ctrl : AbstractController in controllers)
					addController(ctrl);
		}

		override public function clone(cloneControllers : Boolean = false) : ISceneNode
		{
			var clone : Mesh = new Mesh();

			clone.copyFrom(this, true, cloneControllers);

			return clone;
		}

		override protected function addedToSceneHandler(child : ISceneNode, scene : Scene) : void
		{
			super.addedToSceneHandler(child, scene);

			if (child === this)
				_bindings.addProvider(transformData);
		}

		override protected function removedFromSceneHandler(child : ISceneNode, scene : Scene) : void
		{
			super.removedFromSceneHandler(child, scene);

			if (child === this)
				_bindings.removeProvider(transformData);
		}

		protected function copyFrom(source 				: Mesh,
									withBindings 		: Boolean,
									cloneControllers 	: Boolean) : void
		{
			var numControllers : uint = source.numControllers;

			name 		= source.name;

			geometry 	= source._geometry;
			properties	= DataProvider(source._properties.clone());

			_visibility = source._visibility.clone() as MeshVisibilityController;

			_bindings.copySharedProvidersFrom(source._bindings);

			copyControllersFrom(source, this, cloneControllers);
			transform.copyFrom(source.transform);
			effect = source._effect;

			source.cloned.execute(this, source);
		}
	}
}

Fix binding instanciation order.

Fix binding instanciation order.


package corsaair.tool.hash
{
    import C.stdlib.*;

    import cli.args.*;

    import encoding.ansi.AnsiString;

    import flash.utils.ByteArray;

    import hash.ap;
    import hash.bkdr;
    import hash.brp;
    import hash.dek;
    import hash.djb;
    import hash.elf;
    import hash.fnv;
    import hash.js;
    import hash.pjw;
    import hash.rs;
    import hash.sdbm;

    import shell.FileSystem;

	public class App
	{

        private var _parser:ArgParser;
        private var _results:ArgResults;

        public var executableName:String;
        public var description:String;

		public function App()
		{
			super();
            _ctor();
		}

        private function _ctor():void
        {
            _parser  = new ArgParser();
            _parser.addFlag( "DEBUG", "D", "Debugging", false, false, null, true );
            _parser.addFlag( "help", "h", "Print this usage information.", false, false );
            _parser.addFlag( "verbose", "v", "Show additional diagnostic informations.", false, false );
            _parser.addOption( "hash", "a", "Hashing function used",
                               "",
                               [ "ap", "bkdr", "brp", "dek", "djb", "elf", "fnv", "js", "pjw", "rs", "sdbm" ],
                               { ap:   "Arash Partow hash function",
                                 bkdr: "Brian Kernighan and Dennis Ritchie hash function",
                                 brp:  "Bruno R. Preiss hash function",
                                 dek:  "Donald E. Knuth hash function",
                                 djb:  "Professor Daniel J. Bernstein hash function",
                                 elf:  "ELF hash function",
                                 fnv:  "Fowler–Noll–Vo hash function",
                                 js:   "Justin Sobel hash function",
                                 pjw:  "Peter J. Weinberger hash function",
                                 rs:   "Robert Sedgwicks hash function",
                                 sdbm: "open source SDBM project hash function"
                               },
                               "ap" );
            _parser.addOption( "format", "f", "Output format used",
                               "",
                               [ "hex", "num" ],
                               { hex: "hexadecimal",
                                 num: "numeric"
                               },
                               "hex" );
            _parser.addOption( "color", "c", "Output color",
                               "",
                               [ "none", "red", "green", "blue" ],
                               { none:  "no color",
                                 red:   "red color",
                                 green: "green color",
                                 blue:  "blue color"
                               },
                               "none" );

            executableName = "as3hash";
            description    = "Multiple hashing functions.";
        }

        private function _uintToHex( n:uint ):String
        {
            var hex:String = n.toString( 16 );
            if( hex.length%2 != 0 ) { hex = "0" + hex; }
            return hex;
        }

        public function showUsage( message:String = "" ):void
        {
            trace( executableName + " - " + description + "\n" );
            if( message != "" )
            {
                trace( message );
            }
            trace( "Usage: "  );
            trace( _parser.usage );
        }

        public function main( argv:Array = null ):void
        {
            if( (argv == null) || (argv && argv.length == 0) )
            {
                showUsage();
                exit( EXIT_FAILURE );
            }

            try
            {
                _results = _parser.parse( argv );
            }
            catch( e:SyntaxError )
            {
                showUsage( e.message );
                exit( EXIT_FAILURE );
            }

            if( _results[ "DEBUG" ] )
            {
                trace( "" );
                trace( JSON.stringify( _results, null, "  " ) );
                trace( "" );
                trace( "   help = " + _results[ "help" ] );
                trace( "verbose = " + _results[ "verbose" ] );
                trace( "   hash = " + _results[ "hash" ] );
                trace( " format = " + _results[ "format" ] );
                trace( "  color = " + _results[ "color" ] );
                trace( " string = " + _results.rest[0] );
            }

            if( _results.options[ "help" ] == true )
            {
                showUsage();
            }
            else
            {
                var str:String = "";
                var type:String;

                var tmp:String = _results.rest.join( " " );
                if( tmp )
                {
                    str = tmp;
                }

                if( _results[ "DEBUG" ] )
                {
                    trace( " str = " + str );
                }

                var bytes:ByteArray = new ByteArray();

                if( (str != "") && FileSystem.exists( str ) )
                {
                    bytes = FileSystem.readByteArray( str );
                    type = "file";
                }
                else
                {
                    bytes.writeUTFBytes( str );
                    type = "string";
                }
                bytes.position = 0;

                var hash:uint = 0;

                switch( _results[ "hash" ] )
                {
                    case "ap":
                    hash = ap( bytes );
                    break;

                    case "bkdr":
                    hash = bkdr( bytes );
                    break;

                    case "brp":
                    hash = brp( bytes );
                    break;

                    case "dek":
                    hash = dek( bytes );
                    break;

                    case "djb":
                    hash = djb( bytes );
                    break;

                    case "elf":
                    hash = elf( bytes );
                    break;

                    case "fnv":
                    hash = fnv( bytes );
                    break;

                    case "js":
                    hash = js( bytes );
                    break;

                    case "pjw":
                    hash = pjw( bytes );
                    break;

                    case "rs":
                    hash = rs( bytes );
                    break;

                    case "sdbm":
                    hash = sdbm( bytes );
                    break;
                }

                if( _results[ "DEBUG" ] )
                {
                    trace( " hash = " + hash );
                }

                var result:String = "";
                switch( _results[ "format" ] )
                {
                    case "num":
                    result = String( hash );
                    break;

                    case "hex":
                    result = _uintToHex( hash );
                    break;
                }

                switch( _results[ "color" ] )
                {
                    case "red":
                    result += "「R! 」";
                    break;

                    case "green":
                    result += "「G! 」";
                    break;

                    case "blue":
                    result += "「B! 」";
                    break;

                    case "none":
                    default:
                    // nothing
                }

                if( _results[ "color" ] != "none" )
                {
                    var ansi:AnsiString = new AnsiString( result );
                    result = ansi.toString();
                }

                if( _results[ "verbose" ] )
                {
                    var pre:String = _results[ "hash" ];
                    var sep:String = ":";
                    var post:String = type;

                    if( _results[ "color" ] != "none" )
                    {
                        var tmp1:AnsiString = new AnsiString( pre + "「W! 」" );
                        pre = tmp1.toString();

                        var tmp2:AnsiString = new AnsiString( sep + "「K! 」" );
                        sep = tmp2.toString();

                        var tmp3:AnsiString = new AnsiString( post + "「Y! 」" );
                        post = tmp3.toString();
                    }

                    trace( pre + sep + result + sep + post );
                }
                else
                {
                    trace( result );
                }
            }

            exit( EXIT_SUCCESS );
        }

	}

}

update indentation

update indentation

git-svn-id: 533dbd50173d42a8a7a6f488dbc0c05430609410@11 37abe446-e973-4b93-b0d7-31cb093a2758


package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.scene.SceneIterator;
	import aerys.minko.scene.controller.AbstractController;
	import aerys.minko.type.Signal;
	import aerys.minko.type.Sort;
	import aerys.minko.type.loader.ILoader;
	import aerys.minko.type.loader.SceneLoader;
	import aerys.minko.type.loader.parser.ParserOptions;
	import aerys.minko.type.math.Matrix4x4;
	import aerys.minko.type.math.Ray;

	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;
	import flash.utils.getQualifiedClassName;

	use namespace minko_scene;

	/**
	 * Group objects can contain other scene nodes and applies a 3D
	 * transformation to its descendants.
	 *
	 * @author Jean-Marc Le Roux
	 */
	public class Group extends AbstractSceneNode
	{
		minko_scene var _children		: Vector.<ISceneNode>	= null;
		minko_scene var _numChildren	: uint					= 0;

		private var _numDescendants		: uint					= 0;

		private var _descendantAdded	: Signal				= new Signal('Group.descendantAdded');
		private var _descendantRemoved	: Signal				= new Signal('Group.descendantRemoved');

		/**
		 * The number of children of the Group.
		 */
		public function get numChildren() : uint
		{
			return _numChildren;
		}

		/**
		 * The number of descendants of the Group.
		 *
		 * @return
		 *
		 */
		public function get numDescendants() : uint
		{
			return _numDescendants;
		}

		/**
		 * The signal executed when a descendant is added to the Group.
		 * Callbacks for this signal must accept the following arguments:
		 *

		 *
newParent : Group, the Group the descendant was actually added to

		 *
descendant : ISceneNode, the descendant that was just added

		 *

		 *
		 * @return
		 *
		 */
		public function get descendantAdded() : Signal
		{
			return _descendantAdded
		}

		/**
		 * The signal executed when a descendant is removed from the Group.
		 * Callbacks for this signal must accept the following arguments:
		 *

		 *
oldParent : Group, the Group the descendant was actually removed from

		 *
descendant : ISceneNode, the descendant that was just removed

		 *

		 *
		 * @return
		 *
		 */
		public function get descendantRemoved() : Signal
		{
			return _descendantRemoved;
		}

		public function Group(...children)
		{
			super();

			initialize();
			initializeChildren(children);
		}

		private function initialize() : void
		{
			_children = new <ISceneNode>[];

			descendantAdded.add(descendantAddedHandler);
			descendantRemoved.add(descendantRemovedHandler);
		}

		protected function initializeChildren(children : Array) : void
		{
			while (children.length == 1 && children[0] is Array)
				children = children[0];

			var childrenNum : uint = children.length;

			for (var childrenIndex : uint = 0; childrenIndex < childrenNum; ++childrenIndex)
				addChild(ISceneNode(children[childrenIndex]));
		}

//		override protected function addedHandler(child : ISceneNode, parent : Group) : void
//		{
//			super.addedHandler(child, parent);
//
//			for (var childIndex : int = 0; childIndex < _numChildren; ++childIndex)
//				_children[childIndex].added.execute(child, parent);
//		}
//
//		override protected function removedHandler(child : ISceneNode, parent : Group) : void
//		{
//			super.removedHandler(child, parent);
//
//			for (var childIndex : int = 0; childIndex < _numChildren; ++childIndex)
//				_children[childIndex].removed.execute(child, parent);
//		}

		private function descendantAddedHandler(group : Group, child : ISceneNode) : void
		{
			if (group == this)
			{
				var childGroup : Group = child as Group;

				if (childGroup)
				{
					childGroup.descendantAdded.add(_descendantAdded.execute);
					childGroup.descendantRemoved.add(_descendantRemoved.execute);
				}
			}

			_numDescendants += (child is Group) ? (child as Group)._numDescendants + 1 : 1;
		}

		private function descendantRemovedHandler(group : Group, child : ISceneNode) : void
		{
			if (group == this)
			{
				var childGroup : Group = child as Group;

				if (childGroup)
				{
					childGroup.descendantAdded.remove(_descendantAdded.execute);
					childGroup.descendantRemoved.remove(_descendantRemoved.execute);
				}
			}

			_numDescendants -= (child is Group) ? (child as Group)._numDescendants + 1 : 1;
		}

		/**
		 * Return true if the specified scene node is a child of the Group, false otherwise.
		 *
		 * @param scene
		 * @return
		 *
		 */
		public function contains(scene : ISceneNode) : Boolean
		{
			return getChildIndex(scene) >= 0;
		}

		/**
		 * Return the index of the speficied scene node or -1 if it is not in the Group.
		 *
		 * @param child
		 * @return
		 *
		 */
		public function getChildIndex(child : ISceneNode) : int
		{
			if (child == null)
				throw new Error('The \'child\' parameter cannot be null.');

			for (var i : int = 0; i < _numChildren; i++)
				if (_children[i] === child)
					return i;

			return -1;
		}

		public function getChildByName(name : String) : ISceneNode
		{
			for (var i : int = 0; i < _numChildren; i++)
				if (_children[i].name === name)
					return _children[i];

			return null;
		}

		/**
		 * Add a child to the group.
		 *
		 * @param	scene The child to add.
		 */
		public function addChild(node : ISceneNode) : Group
		{
			return addChildAt(node, _numChildren);
		}

		/**
		 * Add a child to the group at the specified position.
		 *
		 * @param node
		 * @param position
		 * @return
		 *
		 */
		public function addChildAt(node : ISceneNode, position : uint) : Group
		{
			if (!node)
				throw new Error('Parameter \'scene\' must not be null.');

			node.parent = this;

			for (var i : int = _numChildren - 1; i > position; --i)
				_children[i] = _children[int(i - 1)];

			_children[position] = node;

			return this;
		}

		/**
		 * Remove a child from the container.
		 *
		 * @param	myChild The child to remove.
		 * @return Whether the child was actually removed or not.
		 */
		public function removeChild(child : ISceneNode) : Group
		{
			return removeChildAt(getChildIndex(child));
		}

		public function removeChildAt(position : uint) : Group
		{
			if (position >= _numChildren || position < 0)
				throw new Error('The scene node is not a child of the caller.');

			(_children[position] as ISceneNode).parent = null;

			return this;
		}

		/**
		 * Remove all the children.
		 *
		 * @return
		 *
		 */
		public function removeAllChildren() : Group
		{
			while (_numChildren)
				removeChildAt(0);

			return this;
		}

		/**
		 * Return the child at the specified position.
		 *
		 * @param position
		 * @return
		 *
		 */
		public function getChildAt(position : uint) : ISceneNode
		{
			return position < _numChildren ? _children[position] : null;
		}

		/**
		 * Returns the list of descendant scene nodes that have the specified type.
		 *
		 * @param type
		 * @param descendants
		 * @return
		 *
		 */
		public function getDescendantsByType(type 			: Class,
											 descendants 	: Vector.<ISceneNode> = null) : Vector.<ISceneNode>
		{
			descendants ||= new Vector.<ISceneNode>();

			for (var i : int = 0; i < _numChildren; ++i)
			{
				var child	: ISceneNode	= _children[i];
				var group 	: Group 		= child as Group;

				if (child is type)
					descendants.push(child);

				if (group)
					group.getDescendantsByType(type, descendants);
			}

			return descendants;
		}

		public function toString() : String
		{
			return '[' + getQualifiedClassName(this) + ' ' + name + ']';
		}

		/**
		 * Load the 3D scene corresponding to the specified URLRequest object
		 * and add it directly to the group.
		 *
		 * @param request
		 * @param options
		 * @return
		 *
		 */
		public function load(request	: URLRequest,
							 options	: ParserOptions	= null) : ILoader
		{
			var loader	: SceneLoader	= new SceneLoader(options);

			loader.complete.add(loaderCompleteHandler);
			loader.load(request);

			return loader;
		}

		/**
		 * Load the 3D scene corresponding to the specified Class object
		 * and add it directly to the group.
		 *
		 * @param classObject
		 * @param options
		 * @return
		 */
		public function loadClass(classObject	: Class,
								  options		: ParserOptions	= null) : SceneLoader
		{
			var loader : SceneLoader = new SceneLoader(options);

			loader.complete.add(loaderCompleteHandler);
			loader.loadClass(classObject);

			return loader;
		}

		/**
		 * Load the 3D scene corresponding to the specified ByteArray object
		 * and add it directly to the group.
		 *
		 * @param bytes
		 * @param options
		 * @return
		 *
		 */
		public function loadBytes(bytes		: ByteArray,
								  options	: ParserOptions	= null) : ILoader
		{
			var loader	: SceneLoader	= new SceneLoader(options);

			loader.complete.add(loaderCompleteHandler);
			loader.loadBytes(bytes);

			return loader;
		}

		/**
		 * Return the set of nodes matching the specified XPath query.
		 *
		 * @param xpath
		 * @return
		 *
		 */
		public function get(xpath : String) : SceneIterator
		{
			return new SceneIterator(xpath, new <ISceneNode>[this]);
		}

		private function loaderCompleteHandler(loader	: ILoader,
											   scene	: ISceneNode) : void
		{
			addChild(scene);
		}

		/**
		 * Return all the Mesh objects hit by the specified ray.
		 *
		 * @param ray
		 * @param maxDistance
		 * @return
		 *
		 */
		public function cast(ray : Ray, maxDistance : Number = Number.POSITIVE_INFINITY) : SceneIterator
		{
			var meshes		: Vector.<ISceneNode> 	= getDescendantsByType(Mesh);
			var numMeshes	: uint					= meshes.length;
			var hit			: Array					= [];
			var depth		: Vector.<Number>		= new <Number>[];
			var numItems	: uint					= 0;

			for (var i : uint = 0; i < numMeshes; ++i)
			{
				var mesh 		: Mesh		= meshes[i] as Mesh;
				var hitDepth	: Number	= mesh.cast(ray, maxDistance);

				if (hitDepth >= 0.0)
				{
					hit[numItems] = mesh;
					depth[numItems] = hitDepth;
					++numItems;
				}
			}

			if (numItems > 1)
				Sort.flashSort(depth, hit, numItems);

			return new SceneIterator(null, Vector.<ISceneNode>(hit));
		}

		override minko_scene function cloneNode() : AbstractSceneNode
		{
			var clone : Group = new Group();

			clone.name = name;
			clone.transform.copyFrom(transform);

			for (var childId : uint = 0; childId < _numChildren; ++childId)
			{
				var child		: AbstractSceneNode = AbstractSceneNode(_children[childId]);
				var clonedChild	: AbstractSceneNode = AbstractSceneNode(child.cloneNode());

				clone.addChild(clonedChild);
			}

			return clone;
		}
	}
}

package aerys.minko.scene.node
{
	import aerys.minko.ns.minko_scene;
	import aerys.minko.scene.SceneIterator;
	import aerys.minko.scene.controller.AbstractController;
	import aerys.minko.type.Signal;
	import aerys.minko.type.Sort;
	import aerys.minko.type.loader.ILoader;
	import aerys.minko.type.loader.SceneLoader;
	import aerys.minko.type.loader.parser.ParserOptions;
	import aerys.minko.type.math.Matrix4x4;
	import aerys.minko.type.math.Ray;

	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;
	import flash.utils.getQualifiedClassName;

	use namespace minko_scene;

	/**
	 * Group objects can contain other scene nodes and applies a 3D
	 * transformation to its descendants.
	 *
	 * @author Jean-Marc Le Roux
	 */
	public class Group extends AbstractSceneNode
	{
		minko_scene var _children		: Vector.<ISceneNode>	= null;
		minko_scene var _numChildren	: uint					= 0;

		private var _numDescendants		: uint					= 0;

		private var _descendantAdded	: Signal				= new Signal('Group.descendantAdded');
		private var _descendantRemoved	: Signal				= new Signal('Group.descendantRemoved');

		/**
		 * The number of children of the Group.
		 */
		public function get numChildren() : uint
		{
			return _numChildren;
		}

		/**
		 * The number of descendants of the Group.
		 *
		 * @return
		 *
		 */
		public function get numDescendants() : uint
		{
			return _numDescendants;
		}

		/**
		 * The signal executed when a descendant is added to the Group.
		 * Callbacks for this signal must accept the following arguments:
		 *

		 *
newParent : Group, the Group the descendant was actually added to

		 *
descendant : ISceneNode, the descendant that was just added

		 *

		 *
		 * @return
		 *
		 */
		public function get descendantAdded() : Signal
		{
			return _descendantAdded
		}

		/**
		 * The signal executed when a descendant is removed from the Group.
		 * Callbacks for this signal must accept the following arguments:
		 *

		 *
oldParent : Group, the Group the descendant was actually removed from

		 *
descendant : ISceneNode, the descendant that was just removed

		 *

		 *
		 * @return
		 *
		 */
		public function get descendantRemoved() : Signal
		{
			return _descendantRemoved;
		}

		public function Group(...children)
		{
			super();

			initialize();
			initializeChildren(children);
		}

		private function initialize() : void
		{
			_children = new <ISceneNode>[];

			descendantAdded.add(descendantAddedHandler);
			descendantRemoved.add(descendantRemovedHandler);
		}

		protected function initializeChildren(children : Array) : void
		{
			while (children.length == 1 && children[0] is Array)
				children = children[0];

			var childrenNum : uint = children.length;

			for (var childrenIndex : uint = 0; childrenIndex < childrenNum; ++childrenIndex)
				addChild(ISceneNode(children[childrenIndex]));
		}

		private function descendantAddedHandler(group : Group, child : ISceneNode) : void
		{
			if (group == this)
			{
				var childGroup : Group = child as Group;

				if (childGroup)
				{
					childGroup.descendantAdded.add(_descendantAdded.execute);
					childGroup.descendantRemoved.add(_descendantRemoved.execute);
				}
			}

			_numDescendants += (child is Group) ? (child as Group)._numDescendants + 1 : 1;
		}

		private function descendantRemovedHandler(group : Group, child : ISceneNode) : void
		{
			if (group == this)
			{
				var childGroup : Group = child as Group;

				if (childGroup)
				{
					childGroup.descendantAdded.remove(_descendantAdded.execute);
					childGroup.descendantRemoved.remove(_descendantRemoved.execute);
				}
			}

			_numDescendants -= (child is Group) ? (child as Group)._numDescendants + 1 : 1;
		}

		/**
		 * Return true if the specified scene node is a child of the Group, false otherwise.
		 *
		 * @param scene
		 * @return
		 *
		 */
		public function contains(scene : ISceneNode) : Boolean
		{
			return getChildIndex(scene) >= 0;
		}

		/**
		 * Return the index of the speficied scene node or -1 if it is not in the Group.
		 *
		 * @param child
		 * @return
		 *
		 */
		public function getChildIndex(child : ISceneNode) : int
		{
			if (child == null)
				throw new Error('The \'child\' parameter cannot be null.');

			for (var i : int = 0; i < _numChildren; i++)
				if (_children[i] === child)
					return i;

			return -1;
		}

		public function getChildByName(name : String) : ISceneNode
		{
			for (var i : int = 0; i < _numChildren; i++)
				if (_children[i].name === name)
					return _children[i];

			return null;
		}

		/**
		 * Add a child to the group.
		 *
		 * @param	scene The child to add.
		 */
		public function addChild(node : ISceneNode) : Group
		{
			return addChildAt(node, _numChildren);
		}

		/**
		 * Add a child to the group at the specified position.
		 *
		 * @param node
		 * @param position
		 * @return
		 *
		 */
		public function addChildAt(node : ISceneNode, position : uint) : Group
		{
			if (!node)
				throw new Error('Parameter \'scene\' must not be null.');

			node.parent = this;

			for (var i : int = _numChildren - 1; i > position; --i)
				_children[i] = _children[int(i - 1)];

			_children[position] = node;

			return this;
		}

		/**
		 * Remove a child from the container.
		 *
		 * @param	myChild The child to remove.
		 * @return Whether the child was actually removed or not.
		 */
		public function removeChild(child : ISceneNode) : Group
		{
			return removeChildAt(getChildIndex(child));
		}

		public function removeChildAt(position : uint) : Group
		{
			if (position >= _numChildren || position < 0)
				throw new Error('The scene node is not a child of the caller.');

			(_children[position] as ISceneNode).parent = null;

			return this;
		}

		/**
		 * Remove all the children.
		 *
		 * @return
		 *
		 */
		public function removeAllChildren() : Group
		{
			while (_numChildren)
				removeChildAt(0);

			return this;
		}

		/**
		 * Return the child at the specified position.
		 *
		 * @param position
		 * @return
		 *
		 */
		public function getChildAt(position : uint) : ISceneNode
		{
			return position < _numChildren ? _children[position] : null;
		}

		/**
		 * Returns the list of descendant scene nodes that have the specified type.
		 *
		 * @param type
		 * @param descendants
		 * @return
		 *
		 */
		public function getDescendantsByType(type 			: Class,
											 descendants 	: Vector.<ISceneNode> = null) : Vector.<ISceneNode>
		{
			descendants ||= new Vector.<ISceneNode>();

			for (var i : int = 0; i < _numChildren; ++i)
			{
				var child	: ISceneNode	= _children[i];
				var group 	: Group 		= child as Group;

				if (child is type)
					descendants.push(child);

				if (group)
					group.getDescendantsByType(type, descendants);
			}

			return descendants;
		}

		public function toString() : String
		{
			return '[' + getQualifiedClassName(this) + ' ' + name + ']';
		}

		/**
		 * Load the 3D scene corresponding to the specified URLRequest object
		 * and add it directly to the group.
		 *
		 * @param request
		 * @param options
		 * @return
		 *
		 */
		public function load(request	: URLRequest,
							 options	: ParserOptions	= null) : ILoader
		{
			var loader	: SceneLoader	= new SceneLoader(options);

			loader.complete.add(loaderCompleteHandler);
			loader.load(request);

			return loader;
		}

		/**
		 * Load the 3D scene corresponding to the specified Class object
		 * and add it directly to the group.
		 *
		 * @param classObject
		 * @param options
		 * @return
		 */
		public function loadClass(classObject	: Class,
								  options		: ParserOptions	= null) : SceneLoader
		{
			var loader : SceneLoader = new SceneLoader(options);

			loader.complete.add(loaderCompleteHandler);
			loader.loadClass(classObject);

			return loader;
		}

		/**
		 * Load the 3D scene corresponding to the specified ByteArray object
		 * and add it directly to the group.
		 *
		 * @param bytes
		 * @param options
		 * @return
		 *
		 */
		public function loadBytes(bytes		: ByteArray,
								  options	: ParserOptions	= null) : ILoader
		{
			var loader	: SceneLoader	= new SceneLoader(options);

			loader.complete.add(loaderCompleteHandler);
			loader.loadBytes(bytes);

			return loader;
		}

		/**
		 * Return the set of nodes matching the specified XPath query.
		 *
		 * @param xpath
		 * @return
		 *
		 */
		public function get(xpath : String) : SceneIterator
		{
			return new SceneIterator(xpath, new <ISceneNode>[this]);
		}

		private function loaderCompleteHandler(loader	: ILoader,
											   scene	: ISceneNode) : void
		{
			addChild(scene);
		}

		/**
		 * Return all the Mesh objects hit by the specified ray.
		 *
		 * @param ray
		 * @param maxDistance
		 * @return
		 *
		 */
		public function cast(ray : Ray, maxDistance : Number = Number.POSITIVE_INFINITY) : SceneIterator
		{
			var meshes		: Vector.<ISceneNode> 	= getDescendantsByType(Mesh);
			var numMeshes	: uint					= meshes.length;
			var hit			: Array					= [];
			var depth		: Vector.<Number>		= new <Number>[];
			var numItems	: uint					= 0;

			for (var i : uint = 0; i < numMeshes; ++i)
			{
				var mesh 		: Mesh		= meshes[i] as Mesh;
				var hitDepth	: Number	= mesh.cast(ray, maxDistance);

				if (hitDepth >= 0.0)
				{
					hit[numItems] = mesh;
					depth[numItems] = hitDepth;
					++numItems;
				}
			}

			if (numItems > 1)
				Sort.flashSort(depth, hit, numItems);

			return new SceneIterator(null, Vector.<ISceneNode>(hit));
		}

		override minko_scene function cloneNode() : AbstractSceneNode
		{
			var clone : Group = new Group();

			clone.name = name;
			clone.transform.copyFrom(transform);

			for (var childId : uint = 0; childId < _numChildren; ++childId)
			{
				var child		: AbstractSceneNode = AbstractSceneNode(_children[childId]);
				var clonedChild	: AbstractSceneNode = AbstractSceneNode(child.cloneNode());

				clone.addChild(clonedChild);
			}

			return clone;
		}
	}
}

remove dead/commented code

remove dead/commented code


package
{
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.net.URLRequest;

    public class ImpetusSound
    {
        private var url:String;
        private var sound:Sound;

        private var channel:SoundChannel;

        private var volume:int;

        public function ImpetusSound(url:String, defaultVolume:int):void
        {
            this.url = url;
            this.sound = new Sound();

            this.sound.load(new URLRequest(url));

            this.channel = null;

            this.volume = defaultVolume;
        }

        public function getUrl():String
        {
            return this.url
        }

        public function play(pos:int):void
        {
            if(this.channel != null)
            {
                this.channel.stop();
            }

            this.channel = sound.play(pos);
            this.channel.soundTransform = new SoundTransform(this.volume, 0);
        }

        public function stop():void
        {
            this.channel.stop();

            this.channel = null;
        }

        public function getPos():int
        {
            return (this.channel != null)? channel.position : -1;
        }

        public function setVolume(volume:int):void
        {
            this.volume = volume;

            this.channel.soundTransform = new SoundTransform(this.volume, 0);
        }

        public function getVolume():int
        {
            return this.volume;
        }
    }
}

package
{
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.net.URLRequest;

    public class ImpetusSound
    {
        private var url:String;
        private var sound:Sound;

        private var channel:SoundChannel;

        private var volume:int;
        private var balance:int;

        public function ImpetusSound(url:String, defaultVolume:int):void
        {
            this.url = url;
            this.sound = new Sound();

            this.sound.load(new URLRequest(url));

            this.channel = null;

            this.volume = defaultVolume;
        }

        public function getUrl():String
        {
            return this.url
        }

        public function play(pos:int):void
        {
            if(this.channel != null)
            {
                this.channel.stop();
            }

            this.channel = sound.play(pos);

            this.updateTransform();
        }

        public function stop():void
        {
            this.channel.stop();

            this.channel = null;
        }

        public function getPos():int
        {
            return (this.channel != null)? channel.position : -1;
        }

        public function setVolume(volume:int):void
        {
            this.volume = volume;

            this.updateTransform();
        }

        public function getVolume():int
        {
            return this.volume;
        }

        public function setBalance(balance:int):void
        {
            this.balance = balance;

            this.updateTransform();
        }

        public function getBalance():int
        {
            return this.balance;
        }

        private function updateTransform():void
        {
            this.channel.soundTransform = new SoundTransform(this.volume, this.balance);
        }
    }
}

Add balance system

Add balance system


/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 package org.mangui.hls.demux {
    import flash.utils.ByteArray;
    import org.mangui.hls.model.Level;

    CONFIG::LOGGING {
        import org.mangui.hls.utils.Log;
    }
    public class DemuxHelper {
        public static function probe(data : ByteArray, level : Level, audioselect : Function, progress : Function, complete : Function, videometadata : Function, id3tagfound : Function, audioOnly : Boolean) : Demuxer {
            data.position = 0;
            CONFIG::LOGGING {
                Log.debug("probe fragment type");
            }
            var aac_match : Boolean = AACDemuxer.probe(data);
            var mp3_match : Boolean = MP3Demuxer.probe(data);
            var ts_match : Boolean = TSDemuxer.probe(data);
            CONFIG::LOGGING {
                Log.debug("AAC/MP3/TS match:" + aac_match + "/" + mp3_match + "/" + ts_match);
            }
            /* prioritize level info :
             * if ts_match && codec_avc  => TS demuxer
             * if aac_match && codec_aac => AAC demuxer
             * if mp3_match && codec_mp3 => MP3 demuxer
             * if no codec info in Manifest, use fallback order : AAC/MP3/TS
             */
            if (ts_match && level && level.codec_h264) {
                CONFIG::LOGGING {
                    Log.debug("TS match + H264 signaled in Manifest, use TS demuxer");
                }
                return new TSDemuxer(audioselect, progress, complete, videometadata, audioOnly);
            } else if (aac_match && level && level.codec_aac) {
                CONFIG::LOGGING {
                    Log.debug("AAC match + AAC signaled in Manifest, use AAC demuxer");
                }
                return new AACDemuxer(audioselect, progress, complete, id3tagfound);
            } else if (mp3_match && level && level.codec_mp3) {
                CONFIG::LOGGING {
                    Log.debug("MP3 match + MP3 signaled in Manifest, use MP3 demuxer");
                }
                return new MP3Demuxer(audioselect, progress, complete, id3tagfound);
            } else if (aac_match) {
                return new AACDemuxer(audioselect, progress, complete, id3tagfound);
            } else if (mp3_match) {
                return new MP3Demuxer(audioselect, progress, complete, id3tagfound);
            } else if (ts_match) {
                return new TSDemuxer(audioselect, progress, complete, videometadata, audioOnly);
            } else {
                CONFIG::LOGGING {
                    Log.debug("probe fails");
                }
                return null;
            }
        }
    }
}

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 package org.mangui.hls.demux {
    import flash.utils.ByteArray;
    import org.mangui.hls.model.Level;

    CONFIG::LOGGING {
        import org.mangui.hls.utils.Log;
    }
    public class DemuxHelper {
        public static function probe(data : ByteArray, level : Level, audioselect : Function, progress : Function, complete : Function, videometadata : Function, id3tagfound : Function, audioOnly : Boolean) : Demuxer {
            data.position = 0;
            CONFIG::LOGGING {
                Log.debug("probe fragment type");
            }
            var aac_match : Boolean = AACDemuxer.probe(data);
            var mp3_match : Boolean = MP3Demuxer.probe(data);
            var ts_match : Boolean = TSDemuxer.probe(data);
            CONFIG::LOGGING {
                Log.debug("AAC/MP3/TS match:" + aac_match + "/" + mp3_match + "/" + ts_match);
            }
            /* prioritize level info :
             * if ts_match && codec_avc  => TS demuxer
             * if aac_match && codec_aac => AAC demuxer
             * if mp3_match && codec_mp3 => MP3 demuxer
             * if no codec info in Manifest, use fallback order : AAC/MP3/TS
             */
            if (ts_match && level.codec_h264) {
                CONFIG::LOGGING {
                    Log.debug("TS match + H264 signaled in Manifest, use TS demuxer");
                }
                return new TSDemuxer(audioselect, progress, complete, videometadata, audioOnly);
            } else if (aac_match && level.codec_aac) {
                CONFIG::LOGGING {
                    Log.debug("AAC match + AAC signaled in Manifest, use AAC demuxer");
                }
                return new AACDemuxer(audioselect, progress, complete, id3tagfound);
            } else if (mp3_match && level.codec_mp3) {
                CONFIG::LOGGING {
                    Log.debug("MP3 match + MP3 signaled in Manifest, use MP3 demuxer");
                }
                return new MP3Demuxer(audioselect, progress, complete, id3tagfound);
            } else if (aac_match) {
                return new AACDemuxer(audioselect, progress, complete, id3tagfound);
            } else if (mp3_match) {
                return new MP3Demuxer(audioselect, progress, complete, id3tagfound);
            } else if (ts_match) {
                return new TSDemuxer(audioselect, progress, complete, videometadata, audioOnly);
            } else {
                CONFIG::LOGGING {
                    Log.debug("probe fails");
                }
                return null;
            }
        }
    }
}

Revert "[Mangui.DemuxHelper] Make probe Level parameter optional"

This reverts commit 3b6ac534dc61f2d9e09b0ed3e15141b1bb25a64b.


package org.mangui.HLS.muxing {
   import flash.utils.ByteArray;
   import org.mangui.HLS.utils.Log;

   public class ID3
   {
      public var len:Number;
      public var hasTimestamp:Boolean = false;
      public var timestamp:Number;

      /* create ID3 object by parsing ByteArray, looking for ID3 tag length, and timestamp */
      public function ID3(data:ByteArray) {
         var tagSize:uint = 0;
         try {
            var pos:Number = data.position;
            do {
              if(data.readUTFBytes(3) == 'ID3') {
                // skip 24 bits
                data.position += 3;
                // retrieve tag length
                var byte1:uint = data.readUnsignedByte() & 0x7f;
                var byte2:uint = data.readUnsignedByte() & 0x7f;
                var byte3:uint = data.readUnsignedByte() & 0x7f;
                var byte4:uint = data.readUnsignedByte() & 0x7f;
                tagSize = (byte1 << 21) + (byte2 << 14) + (byte3 << 7) + byte4;

                var end_pos:Number = data.position + tagSize;
                // read tag
                _parseFrame(data);
                data.position = end_pos;
              } else {
                data.position-=3;
                //Log.txt("ID3 len:"+ (data.position-pos));
                len = data.position-pos;
                return;
              }
            } while (true);
         } catch(e:Error)
         {
         }
         len = 0;
         return;
      };

      /*  Each Elementary Audio Stream segment MUST signal the timestamp of
          its first sample with an ID3 PRIV tag [ID3] at the beginning of
          the segment.  The ID3 PRIV owner identifier MUST be
          "com.apple.streaming.transportStreamTimestamp".  The ID3 payload
          MUST be a 33-bit MPEG-2 Program Elementary Stream timestamp
          expressed as a big-endian eight-octet number, with the upper 31
          bits set to zero.
       */

      private function _parseFrame(data:ByteArray):void {
        if (data.readUTFBytes(4) == "PRIV") {
          var frame_len:uint = data.readUnsignedInt();
          // smelling good ! 53 is the size of tag we are looking for
          if(frame_len == 53) {
            // skip flags (2 bytes)
            data.position+=2;
            // owner should be "com.apple.streaming.transportStreamTimestamp"
            if(data.readUTFBytes(44) == 'com.apple.streaming.transportStreamTimestamp') {
              // smelling even better ! we found the right descriptor
              // skip null character (string end) + 3 first bytes
              data.position+=4;
              // timestamp is 33 bit expressed as a big-endian eight-octet number, with the upper 31 bits set to zero.
              var pts_33_bit:Number = data.readUnsignedByte() & 0x1;
              hasTimestamp = true;
              timestamp = (data.readUnsignedInt()/90) << pts_33_bit;
              //Log.txt("timestamp found:"+timestamp);
            }
          }
        }
      }
   }
}

package org.mangui.HLS.muxing {
   import flash.utils.ByteArray;
   //import org.mangui.HLS.utils.Log;

   public class ID3
   {
      public var len:Number;
      public var hasTimestamp:Boolean = false;
      public var timestamp:Number;

      /* create ID3 object by parsing ByteArray, looking for ID3 tag length, and timestamp */
      public function ID3(data:ByteArray) {
         var tagSize:uint = 0;
         try {
            var pos:Number = data.position;
            do {
              if(data.readUTFBytes(3) == 'ID3') {
                // skip 24 bits
                data.position += 3;
                // retrieve tag length
                var byte1:uint = data.readUnsignedByte() & 0x7f;
                var byte2:uint = data.readUnsignedByte() & 0x7f;
                var byte3:uint = data.readUnsignedByte() & 0x7f;
                var byte4:uint = data.readUnsignedByte() & 0x7f;
                tagSize = (byte1 << 21) + (byte2 << 14) + (byte3 << 7) + byte4;

                var end_pos:Number = data.position + tagSize;
                // read tag
                _parseFrame(data);
                data.position = end_pos;
              } else {
                data.position-=3;
                //Log.txt("ID3 len:"+ (data.position-pos));
                len = data.position-pos;
                return;
              }
            } while (true);
         } catch(e:Error)
         {
         }
         len = 0;
         return;
      };

      /*  Each Elementary Audio Stream segment MUST signal the timestamp of
          its first sample with an ID3 PRIV tag [ID3] at the beginning of
          the segment.  The ID3 PRIV owner identifier MUST be
          "com.apple.streaming.transportStreamTimestamp".  The ID3 payload
          MUST be a 33-bit MPEG-2 Program Elementary Stream timestamp
          expressed as a big-endian eight-octet number, with the upper 31
          bits set to zero.
       */

      private function _parseFrame(data:ByteArray):void {
        if (data.readUTFBytes(4) == "PRIV") {
          var frame_len:uint = data.readUnsignedInt();
          // smelling good ! 53 is the size of tag we are looking for
          if(frame_len == 53) {
            // skip flags (2 bytes)
            data.position+=2;
            // owner should be "com.apple.streaming.transportStreamTimestamp"
            if(data.readUTFBytes(44) == 'com.apple.streaming.transportStreamTimestamp') {
              // smelling even better ! we found the right descriptor
              // skip null character (string end) + 3 first bytes
              data.position+=4;
              // timestamp is 33 bit expressed as a big-endian eight-octet number, with the upper 31 bits set to zero.
              var pts_33_bit:Number = data.readUnsignedByte() & 0x1;
              hasTimestamp = true;
              timestamp = (data.readUnsignedInt()/90) << pts_33_bit;
              //Log.txt("timestamp found:"+timestamp);
            }
          }
        }
      }
   }
}

remove unused import

remove unused import


/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is [Open Source Virtual Machine.].
 *
 * The Initial Developer of the Original Code is
 * Adobe System Incorporated.
 * Portions created by the Initial Developer are Copyright (C) 2004-2006
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Adobe AS3 Team
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

package
{
  public namespace AS3 = "http://adobe.com/AS3/2006/builtin";

  // Query whether a particular bugfix is in effect for this object.
  // information. Note that we use VM_INTERNAL to hide it from non-builtin code.
  public function bugzilla(n:int):Boolean {
    return false;
  }

  /**
   * @name Toplevel Function Properties
   * Function properties of the global object (ECMA 15.1.2)
   */

  // {DontEnum} length=1
  [native("decodeURI")]
  public native function decodeURI(uri:String="undefined"):String;

  // {DontEnum} length=1
  [native("decodeURIComponent")]
  public native function decodeURIComponent(uri:String="undefined"):String;

  // {DontEnum} length=1
  [native("encodeURI")]
  public native function encodeURI(uri:String="undefined"):String;

  // {DontEnum} length=1
  [native("encodeURIComponent")]
  public native function encodeURIComponent(uri:String="undefined"):String;

  // {DontEnum} length=1
  [native("isNaN")]
  public native function isNaN(n:Number = void 0):Boolean;

  // {DontEnum} length=1
  [native("isFinite")]
  public native function isFinite(n:Number = void 0):Boolean;

  // {DontEnum} length=1
  [native("parseInt")]
  public native function parseInt(s:String = "NaN", radix:int=0):Number;

  // {DontEnum} length=1
  [native("parseFloat")]
  public native function parseFloat(str:String = "NaN"):Number;

  /**
   * @name ECMA-262 Appendix B.2 extensions
   * Extensions to ECMAScript, in ECMA-262 Appendix B.2
   */

  // {DontEnum} length=1
  [native("escape")]
  public native function escape(s:String="undefined"):String;

  // {DontEnum} length=1
  [native("unescape")]
  public native function unescape(s:String="undefined"):String;

  // {DontEnum} length=1
  [native("isXMLName")]
  public native function isXMLName(str=void 0):Boolean;    // moved here from XML.as

  // value properties of global object (ECMA 15.1.1)

  // in E262, these are var {DontEnum,DontDelete}  but not ReadOnly
  // but in E327, these are {ReadOnly, DontEnum, DontDelete}
  // we choose to make them const ala E327

  // The initial value of NaN is NaN (section 8.5).
  // E262 { DontEnum, DontDelete}
  // E327 { DontEnum, DontDelete, ReadOnly}
  public const NaN:Number = NaN;

  // The initial value of Infinity is +8 (section 8.5).
  // E262 { DontEnum, DontDelete}
  // E327 { DontEnum, DontDelete, ReadOnly}
  public const Infinity:Number = 1/0;

  // The initial value of undefined is undefined (section 8.1).
  // E262 { DontEnum, DontDelete}
  // E327 { DontEnum, DontDelete, ReadOnly}
  public const undefined = void 0;
}

/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is [Open Source Virtual Machine.].
 *
 * The Initial Developer of the Original Code is
 * Adobe System Incorporated.
 * Portions created by the Initial Developer are Copyright (C) 2004-2006
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Adobe AS3 Team
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

package
{
  public namespace AS3 = "http://adobe.com/AS3/2006/builtin";

  // Query whether a particular bugfix is in effect for this object.
  // information. Note that we use VM_INTERNAL to hide it from non-builtin code.
  public function bugzilla(n:int):Boolean {
    return false;
  }

  /**
   * @name Toplevel Function Properties
   * Function properties of the global object (ECMA 15.1.2)
   */

  // {DontEnum} length=1
  [native("decodeURI")]
  public native function decodeURI(uri:String="undefined"):String;

  // {DontEnum} length=1
  [native("decodeURIComponent")]
  public native function decodeURIComponent(uri:String="undefined"):String;

  // {DontEnum} length=1
  [native("encodeURI")]
  public native function encodeURI(uri:String="undefined"):String;

  // {DontEnum} length=1
  [native("encodeURIComponent")]
  public native function encodeURIComponent(uri:String="undefined"):String;

  // {DontEnum} length=1
  [native("isNaN")]
  public native function isNaN(n:Number = void 0):Boolean;

  // {DontEnum} length=1
  [native("isFinite")]
  public native function isFinite(n:Number = void 0):Boolean;

  // {DontEnum} length=1
  [native("parseInt")]
  public native function parseInt(s:String = "NaN", radix:int=0):Number;

  // {DontEnum} length=1
  [native("parseFloat")]
  public native function parseFloat(str:String = "NaN"):Number;

  /**
   * @name ECMA-262 Appendix B.2 extensions
   * Extensions to ECMAScript, in ECMA-262 Appendix B.2
   */

  // {DontEnum} length=1
  [native("escape")]
  public native function escape(s:String="undefined"):String;

  // {DontEnum} length=1
  [native("unescape")]
  public native function unescape(s:String="undefined"):String;

  // {DontEnum} length=1
  [native("isXMLName")]
  public native function isXMLName(str=void 0):Boolean;    // moved here from XML.as

  // value properties of global object (ECMA 15.1.1)

  // in E262, these are var {DontEnum,DontDelete}  but not ReadOnly
  // but in E327, these are {ReadOnly, DontEnum, DontDelete}
  // we choose to make them const ala E327

  // The initial value of NaN is NaN (section 8.5).
  // E262 { DontEnum, DontDelete}
  // E327 { DontEnum, DontDelete, ReadOnly}
  public const NaN:Number = 0/0;

  // The initial value of Infinity is +8 (section 8.5).
  // E262 { DontEnum, DontDelete}
  // E327 { DontEnum, DontDelete, ReadOnly}
  public const Infinity:Number = 1/0;

  // The initial value of undefined is undefined (section 8.1).
  // E262 { DontEnum, DontDelete}
  // E327 { DontEnum, DontDelete, ReadOnly}
  public const undefined = void 0;
}

Fix top-level NaN constant.

Fix top-level NaN constant.


package aerys.minko.render.shader.part.projection
{
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.render.shader.part.ShaderPart;
	import aerys.minko.render.shader.part.coordinates.SphericalCoordinatesShaderPart;

	import flash.geom.Rectangle;

	/**
	 * Blinn-Newell projection and deprojection.
	 * It simply maps spherical coordinates to the plane (theta is x, phi is y).
	 *
	 * @author Romain Gilliotte
	 */
	public class BlinnNewellProjectionShaderPart extends ShaderPart implements IProjectionShaderPart
	{
		private static const SPHERICAL_COORDINATES_RECTANGLE : Rectangle = new Rectangle(0, 0, 2 * Math.PI, Math.PI);

		private var _sphericalPart : SphericalCoordinatesShaderPart;

		public function BlinnNewellProjectionShaderPart(main : Shader)
		{
			super(main);

			_sphericalPart = new SphericalCoordinatesShaderPart(main);
		}

		/**
		 * Project a vector into a plane with Blinn-Newell projection
		 *
		 * @param vector The vector to be projected
		 * @param target The rectangle to project into. Can be new Rectangle(0, 0, 1, 1) for UV projection, or new Rectangle(-1, -1, 2, 2) for clipspace projection.
		 * @return The projected vector (is a 3d vector, with depth).
		 */
		public function projectVector(vector	: SFloat,
									  target	: Rectangle,
									  zNear		: Number	= 0,
									  zFar		: Number	= 1000) : SFloat
		{
			var sphericalCoordinates	: SFloat = _sphericalPart.fromOrtho(vector);
			var projectedVector			: SFloat = sphericalCoordinates.zy;

			return transform2DCoordinates(projectedVector, SPHERICAL_COORDINATES_RECTANGLE, target);
		}

		/**
		 * Unproject a vector from a plane with Blinn-Newell projection
		 *
		 * @param projectedVector The vector to be unprojected
		 * @param source The rectangle to unproject from. Should be new Rectangle(0, 0, 1, 1) most of the time (if used to read from a texture).
		 * @return The unprojected vector (which is normalized).
		 */
		public function unprojectVector(projectedVector	: SFloat,
										source			: Rectangle) : SFloat
		{
			var coordinates				: SFloat = transform2DCoordinates(projectedVector, source, SPHERICAL_COORDINATES_RECTANGLE);
			var unprojectedVector		: SFloat = _sphericalPart.toOrtho(float3(1, coordinates.yx));

			return unprojectedVector;
		}
	}
}

package aerys.minko.render.shader.part.projection
{
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.render.shader.part.ShaderPart;
	import aerys.minko.render.shader.part.coordinates.SphericalCoordinatesShaderPart;

	import flash.geom.Rectangle;

	/**
	 * Blinn-Newell projection and deprojection.
	 * It simply maps spherical coordinates to the plane (theta is x, phi is y).
	 *
	 * @author Romain Gilliotte
	 */
	public class BlinnNewellProjectionShaderPart extends ShaderPart implements IProjectionShaderPart
	{
		private static const SPHERICAL_COORDINATES_RECTANGLE : Rectangle = new Rectangle(0, 0, 2 * Math.PI, Math.PI);

		private var _sphericalPart : SphericalCoordinatesShaderPart;

		public function BlinnNewellProjectionShaderPart(main : Shader)
		{
			super(main);

			_sphericalPart = new SphericalCoordinatesShaderPart(main);
		}

		/**
		 * Project a vector into a plane with Blinn-Newell projection
		 *
		 * @param vector The vector to be projected
		 * @param target The rectangle to project into. Can be new Rectangle(0, 0, 1, 1) for UV projection, or new Rectangle(-1, -1, 2, 2) for clipspace projection.
		 * @return The projected vector (is a 3d vector, with depth).
		 */
		public function projectVector(vector	: SFloat,
									  target	: Rectangle,
									  zNear		: Number	= 0.,
									  zFar		: Number	= 1000.) : SFloat
		{
			var sphericalCoordinates	: SFloat = _sphericalPart.fromOrtho(vector);
			var projectedVector			: SFloat = sphericalCoordinates.zy;

			return transform2DCoordinates(projectedVector, SPHERICAL_COORDINATES_RECTANGLE, target);
		}

		/**
		 * Unproject a vector from a plane with Blinn-Newell projection
		 *
		 * @param projectedVector The vector to be unprojected
		 * @param source The rectangle to unproject from. Should be new Rectangle(0, 0, 1, 1) most of the time (if used to read from a texture).
		 * @return The unprojected vector (which is normalized).
		 */
		public function unprojectVector(projectedVector	: SFloat,
										source			: Rectangle) : SFloat
		{
			var coordinates	: SFloat = transform2DCoordinates(projectedVector, source, SPHERICAL_COORDINATES_RECTANGLE);

			return _sphericalPart.toOrtho(float3(1, coordinates.yx));
		}
	}
}

fix minor coding style issues

fix minor coding style issues


package streamio
{
  import flash.events.*
  import flash.net.*

  import goplayer.StreamioAPI

  public class Stat
  {
    public static var trackerId:String = "global"

    public static function view(movieId:String)
    {
      update(movieId, "views")
    }

    public static function play(movieId:String)
    {
      update(movieId, "plays")
    }

    public static function heatmap(movieId:String, time:Number)
    {
      update(movieId, "heat", time)
    }

    private static function update(movieId:String, event:String, time = null)
    {
      var params:URLVariables = new URLVariables()
      params.movie_id = movieId
      params.event = event
      params.tracker_id = trackerId
      if(time) params.time = time

      var request:URLRequest = new URLRequest("http://"+StreamioAPI.host+"/stats")
      request.method = URLRequestMethod.POST
      request.data = params

      var loader:URLLoader = new URLLoader()
      loader.load(request)
    }
  }
}

// XXX: Make this file conform to Goplayer code style.

package streamio
{
  import flash.events.*
  import flash.net.*

  import goplayer.StreamioAPI

  public class Stat
  {
    public static var trackerId:String = "global"

    public static function view(movieId:String) : void
    {
      update(movieId, "views")
    }

    public static function play(movieId:String) : void
    {
      update(movieId, "plays")
    }

    public static function heatmap(movieId:String, time:Number) : void
    {
      update(movieId, "heat", time)
    }

    private static function update(movieId:String, event:String, time:Number = NaN) : void
    {
      var params:URLVariables = new URLVariables()
      params.movie_id = movieId
      params.event = event
      params.tracker_id = trackerId
      if(!isNaN(time)) params.time = time

      var request:URLRequest = new URLRequest("http://"+StreamioAPI.host+"/stats")
      request.method = URLRequestMethod.POST
      request.data = params

      var loader:URLLoader = new URLLoader()
      loader.load(request)
    }
  }
}

Fix problems and warnings in Stat.as.

Fix problems and warnings in Stat.as.


/* Vivified
 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
 *
 * 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301  USA
 */

/*** general objects ***/

Wrap = function () {};
Wrap.prototype = {};
Wrap.prototype.get = Native.wrap_get;
Wrap.prototype.toString = Native.wrap_toString;

Frame = function () extends Wrap {};
Frame.prototype = new Wrap ();
Frame.prototype.addProperty ("code", Native.frame_code_get, null);
Frame.prototype.addProperty ("name", Native.frame_name_get, null);
Frame.prototype.addProperty ("next", Native.frame_next_get, null);
Frame.prototype.addProperty ("this", Native.frame_this_get, null);

/*** breakpoints ***/

Breakpoint = function () extends Native.Breakpoint {
  super ();
  Breakpoint.list.push (this);
};
Breakpoint.list = new Array ();
Breakpoint.prototype.addProperty ("active", Native.breakpoint_active_get, Native.breakpoint_active_set);
Breakpoint.prototype.toString = function () {
  return "user-defined breakpoint";
};

/*** information about the player ***/

Player = {};
Player.addProperty ("filename", Native.player_filename_get, Native.player_filename_set);
Player.addProperty ("frame", Native.player_frame_get, null);
Player.addProperty ("global", Native.player_global_get, null);
Player.addProperty ("sound", Native.player_sound_get, Native.player_sound_set);
Player.addProperty ("variables", Native.player_variables_get, Native.player_variables_set);

/*** commands available for debugging ***/

Commands = new Object ();
Commands.print = Native.print;
Commands.error = Native.error;
Commands.r = Native.run;
Commands.run = Native.run;
Commands.halt = Native.stop;
Commands.stop = Native.stop;
Commands.s = Native.step;
Commands.step = Native.step;
Commands.reset = Native.reset;
Commands.restart = function () {
  Commands.reset ();
  Commands.run ();
};
Commands.quit = Native.quit;
/* can't use "break" as a function name, it's a keyword in JS */
Commands.add = function (name) {
  if (name == undefined) {
    Commands.error ("add command requires a function name");
    return undefined;
  }
  var ret = new Breakpoint ();
  ret.onEnterFrame = function (frame) {
    if (frame.name != name)
      return false;

    Commands.print ("Breakpoint: function " + name + " called");
    Commands.print ("  " + frame);
    return true;
  };
  ret.toString = function () {
    return "function call " + name;
  };
  return ret;
};
Commands.list = function () {
  var a = Breakpoint.list;
  var i;
  for (i = 0; i < a.length; i++) {
    Commands.print (i + ": " + a[i]);
  }
};
Commands.del = function (id) {
  var a = Breakpoint.list;
  if (id == undefined) {
    while (a[0])
      Commands.del (0);
  }
  var b = a[id];
  a.splice (id, 1);
  b.active = false;
};
Commands.delete = Commands.del;
Commands.where = function () {
  var frame = Player.frame;
  if (frame == undefined) {
    Commands.print ("---");
    return;
  }
  var i = 0;
  while (frame) {
    Commands.print (i++ + ": " + frame);
    frame = frame.next;
  }
};
Commands.backtrace = Commands.where;
Commands.bt = Commands.where;
Commands.watch = function () {
  var object;
  var name;
  if (arguments.length == 1) {
    name = arguments[0];
  } else if (arguments.length == 2) {
    object = arguments[0];
    name = arguments[1];
  } else {
    Commands.error ("usage: watch [object] name");
    return;
  }
  var ret = new Breakpoint ();
  ret.onSetVariable = function (o, variable, value) {
    if (object && o != object)
      return false;
    if (variable != name)
      return;

    if (object) {
      Commands.print ("Breakpoint: variable " + name + " on " + object);
    } else {
      Commands.print ("Breakpoint: variable " + name);
    }
    Commands.print ("  " + Player.frame);
    return true;
  };
  ret.toString = function () {
    var s = "watch " + name;
    if (object)
      s += " on " + object;
    return s;
  };
  return ret;
};

/* Vivified
 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
 *
 * 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301  USA
 */

/*** general objects ***/

Wrap = function () {};
Wrap.prototype = {};
Wrap.prototype.get = Native.wrap_get;
Wrap.prototype.toString = Native.wrap_toString;

Frame = function () extends Wrap {};
Frame.prototype = new Wrap ();
Frame.prototype.addProperty ("code", Native.frame_code_get, null);
Frame.prototype.addProperty ("name", Native.frame_name_get, null);
Frame.prototype.addProperty ("next", Native.frame_next_get, null);
Frame.prototype.addProperty ("this", Native.frame_this_get, null);

/*** breakpoints ***/

Breakpoint = function () extends Native.Breakpoint {
  super ();
  Breakpoint.list.push (this);
};
Breakpoint.list = new Array ();
Breakpoint.prototype.addProperty ("active", Native.breakpoint_active_get, Native.breakpoint_active_set);
Breakpoint.prototype.toString = function () {
  return "user-defined breakpoint";
};

/*** information about the player ***/

Player = {};
Player.addProperty ("filename", Native.player_filename_get, Native.player_filename_set);
Player.addProperty ("frame", Native.player_frame_get, null);
Player.addProperty ("global", Native.player_global_get, null);
Player.addProperty ("sound", Native.player_sound_get, Native.player_sound_set);
Player.addProperty ("variables", Native.player_variables_get, Native.player_variables_set);

/*** commands available for debugging ***/

Commands = new Object ();
Commands.print = Native.print;
Commands.error = Native.error;
Commands.r = Native.run;
Commands.run = Native.run;
Commands.halt = Native.stop;
Commands.stop = Native.stop;
Commands.s = Native.step;
Commands.step = Native.step;
Commands.reset = Native.reset;
Commands.restart = function () {
  Commands.reset ();
  Commands.run ();
};
Commands.quit = Native.quit;
/* can't use "break" as a function name, it's a keyword in JS */
Commands.add = function (name) {
  if (name == undefined) {
    Commands.error ("add command requires a function name");
    return undefined;
  }
  var ret = new Breakpoint ();
  ret.onEnterFrame = function (frame) {
    if (frame.name != name)
      return false;

    Commands.print ("Breakpoint: function " + name + " called");
    Commands.print ("  " + frame);
    return true;
  };
  ret.toString = function () {
    return "function call " + name;
  };
  return ret;
};
Commands.list = function () {
  var a = Breakpoint.list;
  var i;
  for (i = 0; i < a.length; i++) {
    Commands.print (i + ": " + a[i]);
  }
};
Commands.del = function (id) {
  var a = Breakpoint.list;
  if (id == undefined) {
    while (a[0])
      Commands.del (0);
  }
  var b = a[id];
  a.splice (id, 1);
  b.active = false;
};
Commands.delete = Commands.del;
Commands.where = function () {
  var frame = Player.frame;
  if (frame == undefined) {
    Commands.print ("---");
    return;
  }
  var i = 0;
  while (frame) {
    Commands.print (i++ + ": " + frame);
    frame = frame.next;
  }
};
Commands.backtrace = Commands.where;
Commands.bt = Commands.where;
Commands.watch = function () {
  var object;
  var name;
  if (arguments.length == 1) {
    name = arguments[0];
  } else if (arguments.length == 2) {
    object = arguments[0];
    name = arguments[1];
  } else {
    Commands.error ("usage: watch [object] name");
    return;
  }
  var ret = new Breakpoint ();
  ret.onSetVariable = function (o, variable, value) {
    if (object && o != object)
      return false;
    if (variable != name)
      return;

    if (object) {
      Commands.print ("Breakpoint: variable " + name + " on " + object + " set to: " + value);
    } else {
      Commands.print ("Breakpoint: variable " + name + " set to: " + value);
    }
    Commands.print ("  " + Player.frame);
    return true;
  };
  ret.toString = function () {
    var s = "watch " + name;
    if (object)
      s += " on " + object;
    return s;
  };
  return ret;
};

print the value the variable will be set to


/*
The RTMFPSocket class provides a socket-like interface around RTMFP
NetConnection and NetStream. Each RTMFPSocket contains one NetConnection and two
NetStreams, one for reading and one for writing.

To create a listening socket:
    var rs:RTMFPSocket = new RTMFPSocket(url, key);
    rs.addEventListener(Event.COMPLETE, function (e:Event):void {
        // rs.id is set and can be sent out of band to the client.
    });
    rs.addEventListener(RTMFPSocket.ACCEPT_EVENT, function (e:Event):void {
        // rs.peer_id is the ID of the connected client.
    });
    rs.listen();
To connect to a listening socket:
    // Receive peer_id out of band.
    var rs:RTMFPSocket = new RTMFPSocket(url, key);
    rs.addEventListener(Event.CONNECT, function (e:Event):void {
        // rs.id and rs.peer_id are now set.
    });
*/

package
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IOErrorEvent;
    import flash.events.NetStatusEvent;
    import flash.events.ProgressEvent;
    import flash.net.NetConnection;
    import flash.net.NetStream;
    import flash.utils.ByteArray;

    public class RTMFPSocket extends EventDispatcher
    {
        public static const ACCEPT_EVENT:String = "accept";

        public var connected:Boolean;

        private var nc:NetConnection;
        private var incoming:NetStream;
        private var outgoing:NetStream;

        /* Cache to hold the peer ID between when connect is called and the
           NetConnection exists. */
        private var connect_peer_id:String;

        private var buffer:ByteArray;

        private var cirrus_url:String;
        private var cirrus_key:String;

        public function RTMFPSocket(cirrus_url:String, cirrus_key:String = "")
        {
            connected = false;

            buffer = new ByteArray();

            this.cirrus_url = cirrus_url;
            this.cirrus_key = cirrus_key;

            nc = new NetConnection();
        }

        public function get id():String
        {
            return nc.nearID;
        }

        public function get peer_id():String
        {
            return incoming.farID;
        }

        /* NetStatusEvents that aren't handled more specifically in
           listen_netstatus_event or connect_netstatus_event. */
        private function generic_netstatus_event(e:NetStatusEvent):void
        {
            switch (e.info.code) {
            case "NetConnection.Connect.Closed":
                dispatchEvent(new Event(Event.CLOSE));
                break;
            case "NetStream.Connect.Closed":
                connected = false;
                close();
                break;
            default:
                var event:IOErrorEvent = new IOErrorEvent(IOErrorEvent.IO_ERROR);
                event.text = e.info.code;
                dispatchEvent(event);
                break;
            }
        }

        private function listen_netstatus_event(e:NetStatusEvent):void
        {
            switch (e.info.code) {
            case "NetConnection.Connect.Success":
                outgoing = new NetStream(nc, NetStream.DIRECT_CONNECTIONS);
                outgoing.client = {
                    onPeerConnect: listen_onpeerconnect
                };
                outgoing.publish("server");

                /* listen is complete, ready to accept. */
                dispatchEvent(new Event(Event.COMPLETE));
                break;
            case "NetStream.Connect.Success":
                break;
            default:
                return generic_netstatus_event(e);
                break;
            }
        }

        private function listen_onpeerconnect(peer:NetStream):Boolean {
            incoming = new NetStream(nc, peer.farID);
            incoming.client = {
                r: receive_data
            };
            incoming.play("client");

            connected = true;
            dispatchEvent(new Event(ACCEPT_EVENT));

            return true;
        }

        private function connect_netstatus_event(e:NetStatusEvent):void
        {
            switch (e.info.code) {
            case "NetConnection.Connect.Success":
                outgoing = new NetStream(nc, NetStream.DIRECT_CONNECTIONS);
                outgoing.publish("client");

                incoming = new NetStream(nc, connect_peer_id);
                incoming.client = {
                    r: receive_data
                };
                incoming.play("server");
                break;
            case "NetStream.Connect.Success":
                connected = true;
                dispatchEvent(new Event(Event.CONNECT));
                break;
            default:
                return generic_netstatus_event(e);
                break;
            }
        }

        /* Function called back when the other side does a send. */
        private function receive_data(bytes:ByteArray):void {
            var event:ProgressEvent;

            event = new ProgressEvent(ProgressEvent.SOCKET_DATA);
            event.bytesLoaded = bytes.bytesAvailable;

            bytes.readBytes(buffer, buffer.length, bytes.bytesAvailable);

            dispatchEvent(event);
        }

        public function listen():void
        {
            nc.addEventListener(NetStatusEvent.NET_STATUS, listen_netstatus_event);
            nc.connect(cirrus_url, cirrus_key);
        }

        public function connect(peer_id:String):void
        {
            /* Store for later reading by connect_netstatus_event. */
            this.connect_peer_id = peer_id;

            nc.addEventListener(NetStatusEvent.NET_STATUS, connect_netstatus_event);
            nc.connect(cirrus_url, cirrus_key);
        }

        public function close():void
        {
            if (outgoing)
                outgoing.close();
            if (incoming)
                incoming.close();
            if (nc)
                nc.close();
        }

        public function readBytes(output:ByteArray, offset:uint = 0, length:uint = 0):void
        {
            buffer.readBytes(output, offset, length);
            if (buffer.bytesAvailable == 0) {
                /* Reclaim memory space. */
                buffer.position = 0;
                buffer.length = 0;
            }
        }

        public function writeBytes(input:ByteArray, offset:uint = 0, length:uint = 0):void
        {
            var sendbuf:ByteArray;

            /* Read into a new buffer, in case offset and length do not
               completely span input. */
            sendbuf = new ByteArray();
            sendbuf.writeBytes(input, offset, length);

            /* Use a short method name because it's sent over the wire. */
            outgoing.send("r", sendbuf);
        }

        public function flush():void
        {
            /* Ignored. */
        }
    }
}

/*
The RTMFPSocket class provides a socket-like interface around RTMFP
NetConnection and NetStream. Each RTMFPSocket contains one NetConnection and two
NetStreams, one for reading and one for writing.

To create a listening socket:
    var rs:RTMFPSocket = new RTMFPSocket(url, key);
    rs.addEventListener(Event.COMPLETE, function (e:Event):void {
        // rs.id is set and can be sent out of band to the client.
    });
    rs.addEventListener(RTMFPSocket.ACCEPT_EVENT, function (e:Event):void {
        // rs.peer_id is the ID of the connected client.
    });
    rs.listen();
To connect to a listening socket:
    // Receive peer_id out of band.
    var rs:RTMFPSocket = new RTMFPSocket(url, key);
    rs.addEventListener(Event.CONNECT, function (e:Event):void {
        // rs.id and rs.peer_id are now set.
    });
*/

package
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IOErrorEvent;
    import flash.events.NetStatusEvent;
    import flash.events.ProgressEvent;
    import flash.net.NetConnection;
    import flash.net.NetStream;
    import flash.utils.ByteArray;

    public class RTMFPSocket extends EventDispatcher
    {
        public static const ACCEPT_EVENT:String = "accept";

        public var connected:Boolean;

        private var nc:NetConnection;
        private var incoming:NetStream;
        private var outgoing:NetStream;

        /* Cache to hold the peer ID between when connect is called and the
           NetConnection exists. */
        private var connect_peer_id:String;

        private var buffer:ByteArray;

        private var cirrus_url:String;
        private var cirrus_key:String;

        public function RTMFPSocket(cirrus_url:String, cirrus_key:String = "")
        {
            connected = false;

            buffer = new ByteArray();

            this.cirrus_url = cirrus_url;
            this.cirrus_key = cirrus_key;

            nc = new NetConnection();
        }

        public function get id():String
        {
            return nc.nearID;
        }

        public function get peer_id():String
        {
            return incoming.farID;
        }

        /* NetStatusEvents that aren't handled more specifically in
           listen_netstatus_event or connect_netstatus_event. */
        private function generic_netstatus_event(e:NetStatusEvent):void
        {
            switch (e.info.code) {
            case "NetConnection.Connect.Closed":
                connected = false;
                dispatchEvent(new Event(Event.CLOSE));
                break;
            case "NetStream.Connect.Closed":
                connected = false;
                close();
                break;
            default:
                var event:IOErrorEvent = new IOErrorEvent(IOErrorEvent.IO_ERROR);
                event.text = e.info.code;
                dispatchEvent(event);
                break;
            }
        }

        private function listen_netstatus_event(e:NetStatusEvent):void
        {
            switch (e.info.code) {
            case "NetConnection.Connect.Success":
                outgoing = new NetStream(nc, NetStream.DIRECT_CONNECTIONS);
                outgoing.client = {
                    onPeerConnect: listen_onpeerconnect
                };
                outgoing.publish("server");

                /* listen is complete, ready to accept. */
                dispatchEvent(new Event(Event.COMPLETE));
                break;
            case "NetStream.Connect.Success":
                break;
            default:
                return generic_netstatus_event(e);
                break;
            }
        }

        private function listen_onpeerconnect(peer:NetStream):Boolean {
            incoming = new NetStream(nc, peer.farID);
            incoming.client = {
                r: receive_data
            };
            incoming.play("client");

            connected = true;
            dispatchEvent(new Event(ACCEPT_EVENT));

            return true;
        }

        private function connect_netstatus_event(e:NetStatusEvent):void
        {
            switch (e.info.code) {
            case "NetConnection.Connect.Success":
                outgoing = new NetStream(nc, NetStream.DIRECT_CONNECTIONS);
                outgoing.publish("client");

                incoming = new NetStream(nc, connect_peer_id);
                incoming.client = {
                    r: receive_data
                };
                incoming.play("server");
                break;
            case "NetStream.Connect.Success":
                connected = true;
                dispatchEvent(new Event(Event.CONNECT));
                break;
            default:
                return generic_netstatus_event(e);
                break;
            }
        }

        /* Function called back when the other side does a send. */
        private function receive_data(bytes:ByteArray):void {
            var event:ProgressEvent;

            event = new ProgressEvent(ProgressEvent.SOCKET_DATA);
            event.bytesLoaded = bytes.bytesAvailable;

            bytes.readBytes(buffer, buffer.length, bytes.bytesAvailable);

            dispatchEvent(event);
        }

        public function listen():void
        {
            nc.addEventListener(NetStatusEvent.NET_STATUS, listen_netstatus_event);
            nc.connect(cirrus_url, cirrus_key);
        }

        public function connect(peer_id:String):void
        {
            /* Store for later reading by connect_netstatus_event. */
            this.connect_peer_id = peer_id;

            nc.addEventListener(NetStatusEvent.NET_STATUS, connect_netstatus_event);
            nc.connect(cirrus_url, cirrus_key);
        }

        public function close():void
        {
            if (outgoing)
                outgoing.close();
            if (incoming)
                incoming.close();
            if (nc)
                nc.close();
        }

        public function readBytes(output:ByteArray, offset:uint = 0, length:uint = 0):void
        {
            buffer.readBytes(output, offset, length);
            if (buffer.bytesAvailable == 0) {
                /* Reclaim memory space. */
                buffer.position = 0;
                buffer.length = 0;
            }
        }

        public function writeBytes(input:ByteArray, offset:uint = 0, length:uint = 0):void
        {
            var sendbuf:ByteArray;

            /* Read into a new buffer, in case offset and length do not
               completely span input. */
            sendbuf = new ByteArray();
            sendbuf.writeBytes(input, offset, length);

            /* Use a short method name because it's sent over the wire. */
            outgoing.send("r", sendbuf);
        }

        public function flush():void
        {
            /* Ignored. */
        }
    }
}

Reset the "connected" property on NetConnection.Connect.Closed.