/**

Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/
package
{

import org.apache.flex.core.Application;
import org.apache.flex.core.ItemRendererClassFactory;
import org.apache.flex.core.SimpleCSSValuesImpl;
import org.apache.flex.events.Event;
import org.apache.flex.html.beads.CSSButtonView;
import org.apache.flex.html.beads.CSSTextButtonView;
import org.apache.flex.html.beads.CSSTextToggleButtonView;
import org.apache.flex.html.beads.CheckBoxView;
import org.apache.flex.html.beads.ContainerView;
import org.apache.flex.html.beads.DataItemRendererFactoryForArrayData;
import org.apache.flex.html.beads.DropDownListView;
import org.apache.flex.html.beads.ListView;
import org.apache.flex.html.beads.RadioButtonView;
import org.apache.flex.html.beads.SingleLineBorderBead;
import org.apache.flex.html.beads.SolidBackgroundBead;
import org.apache.flex.html.beads.TextAreaView;
import org.apache.flex.html.beads.TextButtonMeasurementBead;
import org.apache.flex.html.beads.TextFieldLabelMeasurementBead;
import org.apache.flex.html.beads.TextFieldView;
import org.apache.flex.html.beads.TextInputWithBorderView;
import org.apache.flex.html.beads.TextItemRendererFactoryForArrayData;
import org.apache.flex.html.beads.controllers.DropDownListController;
import org.apache.flex.html.beads.controllers.ItemRendererMouseController;
import org.apache.flex.html.beads.controllers.EditableTextKeyboardController;
import org.apache.flex.html.beads.controllers.ListSingleSelectionMouseController;
import org.apache.flex.html.beads.layouts.VerticalLayout;
import org.apache.flex.html.beads.models.ArraySelectionModel;
import org.apache.flex.html.beads.models.SingleLineBorderModel;
import org.apache.flex.html.beads.models.TextModel;
import org.apache.flex.html.beads.models.ToggleButtonModel;
import org.apache.flex.html.beads.models.ValueToggleButtonModel;
import org.apache.flex.html.supportClasses.DropDownListList;
import org.apache.flex.html.supportClasses.DataGroup;
import org.apache.flex.html.supportClasses.ScrollingViewport;
import org.apache.flex.html.supportClasses.StringItemRenderer;
import org.apache.flex.net.HTTPService;
import org.apache.flex.collections.parsers.JSONInputParser;
import org.apache.flex.collections.LazyCollection;
import org.apache.flex.utils.ViewSourceContextMenuOption;

import models.MyModel;
import controllers.MyController;

public class DataBindingExample extends Application
{

    public function DataBindingExample()
    {
        addEventListener("initialize", initializeHandler);
        var vi:SimpleCSSValuesImpl = new SimpleCSSValuesImpl();
        setupStyles(vi);
        valuesImpl = vi;
        initialView = new MyInitialView();
        model = new MyModel();
        controller = new MyController(this);
        service = new HTTPService();
        collection = new LazyCollection();
        collection.inputParser = new JSONInputParser();
        collection.itemConverter = new StockDataJSONItemConverter();
        service.addBead(collection);
        addBead(service);
        addBead(new ViewSourceContextMenuOption());
    }

    public var service:HTTPService;
    public var collection:LazyCollection;

    private function initializeHandler(event:Event):void
    {
        MyModel(model).stockSymbol="ADBE";
    }

    private function setupStyles(vi:SimpleCSSValuesImpl):void
    {
        var viv:Object = vi.values = {};
        viv["global"] =
        {
            fontFamily: "Arial",
            fontSize: 12
        };

        var o:Object;

        o = viv[makeDefinitionName("org.apache.flex.html::Container")] =
        {

            iBeadView: ContainerView
        };

        CONFIG::as_only {
            o.iBackgroundBead = SolidBackgroundBead;
            o.iBorderBead = SingleLineBorderBead;
        }

        viv[makeDefinitionName("org.apache.flex.html::List")] =
        {
            iBeadModel: ArraySelectionModel,
            iBeadView:  ListView,
            iBeadController: ListSingleSelectionMouseController,
            iBeadLayout: VerticalLayout,
            iDataGroup: DataGroup,
            iDataProviderItemRendererMapper: DataItemRendererFactoryForArrayData,
			IViewport: ScrollingViewport,
            iItemRendererClassFactory: ItemRendererClassFactory,
            iItemRenderer: StringItemRenderer
        };

        o = viv[makeDefinitionName("org.apache.flex.html::Button")] =
        {
            backgroundColor: 0xd8d8d8,
            border: [1, "solid", 0x000000],
            padding: 4
        };
        CONFIG::as_only {
            o.iBeadView = CSSButtonView;
        }

        viv[makeDefinitionName("org.apache.flex.html::Button:hover")] =
        {
            backgroundColor: 0x9fa0a1,
            border: [1, "solid", 0x000000],
            padding: 4
        };

        viv[makeDefinitionName("org.apache.flex.html::Button:active")] =
        {
            backgroundColor: 0x929496,
            border: [1, "solid", 0x000000],
            padding: 4
        };

        CONFIG::as_only {
            viv["org.apache.flex.html::CheckBox"] =
            {
                iBeadModel: ToggleButtonModel,
                iBeadView:  CheckBoxView
            };

            viv["org.apache.flex.html::DropDownList"] =
            {
                iBeadModel: ArraySelectionModel,
                iBeadView: DropDownListView,
                iBeadController: DropDownListController,
                iPopUp: DropDownListList
            };

            viv["org.apache.flex.html.supportClasses::DropDownListList"] =
            {
                iBeadModel: ArraySelectionModel,
                iDataProviderItemRendererMapper: TextItemRendererFactoryForArrayData,
                iItemRendererClassFactory: ItemRendererClassFactory,
                iItemRenderer: StringItemRenderer,
			    iBackgroundBead: SolidBackgroundBead,
				borderStyle: "solid",
    			borderRadius: 4,
			    borderColor: 0,
			    borderWidth: 1,
			    backgroundColor: 0xFFFFFF
            };

            viv["org.apache.flex.html::Label"] =
            {
                iBeadModel: TextModel,
                iBeadView: TextFieldView,
                iMeasurementBead: TextFieldLabelMeasurementBead
            };

            viv["org.apache.flex.html::List"] =
            {
                iBorderBead: SingleLineBorderBead,
                iBorderModel: SingleLineBorderModel
            };

            viv["org.apache.flex.html::RadioButton"] =
            {
                iBeadModel: ValueToggleButtonModel,
                iBeadView:  RadioButtonView
            };

            viv["org.apache.flex.html::TextArea"] =
            {
                iBeadModel: TextModel,
                iBeadView: TextAreaView,
                iBeadController: EditableTextKeyboardController,
                iBorderBead: SingleLineBorderBead,
                iBorderModel: SingleLineBorderModel,
			    borderStyle: "solid",
    			borderColor: 0,
    			borderWidth: 1,
    			backgroundColor: 0xFFFFFF
            };

            viv["org.apache.flex.html::TextButton"] =
            {
                iBeadModel: TextModel,
                iBeadView: CSSTextButtonView,
                iMeasurementBead: TextButtonMeasurementBead
            };

            viv["org.apache.flex.html::TextInput"] =
            {
                iBeadModel: TextModel,
                iBeadView: TextInputWithBorderView,
                iBeadController: EditableTextKeyboardController,
                iBorderBead: SingleLineBorderBead,
			    iBackgroundBead: SolidBackgroundBead,
			    borderStyle: "solid",
    			borderColor: 0,
    			borderWidth: 1,
    			backgroundColor: 0xFFFFFF
            };

            viv["org.apache.flex.html::ToggleTextButton"] =
            {
                iBeadModel: ToggleButtonModel,
                iBeadView:  CSSTextToggleButtonView
            };

            viv["org.apache.flex.html::SimpleList"] =
            {
                iBeadModel: ArraySelectionModel,
                iBeadView:  ListView,
                iBeadController: ListSingleSelectionMouseController,
                iBeadLayout: VerticalLayout,
                iDataGroup: DataGroup,
                iDataProviderItemRendererMapper: TextItemRendererFactoryForArrayData,
	    		IViewport: ScrollingViewport,
                iItemRendererClassFactory: ItemRendererClassFactory,
                iItemRenderer: StringItemRenderer
            }

            viv["org.apache.flex.html.supportClasses::StringItemRenderer"] =
            {
                iBeadController: ItemRendererMouseController,
                height: 16
            }
        }
    }

    private function makeDefinitionName(s:String):String
    {
        CONFIG::js_only {
            s = s.replace("::", ".");
        }
        return s;
    }
}

}

/**

Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/
package
{

import org.apache.flex.core.Application;
import org.apache.flex.core.ItemRendererClassFactory;
import org.apache.flex.core.SimpleCSSValuesImpl;
import org.apache.flex.events.Event;
import org.apache.flex.html.beads.CSSButtonView;
import org.apache.flex.html.beads.CSSTextButtonView;
import org.apache.flex.html.beads.CSSTextToggleButtonView;
import org.apache.flex.html.beads.CheckBoxView;
import org.apache.flex.html.beads.ContainerView;
import org.apache.flex.html.beads.DataItemRendererFactoryForArrayData;
import org.apache.flex.html.beads.DropDownListView;
import org.apache.flex.html.beads.ListView;
import org.apache.flex.html.beads.RadioButtonView;
import org.apache.flex.html.beads.SingleLineBorderBead;
import org.apache.flex.html.beads.SolidBackgroundBead;
import org.apache.flex.html.beads.TextAreaView;
import org.apache.flex.html.beads.TextButtonMeasurementBead;
import org.apache.flex.html.beads.TextFieldLabelMeasurementBead;
import org.apache.flex.html.beads.TextFieldView;
import org.apache.flex.html.beads.TextInputWithBorderView;
import org.apache.flex.html.beads.TextItemRendererFactoryForArrayData;
import org.apache.flex.html.beads.controllers.DropDownListController;
import org.apache.flex.html.beads.controllers.ItemRendererMouseController;
import org.apache.flex.html.beads.controllers.EditableTextKeyboardController;
import org.apache.flex.html.beads.controllers.ListSingleSelectionMouseController;
import org.apache.flex.html.beads.layouts.BasicLayout;
import org.apache.flex.html.beads.layouts.VerticalLayout;
import org.apache.flex.html.beads.models.ArraySelectionModel;
import org.apache.flex.html.beads.models.SingleLineBorderModel;
import org.apache.flex.html.beads.models.TextModel;
import org.apache.flex.html.beads.models.ToggleButtonModel;
import org.apache.flex.html.beads.models.ValueToggleButtonModel;
import org.apache.flex.html.beads.models.ViewportModel;
import org.apache.flex.html.supportClasses.ContainerContentArea;
import org.apache.flex.html.supportClasses.DropDownListList;
import org.apache.flex.html.supportClasses.DataGroup;
import org.apache.flex.html.supportClasses.ScrollingViewport;
import org.apache.flex.html.supportClasses.Viewport;
import org.apache.flex.html.supportClasses.StringItemRenderer;
import org.apache.flex.net.HTTPService;
import org.apache.flex.collections.parsers.JSONInputParser;
import org.apache.flex.collections.LazyCollection;
import org.apache.flex.utils.ViewSourceContextMenuOption;

import models.MyModel;
import controllers.MyController;

public class DataBindingExample extends Application
{

    public function DataBindingExample()
    {
        addEventListener("initialize", initializeHandler);
        var vi:SimpleCSSValuesImpl = new SimpleCSSValuesImpl();
        setupStyles(vi);
        valuesImpl = vi;
        initialView = new MyInitialView();
        model = new MyModel();
        controller = new MyController(this);
        service = new HTTPService();
        collection = new LazyCollection();
        collection.inputParser = new JSONInputParser();
        collection.itemConverter = new StockDataJSONItemConverter();
        service.addBead(collection);
        addBead(service);
        addBead(new ViewSourceContextMenuOption());
    }

    public var service:HTTPService;
    public var collection:LazyCollection;

    private function initializeHandler(event:Event):void
    {
        MyModel(model).stockSymbol="ADBE";
    }

    private function setupStyles(vi:SimpleCSSValuesImpl):void
    {
        var viv:Object = vi.values = {};
        viv["global"] =
        {
            fontFamily: "Arial",
            fontSize: 12
        };

        var o:Object;

        o = viv[makeDefinitionName("org.apache.flex.html::Container")] =
        {

            iBeadView: ContainerView,
    		iBeadLayout: BasicLayout,
    		iContentView: ContainerContentArea,
			iViewport: Viewport,
			iViewportModel: ViewportModel
        };

        o = viv[makeDefinitionName("org.apache.flex.core::View")] =
        {

            iBeadView: ContainerView,
    		iBeadLayout: BasicLayout,
    		iContentView: ContainerContentArea,
			iViewport: Viewport,
			iViewportModel: ViewportModel
        };

        CONFIG::as_only {
            o.iBackgroundBead = SolidBackgroundBead;
            o.iBorderBead = SingleLineBorderBead;
        }

        viv[makeDefinitionName("org.apache.flex.html::List")] =
        {
            iBeadModel: ArraySelectionModel,
            iBeadView:  ListView,
            iBeadController: ListSingleSelectionMouseController,
            iBeadLayout: VerticalLayout,
            iContentView: DataGroup,
            iDataProviderItemRendererMapper: DataItemRendererFactoryForArrayData,
			iViewport: ScrollingViewport,
			iViewportModel: ViewportModel,
            iItemRendererClassFactory: ItemRendererClassFactory,
            iItemRenderer: StringItemRenderer
        };

        o = viv[makeDefinitionName("org.apache.flex.html::Button")] =
        {
            backgroundColor: 0xd8d8d8,
            border: [1, "solid", 0x000000],
            padding: 4
        };
        CONFIG::as_only {
            o.iBeadView = CSSButtonView;
        }

        viv[makeDefinitionName("org.apache.flex.html::Button:hover")] =
        {
            backgroundColor: 0x9fa0a1,
            border: [1, "solid", 0x000000],
            padding: 4
        };

        viv[makeDefinitionName("org.apache.flex.html::Button:active")] =
        {
            backgroundColor: 0x929496,
            border: [1, "solid", 0x000000],
            padding: 4
        };

        CONFIG::as_only {
            viv["org.apache.flex.html::CheckBox"] =
            {
                iBeadModel: ToggleButtonModel,
                iBeadView:  CheckBoxView
            };

            viv["org.apache.flex.html::DropDownList"] =
            {
                iBeadModel: ArraySelectionModel,
                iBeadView: DropDownListView,
                iBeadController: DropDownListController,
                iPopUp: DropDownListList
            };

            viv["org.apache.flex.html.supportClasses::DropDownListList"] =
            {
                iBeadModel: ArraySelectionModel,
                iDataProviderItemRendererMapper: TextItemRendererFactoryForArrayData,
                iItemRendererClassFactory: ItemRendererClassFactory,
                iItemRenderer: StringItemRenderer,
			    iBackgroundBead: SolidBackgroundBead,
				borderStyle: "solid",
    			borderRadius: 4,
			    borderColor: 0,
			    borderWidth: 1,
			    backgroundColor: 0xFFFFFF
            };

            viv["org.apache.flex.html::Label"] =
            {
                iBeadModel: TextModel,
                iBeadView: TextFieldView,
                iMeasurementBead: TextFieldLabelMeasurementBead
            };

            viv["org.apache.flex.html::List"] =
            {
                iBorderBead: SingleLineBorderBead,
                iBorderModel: SingleLineBorderModel
            };

            viv["org.apache.flex.html::RadioButton"] =
            {
                iBeadModel: ValueToggleButtonModel,
                iBeadView:  RadioButtonView
            };

            viv["org.apache.flex.html::TextArea"] =
            {
                iBeadModel: TextModel,
                iBeadView: TextAreaView,
                iBeadController: EditableTextKeyboardController,
                iBorderBead: SingleLineBorderBead,
                iBorderModel: SingleLineBorderModel,
			    borderStyle: "solid",
    			borderColor: 0,
    			borderWidth: 1,
    			backgroundColor: 0xFFFFFF
            };

            viv["org.apache.flex.html::TextButton"] =
            {
                iBeadModel: TextModel,
                iBeadView: CSSTextButtonView,
                iMeasurementBead: TextButtonMeasurementBead
            };

            viv["org.apache.flex.html::TextInput"] =
            {
                iBeadModel: TextModel,
                iBeadView: TextInputWithBorderView,
                iBeadController: EditableTextKeyboardController,
                iBorderBead: SingleLineBorderBead,
			    iBackgroundBead: SolidBackgroundBead,
			    borderStyle: "solid",
    			borderColor: 0,
    			borderWidth: 1,
    			backgroundColor: 0xFFFFFF
            };

            viv["org.apache.flex.html::ToggleTextButton"] =
            {
                iBeadModel: ToggleButtonModel,
                iBeadView:  CSSTextToggleButtonView
            };

            viv["org.apache.flex.html::SimpleList"] =
            {
                iBeadModel: ArraySelectionModel,
                iBeadView:  ListView,
                iBeadController: ListSingleSelectionMouseController,
                iBeadLayout: VerticalLayout,
                iContentView: DataGroup,
                iDataProviderItemRendererMapper: TextItemRendererFactoryForArrayData,
	    		iViewport: ScrollingViewport,
	    		iViewportModel: ViewportModel,
                iItemRendererClassFactory: ItemRendererClassFactory,
                iItemRenderer: StringItemRenderer
            }

            viv["org.apache.flex.html.supportClasses::StringItemRenderer"] =
            {
                iBeadController: ItemRendererMouseController,
                height: 16
            }
        }
    }

    private function makeDefinitionName(s:String):String
    {
        CONFIG::js_only {
            s = s.replace("::", ".");
        }
        return s;
    }
}

}

fix as example

fix as example


////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package spark.components
{
	import flash.events.Event;

	import mx.core.IUIComponent;
	import mx.core.IVisualElement;
	import mx.events.FlexEvent;
	import mx.states.State;

	import spark.components.supportClasses.SkinnableComponent;

	[SkinState("rotatingState")]
	[SkinState("notRotatingState")]

//--------------------------------------
//  Styles
//--------------------------------------

/**
 *  The interval to delay, in milliseconds, between rotations of this
 *  component. Controls the speed at which this component spins.
 *
 *  @default 50
 *
 *  @langversion 3.0
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 *
 */
[Style(name="rotationInterval", type="Number", format="Time", inherit="no")]

/**
 *  Color of the spokes of the spinner.
 *
 *  @default 0x000000
 *
 *  @langversion 3.0
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Style(name="symbolColor", type="uint", format="Color", inherit="yes", theme="spark,mobile")]

//--------------------------------------
//  Other metadata
//--------------------------------------

[IconFile("BusyIndicator.png")]

/**
 *  The BusyIndicator defines a component to display when a long-running
 *  operation is in progress.
 *  For Web, Desktop and Android, a circle is drawn that rotates.
 *  For iOS, a spinner with twelve spoke is drawn.
 *  The color of the circle or spokes is controlled by the value of the symbolColor style.
 *  The transparency of this component can be modified using the alpha property,
 *  but the alpha value of each spoke cannot be modified.
 *
 *
The following image shows the BusyIndicator at the bottom of the screen next
 *  to the Submit button:

 *
 *

 *
 *

 *
 *
The speed at which this component spins is controlled by the rotationInterval
 *  style. The rotationInterval style sets the delay, in milliseconds, between
 *  rotations. Decrease the rotationInterval value to increase the speed of the spin.

 *
 *
The BusyIndicator has the following default characteristics:

 *

 *
Characteristic	Description

 *
Default size	160 DPI: 26x26 pixels

 *                                  240 DPI: 40x40 pixels

 *                                  320 DPI: 52x52 pixels

 * 									380 DPI: 80x80 pixels

 *
Minimum size	20x20 pixels

 *
Maximum size	No limit

 *

 *
 *
The diameter of the BusyIndicator's spinner is the minimum of the width and
 *  height of the component. The diameter must be an even number, and is
 *  reduced by one if it is set to an odd number.

 *
 *  @mxml
 *
 *
The <s:BusyIndicator> tag inherits all of the tag
 *  attributes of its superclass and adds the following tag attributes:

 *
 *

 *  <s:BusyIndicator
 *    Common Styles
 *    rotationInterval=50
 *
 *    Spark Styles
 *    symbolColor="0x000000"
 *
 *    Mobile Styles
 *    symbolColor="0x000000"
 *  >
 *

 *
 *  @includeExample examples/BusyIndicatorExample.mxml -noswf
 *  @includeExample examples/views/BusyIndicatorExampleHomeView.mxml -noswf
 *
 *  @langversion 3.0
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
	public class BusyIndicator extends SkinnableComponent
	{
		private var effectiveVisibility:Boolean = false;
		private var effectiveVisibilityChanged:Boolean = true;

		public function BusyIndicator()
		{
			super();
			// Listen to added to stage and removed from stage.
			// Start rotating when we are on the stage and stop
			// when we are removed from the stage.
			addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
			addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
			states = 	[
				new State({name:"notRotatingState"}),
				new State({name:"rotatingState"})
			];
		}

		override protected function getCurrentSkinState():String
		{
			return currentState;
		}

		private function addedToStageHandler(event:Event):void
		{
			// Check our visibility here since we haven't added
			// visibility listeners yet.
			computeEffectiveVisibility();

			if (canRotate())
				currentState = "rotatingState";

			addVisibilityListeners();
			invalidateSkinState();
		}

		private function removedFromStageHandler(event:Event):void
		{
			currentState = "notRotatingState";

			removeVisibilityListeners();
			invalidateSkinState();
		}

		private function computeEffectiveVisibility():void
		{

			// Check our design layer first.
			if (designLayer && !designLayer.effectiveVisibility)
			{
				effectiveVisibility = false;
				return;
			}

			// Start out with true visibility and enablement
			// then loop up parent-chain to see if any of them are false.
			effectiveVisibility = true;
			var current:IVisualElement = this;

			while (current)
			{
				if (!current.visible)
				{
					if (!(current is IUIComponent) || !IUIComponent(current).isPopUp)
					{
						// Treat all pop ups as if they were visible. This is to
						// fix a bug where the BusyIndicator does not spin when it
						// is inside modal popup. The problem is in we do not get
						// an event when the modal window is made visible in
						// PopUpManagerImpl.fadeInEffectEndHandler(). When the modal
						// window is made visible, setVisible() is passed "true" so
						// as to not send an event. When do get events when the
						// non-modal windows are popped up. Only modal windows are
						// a problem.
						// The downside of this fix is BusyIndicator components that are
						// inside of hidden, non-modal, popup windows will paint themselves
						// on a timer.
						effectiveVisibility = false;
						break;
					}
				}

				current = current.parent as IVisualElement;
			}
		}

		/**
		 *  The BusyIndicator can be rotated if it is both on the display list and
		 *  visible.
		 *
		 *  @returns true if the BusyIndicator can be rotated, false otherwise.
		 */
		private function canRotate():Boolean
		{
			if (effectiveVisibility && stage != null)
				return true;

			return false;
		}

		/**
		 *  @private
		 *  Add event listeners for SHOW and HIDE on all the ancestors up the parent chain.
		 *  Adding weak event listeners just to be safe.
		 */
		private function addVisibilityListeners():void
		{
			var current:IVisualElement = this.parent as IVisualElement;
			while (current)
			{
				// add visibility listeners to the parent
				current.addEventListener(FlexEvent.HIDE, visibilityChangedHandler, false, 0, true);
				current.addEventListener(FlexEvent.SHOW, visibilityChangedHandler, false, 0, true);

				current = current.parent as IVisualElement;
			}
		}

		/**
		 *  @private
		 *  Remove event listeners for SHOW and HIDE on all the ancestors up the parent chain.
		 */
		private function removeVisibilityListeners():void
		{
			var current:IVisualElement = this;
			while (current)
			{
				current.removeEventListener(FlexEvent.HIDE, visibilityChangedHandler, false);
				current.removeEventListener(FlexEvent.SHOW, visibilityChangedHandler, false);

				current = current.parent as IVisualElement;
			}
		}

		/**
		 *  @private
		 *  Event call back whenever the visibility of us or one of our ancestors
		 *  changes
		 */
		private function visibilityChangedHandler(event:FlexEvent):void
		{
			effectiveVisibilityChanged = true;
			invalidateProperties();
		}

	}
}

////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package spark.components
{
	import flash.events.Event;

	import mx.core.IUIComponent;
	import mx.core.IVisualElement;
	import mx.events.FlexEvent;
	import mx.states.State;

	import spark.components.supportClasses.SkinnableComponent;

	[SkinState("rotatingState")]
	[SkinState("notRotatingState")]

//--------------------------------------
//  Styles
//--------------------------------------

/**
 *  The interval to delay, in milliseconds, between rotations of this
 *  component. Controls the speed at which this component spins.
 *
 *  @default 50
 *
 *  @langversion 3.0
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 *
 */
[Style(name="rotationInterval", type="Number", format="Time", inherit="no")]

/**
 *  Color of the spokes of the spinner.
 *
 *  @default 0x000000
 *
 *  @langversion 3.0
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
[Style(name="symbolColor", type="uint", format="Color", inherit="yes", theme="spark,mobile")]

//--------------------------------------
//  Other metadata
//--------------------------------------

[IconFile("BusyIndicator.png")]

/**
 *  The BusyIndicator defines a component to display when a long-running
 *  operation is in progress.
 *  For Web, Desktop and iOS, a spinner with twelve spoke is drawn.
 *  For Android, a circle is drawn that rotates.
 *  The color of the circle or spokes is controlled by the value of the symbolColor style.
 *  The transparency of this component can be modified using the alpha property,
 *  but the alpha value of each spoke cannot be modified.
 *
 *
The following image shows the BusyIndicator at the bottom of the screen next
 *  to the Submit button:

 *
 *

 *
 *

 *
 *
The speed at which this component spins is controlled by the rotationInterval
 *  style. The rotationInterval style sets the delay, in milliseconds, between
 *  rotations. Decrease the rotationInterval value to increase the speed of the spin.

 *
 *
The BusyIndicator has the following default characteristics:

 *

 *
Characteristic	Description

 *
Default size	160 DPI: 36x36 pixels

 *                                  120 DPI: 27x27 pixels

 *                                  240 DPI: 54x54 pixels

 *                                  320 DPI: 72x72 pixels

 * 									480 DPI: 108x108 pixels

 * 									640 DPI: 144x144 pixels

 *
Minimum size	20x20 pixels

 *
Maximum size	No limit

 *

 *
 *
The diameter of the BusyIndicator's spinner is the minimum of the width and
 *  height of the component. The diameter must be an even number, and is
 *  reduced by one if it is set to an odd number.

 *
 *  @mxml
 *
 *
The <s:BusyIndicator> tag inherits all of the tag
 *  attributes of its superclass and adds the following tag attributes:

 *
 *

 *  <s:BusyIndicator
 *    Common Styles
 *    rotationInterval=50
 *
 *    Spark Styles
 *    symbolColor="0x000000"
 *
 *    Mobile Styles
 *    symbolColor="0x000000"
 *  >
 *

 *
 *  @includeExample examples/BusyIndicatorExample.mxml -noswf
 *  @includeExample examples/views/BusyIndicatorExampleHomeView.mxml -noswf
 *
 *  @langversion 3.0
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
	public class BusyIndicator extends SkinnableComponent
	{
		private var effectiveVisibility:Boolean = false;
		private var effectiveVisibilityChanged:Boolean = true;

		public function BusyIndicator()
		{
			super();
			// Listen to added to stage and removed from stage.
			// Start rotating when we are on the stage and stop
			// when we are removed from the stage.
			addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
			addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
			states = 	[
				new State({name:"notRotatingState"}),
				new State({name:"rotatingState"})
			];
		}

		override protected function getCurrentSkinState():String
		{
			return currentState;
		}

		private function addedToStageHandler(event:Event):void
		{
			// Check our visibility here since we haven't added
			// visibility listeners yet.
			computeEffectiveVisibility();

			if (canRotate())
				currentState = "rotatingState";

			addVisibilityListeners();
			invalidateSkinState();
		}

		private function removedFromStageHandler(event:Event):void
		{
			currentState = "notRotatingState";

			removeVisibilityListeners();
			invalidateSkinState();
		}

		private function computeEffectiveVisibility():void
		{

			// Check our design layer first.
			if (designLayer && !designLayer.effectiveVisibility)
			{
				effectiveVisibility = false;
				return;
			}

			// Start out with true visibility and enablement
			// then loop up parent-chain to see if any of them are false.
			effectiveVisibility = true;
			var current:IVisualElement = this;

			while (current)
			{
				if (!current.visible)
				{
					if (!(current is IUIComponent) || !IUIComponent(current).isPopUp)
					{
						// Treat all pop ups as if they were visible. This is to
						// fix a bug where the BusyIndicator does not spin when it
						// is inside modal popup. The problem is in we do not get
						// an event when the modal window is made visible in
						// PopUpManagerImpl.fadeInEffectEndHandler(). When the modal
						// window is made visible, setVisible() is passed "true" so
						// as to not send an event. When do get events when the
						// non-modal windows are popped up. Only modal windows are
						// a problem.
						// The downside of this fix is BusyIndicator components that are
						// inside of hidden, non-modal, popup windows will paint themselves
						// on a timer.
						effectiveVisibility = false;
						break;
					}
				}

				current = current.parent as IVisualElement;
			}
		}

		/**
		 *  The BusyIndicator can be rotated if it is both on the display list and
		 *  visible.
		 *
		 *  @returns true if the BusyIndicator can be rotated, false otherwise.
		 */
		private function canRotate():Boolean
		{
			if (effectiveVisibility && stage != null)
				return true;

			return false;
		}

		/**
		 *  @private
		 *  Add event listeners for SHOW and HIDE on all the ancestors up the parent chain.
		 *  Adding weak event listeners just to be safe.
		 */
		private function addVisibilityListeners():void
		{
			var current:IVisualElement = this.parent as IVisualElement;
			while (current)
			{
				// add visibility listeners to the parent
				current.addEventListener(FlexEvent.HIDE, visibilityChangedHandler, false, 0, true);
				current.addEventListener(FlexEvent.SHOW, visibilityChangedHandler, false, 0, true);

				current = current.parent as IVisualElement;
			}
		}

		/**
		 *  @private
		 *  Remove event listeners for SHOW and HIDE on all the ancestors up the parent chain.
		 */
		private function removeVisibilityListeners():void
		{
			var current:IVisualElement = this;
			while (current)
			{
				current.removeEventListener(FlexEvent.HIDE, visibilityChangedHandler, false);
				current.removeEventListener(FlexEvent.SHOW, visibilityChangedHandler, false);

				current = current.parent as IVisualElement;
			}
		}

		/**
		 *  @private
		 *  Event call back whenever the visibility of us or one of our ancestors
		 *  changes
		 */
		private function visibilityChangedHandler(event:FlexEvent):void
		{
			effectiveVisibilityChanged = true;
			invalidateProperties();
		}

	}
}

Update comments to keep up with latest visual changes


package org.mangui.HLS.muxing {
    import org.mangui.HLS.HLSAudioTrack;

    import flash.utils.ByteArray;

    import org.mangui.HLS.utils.Log;

    /** Constants and utilities for the AAC audio format. **/
    public class AAC implements Demuxer {
        /** ADTS Syncword (111111111111), ID (MPEG4), layer (00) and protection_absent (1).**/
        private static const SYNCWORD : uint = 0xFFF1;
        /** ADTS Syncword with MPEG2 stream ID (used by e.g. Squeeze 7). **/
        private static const SYNCWORD_2 : uint = 0xFFF9;
        /** ADTS Syncword with MPEG2 stream ID (used by e.g. Envivio 4Caster). **/
        private static const SYNCWORD_3 : uint = 0xFFF8;
        /** ADTS/ADIF sample rates index. **/
        private static const RATES : Array = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
        /** ADIF profile index (ADTS doesn't have Null). **/
        private static const PROFILES : Array = ['Null', 'Main', 'LC', 'SSR', 'LTP', 'SBR'];
        /** Byte data to be read **/
        private var _data : ByteArray;
        /* callback functions for audio selection, and parsing progress/complete */
        private var _callback_audioselect : Function;
        private var _callback_progress : Function;
        private var _callback_complete : Function;

        /** append new data */
        public function append(data : ByteArray) : void {
            _data.writeBytes(data);
        }

        /** cancel demux operation */
        public function cancel() : void {
            _data = null;
        }

        public function notifycomplete() : void {
            Log.debug("AAC: extracting AAC tags");
            var audioTags : Vector.<Tag> = new Vector.<Tag>();
            /* parse AAC, convert Elementary Streams to TAG */
            _data.position = 0;
            var id3 : ID3 = new ID3(_data);
            // AAC should contain ID3 tag filled with a timestamp
            var frames : Vector.<AudioFrame> = AAC.getFrames(_data, _data.position);
            var adif : ByteArray = getADIF(_data, 0);
            var adifTag : Tag = new Tag(Tag.AAC_HEADER, id3.timestamp, id3.timestamp, true);
            adifTag.push(adif, 0, adif.length);
            audioTags.push(adifTag);

            var audioTag : Tag;
            var stamp : Number;
            var i : Number = 0;

            while (i < frames.length) {
                stamp = Math.round(id3.timestamp + i * 1024 * 1000 / frames[i].rate);
                audioTag = new Tag(Tag.AAC_RAW, stamp, stamp, false);
                if (i != frames.length - 1) {
                    audioTag.push(_data, frames[i].start, frames[i].length);
                } else {
                    audioTag.push(_data, frames[i].start, _data.length - frames[i].start);
                }
                audioTags.push(audioTag);
                i++;
            }
            var audiotracks : Vector.<HLSAudioTrack> = new Vector.<HLSAudioTrack>();
            audiotracks.push(new HLSAudioTrack('AAC ES', HLSAudioTrack.FROM_DEMUX, 0, true));
            // report unique audio track. dont check return value as obviously the track will be selected
            _callback_audioselect(audiotracks);
            Log.debug("AAC: all tags extracted, callback demux");
            _callback_progress(audioTags, new Vector.<Tag>());
            _callback_complete();
        }

        public function AAC(callback_audioselect : Function, callback_progress : Function, callback_complete : Function) : void {
            _callback_audioselect = callback_audioselect;
            _callback_progress = callback_progress;
            _callback_complete = callback_complete;
            _data = new ByteArray();
        };

        public static function probe(data : ByteArray) : Boolean {
            var pos : Number = data.position;
            var id3 : ID3 = new ID3(data);
            // AAC should contain ID3 tag filled with a timestamp
            if (id3.hasTimestamp) {
                while (data.bytesAvailable > 1) {
                    // Check for ADTS header
                    var short : uint = data.readUnsignedShort();
                    if (short == SYNCWORD || short == SYNCWORD_2 || short == SYNCWORD_3) {
                        // rewind to sync word
                        data.position -= 2;
                        return true;
                    } else {
                        data.position--;
                    }
                }
                data.position = pos;
            }
            return false;
        }

        /** Get ADIF header from ADTS stream. **/
        public static function getADIF(adts : ByteArray, position : Number = 0) : ByteArray {
            adts.position = position;
            var short : uint;
            // we need at least 6 bytes, 2 for sync word, 4 for frame length
            while ((adts.bytesAvailable > 5) && (short != SYNCWORD) && (short != SYNCWORD_2) && (short != SYNCWORD_3)) {
                short = adts.readUnsignedShort();
            }

            if (short == SYNCWORD || short == SYNCWORD_2 || short == SYNCWORD_3) {
                var profile : uint = (adts.readByte() & 0xF0) >> 6;
                // Correcting zero-index of ADIF and Flash playing only LC/HE.
                if (profile > 3) {
                    profile = 5;
                } else {
                    profile = 2;
                }
                adts.position--;
                var srate : uint = (adts.readByte() & 0x3C) >> 2;
                adts.position--;
                var channels : uint = (adts.readShort() & 0x01C0) >> 6;
            } else {
                throw new Error("Stream did not start with ADTS header.");
                return null;
            }
            // 5 bits profile + 4 bits samplerate + 4 bits channels.
            var adif : ByteArray = new ByteArray();
            adif.writeByte((profile << 3) + (srate >> 1));
            adif.writeByte((srate << 7) + (channels << 3));
            if (Log.LOG_DEBUG_ENABLED) {
                Log.debug('AAC: ' + PROFILES[profile] + ', ' + RATES[srate] + ' Hz ' + channels + ' channel(s)');
            }
            // Reset position and return adif.
            adts.position -= 4;
            adif.position = 0;
            return adif;
        };

        /** Get a list with AAC frames from ADTS stream. **/
        public static function getFrames(adts : ByteArray, position : Number) : Vector.<AudioFrame> {
            var frames : Vector.<AudioFrame> = new Vector.<AudioFrame>();
            var frame_start : uint;
            var frame_length : uint;
            var id3 : ID3 = new ID3(adts);
            position += id3.len;
            // Get raw AAC frames from audio stream.
            adts.position = position;
            var samplerate : uint;
            // we need at least 6 bytes, 2 for sync word, 4 for frame length
            while (adts.bytesAvailable > 5) {
                // Check for ADTS header
                var short : uint = adts.readUnsignedShort();
                if (short == SYNCWORD || short == SYNCWORD_2 || short == SYNCWORD_3) {
                    // Store samplerate for offsetting timestamps.
                    if (!samplerate) {
                        samplerate = RATES[(adts.readByte() & 0x3C) >> 2];
                        adts.position--;
                    }
                    // Store raw AAC preceding this header.
                    if (frame_start) {
                        frames.push(new AudioFrame(frame_start, frame_length, frame_length, samplerate));
                    }
                    if (short == SYNCWORD_3) {
                        // ADTS header is 9 bytes.
                        frame_length = ((adts.readUnsignedInt() & 0x0003FFE0) >> 5) - 9;
                        frame_start = adts.position + 3;
                        adts.position += frame_length + 3;
                    } else {
                        // ADTS header is 7 bytes.
                        frame_length = ((adts.readUnsignedInt() & 0x0003FFE0) >> 5) - 7;
                        frame_start = adts.position + 1;
                        adts.position += frame_length + 1;
                    }
                } else {
                    Log.debug("no ADTS header found, probing...");
                    adts.position--;
                }
            }
            if (frame_start) {
                // check if we have a complete frame available at the end, i.e. last found frame is fitting in this PES packet
                var overflow : Number = frame_start + frame_length - adts.length;
                if (overflow <= 0 ) {
                    // no overflow, Write raw AAC after last header.
                    frames.push(new AudioFrame(frame_start, frame_length, frame_length, samplerate));
                } else {
                    Log.debug2("ADTS overflow at the end of PES packet, missing " + overflow + " bytes to complete the ADTS frame");
                }
            } else if (frames.length == 0) {
                Log.warn("No ADTS headers found in this stream.");
            }
            adts.position = position;
            return frames;
        };
    }
}

package org.mangui.HLS.muxing {
    import org.mangui.HLS.HLSAudioTrack;

    import flash.utils.ByteArray;

    import org.mangui.HLS.utils.Log;

    /** Constants and utilities for the AAC audio format. **/
    public class AAC implements Demuxer {
        /** ADTS Syncword (111111111111), ID (MPEG4), layer (00) and protection_absent (1).**/
        private static const SYNCWORD : uint = 0xFFF1;
        /** ADTS Syncword with MPEG2 stream ID (used by e.g. Squeeze 7). **/
        private static const SYNCWORD_2 : uint = 0xFFF9;
        /** ADTS Syncword with MPEG2 stream ID (used by e.g. Envivio 4Caster). **/
        private static const SYNCWORD_3 : uint = 0xFFF8;
        /** ADTS/ADIF sample rates index. **/
        private static const RATES : Array = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
        /** ADIF profile index (ADTS doesn't have Null). **/
        private static const PROFILES : Array = ['Null', 'Main', 'LC', 'SSR', 'LTP', 'SBR'];
        /** Byte data to be read **/
        private var _data : ByteArray;
        /* callback functions for audio selection, and parsing progress/complete */
        private var _callback_audioselect : Function;
        private var _callback_progress : Function;
        private var _callback_complete : Function;

        /** append new data */
        public function append(data : ByteArray) : void {
            _data.writeBytes(data);
        }

        /** cancel demux operation */
        public function cancel() : void {
            _data = null;
        }

        public function notifycomplete() : void {
            Log.debug("AAC: extracting AAC tags");
            var audioTags : Vector.<Tag> = new Vector.<Tag>();
            /* parse AAC, convert Elementary Streams to TAG */
            _data.position = 0;
            var id3 : ID3 = new ID3(_data);
            // AAC should contain ID3 tag filled with a timestamp
            var frames : Vector.<AudioFrame> = AAC.getFrames(_data, _data.position);
            var adif : ByteArray = getADIF(_data, 0);
            var adifTag : Tag = new Tag(Tag.AAC_HEADER, id3.timestamp, id3.timestamp, true);
            adifTag.push(adif, 0, adif.length);
            audioTags.push(adifTag);

            var audioTag : Tag;
            var stamp : Number;
            var i : Number = 0;

            while (i < frames.length) {
                stamp = Math.round(id3.timestamp + i * 1024 * 1000 / frames[i].rate);
                audioTag = new Tag(Tag.AAC_RAW, stamp, stamp, false);
                if (i != frames.length - 1) {
                    audioTag.push(_data, frames[i].start, frames[i].length);
                } else {
                    audioTag.push(_data, frames[i].start, _data.length - frames[i].start);
                }
                audioTags.push(audioTag);
                i++;
            }
            var audiotracks : Vector.<HLSAudioTrack> = new Vector.<HLSAudioTrack>();
            audiotracks.push(new HLSAudioTrack('AAC ES', HLSAudioTrack.FROM_DEMUX, 0, true));
            // report unique audio track. dont check return value as obviously the track will be selected
            _callback_audioselect(audiotracks);
            Log.debug("AAC: all tags extracted, callback demux");
            _callback_progress(audioTags, new Vector.<Tag>());
            _callback_complete();
        }

        public function AAC(callback_audioselect : Function, callback_progress : Function, callback_complete : Function) : void {
            _callback_audioselect = callback_audioselect;
            _callback_progress = callback_progress;
            _callback_complete = callback_complete;
            _data = new ByteArray();
        };

        public static function probe(data : ByteArray) : Boolean {
            var pos : Number = data.position;
            var id3 : ID3 = new ID3(data);
            // AAC should contain ID3 tag filled with a timestamp
            if (id3.hasTimestamp) {
                while (data.bytesAvailable > 1) {
                    // Check for ADTS header
                    var short : uint = data.readUnsignedShort();
                    if (short == SYNCWORD || short == SYNCWORD_2 || short == SYNCWORD_3) {
                        // rewind to sync word
                        data.position -= 2;
                        return true;
                    } else {
                        data.position--;
                    }
                }
                data.position = pos;
            }
            return false;
        }

        /** Get ADIF header from ADTS stream. **/
        public static function getADIF(adts : ByteArray, position : Number = 0) : ByteArray {
            adts.position = position;
            var short : uint;
            // we need at least 6 bytes, 2 for sync word, 4 for frame length
            while ((adts.bytesAvailable > 5) && (short != SYNCWORD) && (short != SYNCWORD_2) && (short != SYNCWORD_3)) {
                short = adts.readUnsignedShort();
            }

            if (short == SYNCWORD || short == SYNCWORD_2 || short == SYNCWORD_3) {
                var profile : uint = (adts.readByte() & 0xF0) >> 6;
                // Correcting zero-index of ADIF and Flash playing only LC/HE.
                if (profile > 3) {
                    profile = 5;
                } else {
                    profile = 2;
                }
                adts.position--;
                var srate : uint = (adts.readByte() & 0x3C) >> 2;
                adts.position--;
                var channels : uint = (adts.readShort() & 0x01C0) >> 6;
            } else {
                throw new Error("Stream did not start with ADTS header.");
            }
            // 5 bits profile + 4 bits samplerate + 4 bits channels.
            var adif : ByteArray = new ByteArray();
            adif.writeByte((profile << 3) + (srate >> 1));
            adif.writeByte((srate << 7) + (channels << 3));
            if (Log.LOG_DEBUG_ENABLED) {
                Log.debug('AAC: ' + PROFILES[profile] + ', ' + RATES[srate] + ' Hz ' + channels + ' channel(s)');
            }
            // Reset position and return adif.
            adts.position -= 4;
            adif.position = 0;
            return adif;
        };

        /** Get a list with AAC frames from ADTS stream. **/
        public static function getFrames(adts : ByteArray, position : Number) : Vector.<AudioFrame> {
            var frames : Vector.<AudioFrame> = new Vector.<AudioFrame>();
            var frame_start : uint;
            var frame_length : uint;
            var id3 : ID3 = new ID3(adts);
            position += id3.len;
            // Get raw AAC frames from audio stream.
            adts.position = position;
            var samplerate : uint;
            // we need at least 6 bytes, 2 for sync word, 4 for frame length
            while (adts.bytesAvailable > 5) {
                // Check for ADTS header
                var short : uint = adts.readUnsignedShort();
                if (short == SYNCWORD || short == SYNCWORD_2 || short == SYNCWORD_3) {
                    // Store samplerate for offsetting timestamps.
                    if (!samplerate) {
                        samplerate = RATES[(adts.readByte() & 0x3C) >> 2];
                        adts.position--;
                    }
                    // Store raw AAC preceding this header.
                    if (frame_start) {
                        frames.push(new AudioFrame(frame_start, frame_length, frame_length, samplerate));
                    }
                    if (short == SYNCWORD_3) {
                        // ADTS header is 9 bytes.
                        frame_length = ((adts.readUnsignedInt() & 0x0003FFE0) >> 5) - 9;
                        frame_start = adts.position + 3;
                        adts.position += frame_length + 3;
                    } else {
                        // ADTS header is 7 bytes.
                        frame_length = ((adts.readUnsignedInt() & 0x0003FFE0) >> 5) - 7;
                        frame_start = adts.position + 1;
                        adts.position += frame_length + 1;
                    }
                } else {
                    Log.debug("no ADTS header found, probing...");
                    adts.position--;
                }
            }
            if (frame_start) {
                // check if we have a complete frame available at the end, i.e. last found frame is fitting in this PES packet
                var overflow : Number = frame_start + frame_length - adts.length;
                if (overflow <= 0 ) {
                    // no overflow, Write raw AAC after last header.
                    frames.push(new AudioFrame(frame_start, frame_length, frame_length, samplerate));
                } else {
                    Log.debug2("ADTS overflow at the end of PES packet, missing " + overflow + " bytes to complete the ADTS frame");
                }
            } else if (frames.length == 0) {
                Log.warn("No ADTS headers found in this stream.");
            }
            adts.position = position;
            return frames;
        };
    }
}

remove useless return

remove useless return


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

package com.threerings.util {

import flash.net.registerClassAlias; // function import
import flash.net.ObjectEncoding;

import flash.geom.Point;
import flash.geom.Rectangle;

import flash.utils.ByteArray;
import flash.utils.Dictionary;
import flash.utils.Endian;
import flash.utils.IExternalizable;

import com.threerings.io.TypedArray;

/**
 * Utility methods for transforming flash objects into byte[].
 */
public class ObjectMarshaller
{
    /**
     * Encode the specified object as either a byte[] or a byte[][] (see below).
     * The specific mechanism of encoding is not important,
     * as long as decode returns a clone of the original object.
     *
     * No validation is done to verify that the object can be serialized.
     *
     * Currently, cycles in the object graph are preserved on the other end.
     *
     * @param encodeArrayElements if true and the obj is an Array, each element is
     * encoded separately, returning a byte[][] instead of a byte[].
     */
    public static function encode (
        obj :Object, encodeArrayElements :Boolean = false) :Object
    {
        if (obj == null) {
            return null;
        }
        if (encodeArrayElements && obj is Array) {
            var src :Array = (obj as Array);
            var dest :TypedArray = TypedArray.create(ByteArray);
            for (var ii :int = 0; ii < src.length; ii++) {
                dest.push(encode(src[ii], false));
            }
            return dest;
        }

        var bytes :ByteArray = new ByteArray();
        bytes.endian = Endian.BIG_ENDIAN;
        bytes.objectEncoding = ObjectEncoding.AMF3;
        // FIX, Because adobe is FUCKING IT UP as usual.
        // It seems that with flash 10, they "enhanced" AMF3 encoding. That's great and all,
        // except when we try to send this data back to a flash 9 player, which can't read it.
        // Guess what, asshats? If you change the encoding spec, IT'S NOT THE SAME VERSION ANYMORE.
        // Thanks for breaking all our code where we explicitly set AMF3, even though
        // it's currently the default.
        // TODO: find out what's doing it. I can't create a small test case- it seems to
        // only booch inside Whirled. Even using the viewer seems to always work.
        // I suspect it's a SecurityDomain/ApplicationDomain thing that's doing it, but
        // have tried correcting for or erasing those differences and I still have the problem.
        // Sometime.
        if (obj is Dictionary) {
            var asArray :Array = [];
            for (var key :* in obj) {
                asArray.push(key);
                asArray.push(obj[key]);
            }
            obj = asArray;
            // then insert our special marker byte before writing this array
            bytes.writeByte(DICTIONARY_MARKER);
        }
        bytes.writeObject(obj);
        return bytes;
    }

    /**
     * Validate the value and encode it. Arrays are not broken-up.
     * @param maxLength The maximum size of the data after encoding,
     *                  or -1 if no size restriction.
     */
    public static function validateAndEncode (obj :Object, maxLength :int = -1) :ByteArray
    {
        validateValue(obj);

        var data :ByteArray = encode(obj, false) as ByteArray;
        if (maxLength >= 0 && data != null && data.length > maxLength) {
            throw new ArgumentError("Cannot encode data of size " + data.length + " bytes. " +
                                    "May be at most " + maxLength + " bytes.");
        }

        return data;
    }

    /**
     * Decode the specified byte[] or byte[][] back into a flash Object.
     */
    public static function decode (encoded :Object) :Object
    {
        if (encoded == null) {
            return null;
        }
        if (encoded is TypedArray) {
            var src :TypedArray = (encoded as TypedArray);
            var dest :Array = [];
            for (var ii :int = 0; ii < src.length; ii++) {
                dest.push(decode(src[ii] as ByteArray));
            }
            return dest;
        }
        var bytes :ByteArray = (encoded as ByteArray);

        // Work around dictionary idiocy. Holy shit. See note in encode().
        const isDict :Boolean = (bytes[0] === DICTIONARY_MARKER);
        // re-set the position in case we're decoding the actual same byte
        // array used to encode (and not a network reconstruction)
        bytes.position = isDict ? 1 : 0;

        bytes.endian = Endian.BIG_ENDIAN;
        bytes.objectEncoding = ObjectEncoding.AMF3;
        var decoded :Object = bytes.readObject();
        if (isDict) {
            var decodedArray :Array = decoded as Array;
            var asDict :Dictionary = new Dictionary();
            for (var jj :int = 0; jj < decodedArray.length; jj += 2) {
                asDict[decodedArray[jj]] = decodedArray[jj + 1];
            }
            decoded = asDict;
        }
        return decoded;
    }

    /**
     * Validate that the value is kosher for encoding, or throw an ArgumentError if it's not.
     */
    public static function validateValue (value :Object) :void
        // throws ArgumentError
    {
        var s :String = getValidationError(value);
        if (s != null) {
            throw new ArgumentError(s);
        }
    }

    /**
     * Get the String reason why this value is not encodable, or null if no error.
     */
    public static function getValidationError (value :Object) :String
    {
        if (value == null) {
            return null;

        } else if (value is IExternalizable) {
            return "IExternalizable is not yet supported";

        } else if (value is Array) {
            if (ClassUtil.getClassName(value) != "Array") {
                // We can't allow arrays to be serialized as IExternalizables
                // because we need to know element values (opaquely) on the
                // server. Also, we don't allow other types because we wouldn't
                // create the right class on the other side.
                return "Custom array subclasses are not supported";
            }
            // then, continue on with the sub-properties check (below)

        } else if (value is Dictionary) {
            if (ClassUtil.getClassName(value) != "flash.utils.Dictionary") {
                return "Custom Dictionary subclasses are not supported";
            }
            // check all the keys
            for (var key :* in value) {
                var se :String = getValidationError(key);
                if (se != null) {
                    return se;
                }
            }
            // then, continue on with sub-property check (below)

        } else {
            var type :String = typeof(value);
            if (type == "number" || type == "string" || type == "boolean" ) {
                return null; // kosher!
            }
            if (-1 != VALID_CLASSES.indexOf(ClassUtil.getClassName(value))) {
                return null; // kosher
            }
            if (!Util.isPlainObject(value)) {
                return "Non-simple properties may not be set.";
            }
            // fall through and verify the plain object's sub-properties
        }

        // check sub-properties (of arrays and objects)
        for each (var arrValue :Object in value) {
            var s :String = getValidationError(arrValue);
            if (s != null) {
                return s;
            }
        }

        return null; // it all checks out!
    }

    // hope and pray that they don't revamp amf3 again and start using this byte. Assholes.
    public static const DICTIONARY_MARKER :int = 99;

    /**
     * Our static initializer.
     */
    private static function staticInit () :void
    {
        registerClassAlias("P", Point);
        registerClassAlias("R", Rectangle);
        registerClassAlias("D", Dictionary);
    }
    staticInit();

    /** Non-simple classes that we allow, as long as they are not subclassed. */
    protected static const VALID_CLASSES :Array = [
        "flash.utils.ByteArray", "flash.geom.Point", "flash.geom.Rectangle" ];
}
}

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

package com.threerings.util {

import flash.net.registerClassAlias; // function import
import flash.net.ObjectEncoding;

import flash.geom.Point;
import flash.geom.Rectangle;

import flash.utils.ByteArray;
import flash.utils.Dictionary;
import flash.utils.Endian;
import flash.utils.IExternalizable;

import com.threerings.io.TypedArray;

/**
 * Utility methods for transforming flash objects into byte[].
 */
public class ObjectMarshaller
{
    /**
     * Encode the specified object as either a byte[] or a byte[][] (see below).
     * The specific mechanism of encoding is not important,
     * as long as decode returns a clone of the original object.
     *
     * No validation is done to verify that the object can be serialized.
     *
     * Currently, cycles in the object graph are preserved on the other end.
     *
     * @param encodeArrayElements if true and the obj is an Array, each element is
     * encoded separately, returning a byte[][] instead of a byte[].
     */
    public static function encode (
        obj :Object, encodeArrayElements :Boolean = false) :Object
    {
        if (obj == null) {
            return null;
        }
        if (encodeArrayElements && obj is Array) {
            var src :Array = (obj as Array);
            var dest :TypedArray = TypedArray.create(ByteArray);
            for (var ii :int = 0; ii < src.length; ii++) {
                dest.push(encode(src[ii], false));
            }
            return dest;
        }

        var bytes :ByteArray = new ByteArray();
        bytes.endian = Endian.BIG_ENDIAN;
        bytes.objectEncoding = ObjectEncoding.AMF3;
        // FIX, Because adobe is FUCKING IT UP as usual.
        // It seems that with flash 10, they "enhanced" AMF3 encoding. That's great and all,
        // except when we try to send this data back to a flash 9 player, which can't read it.
        // Guess what, asshats? If you change the encoding spec, IT'S NOT THE SAME VERSION ANYMORE.
        // Thanks for breaking all our code where we explicitly set AMF3, even though
        // it's currently the default.
        // TODO: find out what's doing it. I can't create a small test case- it seems to
        // only booch inside Whirled. Even using the viewer seems to always work.
        // I suspect it's a SecurityDomain/ApplicationDomain thing that's doing it, but
        // have tried correcting for or erasing those differences and I still have the problem.
        // Sometime.
        if (obj is Dictionary) {
            var asArray :Array = [];
            for (var key :* in obj) {
                asArray.push(key);
                asArray.push(obj[key]);
            }
            obj = asArray;
            // then insert our special marker byte before writing this array
            bytes.writeByte(DICTIONARY_MARKER);
        }
        bytes.writeObject(obj);
        return bytes;
    }

    /**
     * Validate the value and encode it. Arrays are not broken-up.
     * @param maxLength The maximum size of the data after encoding,
     *                  or -1 if no size restriction.
     */
    public static function validateAndEncode (obj :Object, maxLength :int = -1) :ByteArray
    {
        validateValue(obj);

        var data :ByteArray = encode(obj, false) as ByteArray;
        if (maxLength >= 0 && data != null && data.length > maxLength) {
            throw new ArgumentError("Cannot encode data of size " + data.length + " bytes. " +
                                    "May be at most " + maxLength + " bytes.");
        }

        return data;
    }

    /**
     * Decode the specified byte[] or byte[][] back into a flash Object.
     */
    public static function decode (encoded :Object) :Object
    {
        if (encoded == null) {
            return null;
        }
        if (encoded is TypedArray) {
            var src :TypedArray = (encoded as TypedArray);
            var dest :Array = [];
            for (var ii :int = 0; ii < src.length; ii++) {
                dest.push(decode(src[ii] as ByteArray));
            }
            return dest;
        }
        var bytes :ByteArray = (encoded as ByteArray);

        // Work around dictionary idiocy. Holy shit. See note in encode().
        const isDict :Boolean = (bytes[0] === DICTIONARY_MARKER);
        // re-set the position in case we're decoding the actual same byte
        // array used to encode (and not a network reconstruction)
        bytes.position = isDict ? 1 : 0;

        bytes.endian = Endian.BIG_ENDIAN;
        bytes.objectEncoding = ObjectEncoding.AMF3;
        var decoded :Object = bytes.readObject();
        if (isDict) {
            var decodedArray :Array = decoded as Array;
            var asDict :Dictionary = new Dictionary();
            for (var jj :int = 0; jj < decodedArray.length; jj += 2) {
                asDict[decodedArray[jj]] = decodedArray[jj + 1];
            }
            decoded = asDict;
        }
        return decoded;
    }

    /**
     * Validate that the value is kosher for encoding, or throw an ArgumentError if it's not.
     */
    public static function validateValue (value :Object) :void
        // throws ArgumentError
    {
        var s :String = getValidationError(value);
        if (s != null) {
            throw new ArgumentError(s);
        }
    }

    /**
     * Get the String reason why this value is not encodable, or null if no error.
     */
    public static function getValidationError (value :Object) :String
    {
        if (value == null) {
            return null;

        } else if (value is IExternalizable) {
            return "IExternalizable is not yet supported";

        } else if (value is Array) {
            if (ClassUtil.getClassName(value) != "Array") {
                // We can't allow arrays to be serialized as IExternalizables
                // because we need to know element values (opaquely) on the
                // server. Also, we don't allow other types because we wouldn't
                // create the right class on the other side.
                return "Custom array subclasses are not supported";
            }
            // then, continue on with the sub-properties check (below)

        } else if (value is Dictionary) {
            if (ClassUtil.getClassName(value) != "flash.utils.Dictionary") {
                return "Custom Dictionary subclasses are not supported";
            }
            // check all the keys
            for (var key :* in value) {
                var se :String = getValidationError(key);
                if (se != null) {
                    return se;
                }
            }
            // then, continue on with sub-property check (below)

        } else {
            var type :String = typeof(value);
            if (type == "number" || type == "string" || type == "boolean" || type == "xml") {
                return null; // kosher!
            }
            if (-1 != VALID_CLASSES.indexOf(ClassUtil.getClassName(value))) {
                return null; // kosher
            }
            if (!Util.isPlainObject(value)) {
                return "Non-simple properties may not be set.";
            }
            // fall through and verify the plain object's sub-properties
        }

        // check sub-properties (of arrays and objects)
        for each (var arrValue :Object in value) {
            var s :String = getValidationError(arrValue);
            if (s != null) {
                return s;
            }
        }

        return null; // it all checks out!
    }

    // hope and pray that they don't revamp amf3 again and start using this byte. Assholes.
    public static const DICTIONARY_MARKER :int = 99;

    /**
     * Our static initializer.
     */
    private static function staticInit () :void
    {
        registerClassAlias("P", Point);
        registerClassAlias("R", Rectangle);
        registerClassAlias("D", Dictionary);
    }
    staticInit();

    /** Non-simple classes that we allow, as long as they are not subclassed. */
    protected static const VALID_CLASSES :Array = [
        "flash.utils.ByteArray", "flash.geom.Point", "flash.geom.Rectangle" ];
}
}

Allow XML to be encoded.
Let's try it and see if it works. Let us know Nathan.

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