package org.mangui.osmf.plugins.loader {
    import org.mangui.hls.HLS;
    import org.mangui.hls.HLSEvent;
	import org.mangui.hls.model.Level;
    import org.mangui.hls.HLSTypes;
    import org.mangui.osmf.plugins.HLSMediaElement;
    import org.mangui.osmf.plugins.utils.ErrorManager;
    import org.osmf.elements.proxyClasses.LoadFromDocumentLoadTrait;
    import org.osmf.events.MediaError;
    import org.osmf.events.MediaErrorEvent;
    import org.osmf.media.MediaElement;
    import org.osmf.media.MediaResourceBase;
    import org.osmf.media.URLResource;
    import org.osmf.net.DynamicStreamingItem;
    import org.osmf.net.DynamicStreamingResource;
    import org.osmf.net.StreamType;
    import org.osmf.net.StreamingURLResource;
    import org.osmf.traits.LoadState;
    import org.osmf.traits.LoadTrait;
    import org.osmf.traits.LoaderBase;

    CONFIG::LOGGING {
    import org.mangui.hls.utils.Log;
    }

    /**
     * Loader for .m3u8 playlist file.
     * Works like a F4MLoader
     */
    public class HLSLoaderBase extends LoaderBase {
        private var _loadTrait : LoadTrait;
        /** Reference to the framework. **/
        private static var _hls : HLS = null;

        public function HLSLoaderBase() {
            super();
        }

        public static function canHandle(resource : MediaResourceBase) : Boolean {
            if (resource !== null && resource is URLResource) {
                var urlResource : URLResource = URLResource(resource);
                if (urlResource.url.search(/(https?|file)\:\/\/.*?\m3u8(\?.*)?/i) !== -1) {
                    return true;
                }

                var contentType : Object = urlResource.getMetadataValue("content-type");
                if (contentType && contentType is String) {
                    // If the filename doesn't include a .m3u8 extension, but
                    // explicit content-type metadata is found on the
                    // URLResource, we can handle it.  Must be either of:
                    // - "application/x-mpegURL"
                    // - "vnd.apple.mpegURL"
                    if ((contentType as String).search(/(application\/x-mpegURL|vnd.apple.mpegURL)/i) !== -1) {
                        return true;
                    }
                }
            }
            return false;
        }

        override public function canHandleResource(resource : MediaResourceBase) : Boolean {
            return canHandle(resource);
        }

        override protected function executeLoad(loadTrait : LoadTrait) : void {
            _loadTrait = loadTrait;
            updateLoadTrait(loadTrait, LoadState.LOADING);

            if (_hls != null) {
                _hls.removeEventListener(HLSEvent.MANIFEST_LOADED, _manifestHandler);
                _hls.removeEventListener(HLSEvent.ERROR, _errorHandler);
                _hls.dispose();
                _hls = null;
            }
            _hls = new HLS();
            _hls.addEventListener(HLSEvent.MANIFEST_LOADED, _manifestHandler);
            _hls.addEventListener(HLSEvent.ERROR, _errorHandler);
            /* load playlist */
            _hls.load(URLResource(loadTrait.resource).url);
        }

        override protected function executeUnload(loadTrait : LoadTrait) : void {
            updateLoadTrait(loadTrait, LoadState.UNINITIALIZED);
        }

        /** Update video A/R on manifest load. **/
        private function _manifestHandler(event : HLSEvent) : void {
            var resource : MediaResourceBase = URLResource(_loadTrait.resource);

            // retrieve stream type
            var streamType : String = (resource as StreamingURLResource).streamType;
            if (streamType == null || streamType == StreamType.LIVE_OR_RECORDED) {
                if (_hls.type == HLSTypes.LIVE) {
                    streamType = StreamType.LIVE;
                } else {
                    streamType = StreamType.RECORDED;
                }
            }

            var levels : Vector.<Level> = _hls.levels;
            var nbLevel : int = levels.length;
            var urlRes : URLResource = resource as URLResource;
            var dynamicRes : DynamicStreamingResource = new DynamicStreamingResource(urlRes.url);
            var streamItems : Vector.<DynamicStreamingItem> = new Vector.<DynamicStreamingItem>();

            for (var i : int = 0; i < nbLevel; i++) {
                if (levels[i].width) {
                    streamItems.push(new DynamicStreamingItem(level2label(levels[i]), levels[i].bitrate / 1024, levels[i].width, levels[i].height));
                } else {
                    streamItems.push(new DynamicStreamingItem(level2label(levels[i]), levels[i].bitrate / 1024));
                }
            }
            dynamicRes.streamItems = streamItems;
            dynamicRes.initialIndex = 0;
            resource = dynamicRes;
            // set Stream Type
            var streamUrlRes : StreamingURLResource = resource as StreamingURLResource;
            streamUrlRes.streamType = streamType;
            try {
                var loadedElem : MediaElement = new HLSMediaElement(resource, _hls, event.levels[_hls.startlevel].duration);
                LoadFromDocumentLoadTrait(_loadTrait).mediaElement = loadedElem;
                updateLoadTrait(_loadTrait, LoadState.READY);
            } catch(e : Error) {
                updateLoadTrait(_loadTrait, LoadState.LOAD_ERROR);
                _loadTrait.dispatchEvent(new MediaErrorEvent(MediaErrorEvent.MEDIA_ERROR, false, false, new MediaError(e.errorID, e.message)));
            }
        };

        private function level2label(level : Level) : String {
            if (level.name) {
                return level.name;
            } else {
                if (level.height) {
                    return(level.height + 'p / ' + Math.round(level.bitrate / 1024) + 'kb');
                } else {
                    return(Math.round(level.bitrate / 1024) + 'kb');
                }
            }
        }

        private function _errorHandler(event : HLSEvent) : void {
            var errorCode : int = ErrorManager.getMediaErrorCode(event);
            var errorMsg : String = ErrorManager.getMediaErrorMessage(event);
            CONFIG::LOGGING {
            Log.warn("HLS Error event received, dispatching MediaError " + errorCode + "," + errorMsg);
            }
            updateLoadTrait(_loadTrait, LoadState.LOAD_ERROR);
            dispatchEvent(new MediaErrorEvent(MediaErrorEvent.MEDIA_ERROR, true, true, new MediaError(errorCode, errorMsg)));
        }
    }
}

package org.mangui.osmf.plugins.loader {
    import org.mangui.hls.HLS;
    import org.mangui.hls.HLSEvent;
	import org.mangui.hls.model.Level;
    import org.mangui.hls.HLSTypes;
    import org.mangui.osmf.plugins.HLSMediaElement;
    import org.mangui.osmf.plugins.utils.ErrorManager;
    import org.osmf.elements.proxyClasses.LoadFromDocumentLoadTrait;
    import org.osmf.events.MediaError;
    import org.osmf.events.MediaErrorEvent;
    import org.osmf.media.MediaElement;
    import org.osmf.media.MediaResourceBase;
    import org.osmf.media.URLResource;
    import org.osmf.net.DynamicStreamingItem;
    import org.osmf.net.DynamicStreamingResource;
    import org.osmf.net.StreamType;
    import org.osmf.net.StreamingURLResource;
    import org.osmf.traits.LoadState;
    import org.osmf.traits.LoadTrait;
    import org.osmf.traits.LoaderBase;

    CONFIG::LOGGING {
    import org.mangui.hls.utils.Log;
    }

    /**
     * Loader for .m3u8 playlist file.
     * Works like a F4MLoader
     */
    public class HLSLoaderBase extends LoaderBase {
        private var _loadTrait : LoadTrait;
        /** Reference to the framework. **/
        private static var _hls : HLS = null;

        public function HLSLoaderBase() {
            super();
        }

        public static function canHandle(resource : MediaResourceBase) : Boolean {
            if (resource !== null && resource is URLResource) {
                var urlResource : URLResource = URLResource(resource);
                if (urlResource.url.search(/(https?|file)\:\/\/.*?\m3u8(\?.*)?/i) !== -1) {
                    return true;
                }

                var contentType : Object = urlResource.getMetadataValue("content-type");
                if (contentType && contentType is String) {
                    // If the filename doesn't include a .m3u8 extension, but
                    // explicit content-type metadata is found on the
                    // URLResource, we can handle it.  Must be either of:
                    // - "application/x-mpegURL"
                    // - "vnd.apple.mpegURL"
                    if ((contentType as String).search(/(application\/x-mpegURL|vnd.apple.mpegURL)/i) !== -1) {
                        return true;
                    }
                }
            }
            return false;
        }

        override public function canHandleResource(resource : MediaResourceBase) : Boolean {
            return canHandle(resource);
        }

        override protected function executeLoad(loadTrait : LoadTrait) : void {
            _loadTrait = loadTrait;
            updateLoadTrait(loadTrait, LoadState.LOADING);

            if (_hls != null) {
                _hls.removeEventListener(HLSEvent.MANIFEST_LOADED, _manifestHandler);
                _hls.removeEventListener(HLSEvent.ERROR, _errorHandler);
                _hls.dispose();
                _hls = null;
            }
            _hls = new HLS();
            _hls.addEventListener(HLSEvent.MANIFEST_LOADED, _manifestHandler);
            _hls.addEventListener(HLSEvent.ERROR, _errorHandler);
            /* load playlist */
            _hls.load(URLResource(loadTrait.resource).url);
        }

        override protected function executeUnload(loadTrait : LoadTrait) : void {
            updateLoadTrait(loadTrait, LoadState.UNINITIALIZED);
        }

        /** Update video A/R on manifest load. **/
        private function _manifestHandler(event : HLSEvent) : void {
            var resource : MediaResourceBase = URLResource(_loadTrait.resource);

            // retrieve stream type
            var streamType : String = (resource as StreamingURLResource).streamType;
            if (streamType == null || streamType == StreamType.LIVE_OR_RECORDED) {
                if (_hls.type == HLSTypes.LIVE) {
                    streamType = StreamType.LIVE;
                } else {
                    streamType = StreamType.RECORDED;
                }
            }

            var levels : Vector.<Level> = _hls.levels;
            var nbLevel : int = levels.length;
            var urlRes : URLResource = resource as URLResource;
            var dynamicRes : DynamicStreamingResource = new DynamicStreamingResource(urlRes.url);
            var streamItems : Vector.<DynamicStreamingItem> = new Vector.<DynamicStreamingItem>();

            for (var i : int = 0; i < nbLevel; i++) {
                if (levels[i].width) {
                    streamItems.push(new DynamicStreamingItem(level2label(levels[i]), levels[i].bitrate / 1024, levels[i].width, levels[i].height));
                } else {
                    streamItems.push(new DynamicStreamingItem(level2label(levels[i]), levels[i].bitrate / 1024));
                }
            }
            dynamicRes.streamItems = streamItems;
            dynamicRes.initialIndex = 0;
            resource = dynamicRes;
            // set Stream Type
            var streamUrlRes : StreamingURLResource = resource as StreamingURLResource;
            streamUrlRes.streamType = streamType;
            try {
                var loadedElem : MediaElement = new HLSMediaElement(resource, _hls, event.levels[_hls.startlevel].duration);
                LoadFromDocumentLoadTrait(_loadTrait).mediaElement = loadedElem;
                updateLoadTrait(_loadTrait, LoadState.READY);
            } catch(e : Error) {
                updateLoadTrait(_loadTrait, LoadState.LOAD_ERROR);
                _loadTrait.dispatchEvent(new MediaErrorEvent(MediaErrorEvent.MEDIA_ERROR, false, false, new MediaError(e.errorID, e.message)));
            }
        };

        private function level2label(level : Level) : String {
            if (level.name) {
                return level.name;
            } else {
                if (level.height) {
                    return(level.height + 'p / ' + Math.round(level.bitrate / 1024) + 'kb');
                } else {
                    return(Math.round(level.bitrate / 1024) + 'kb');
                }
            }
        }

        private function _errorHandler(event : HLSEvent) : void {
            var errorCode : int = ErrorManager.getMediaErrorCode(event);
            var errorMsg : String = ErrorManager.getMediaErrorMessage(event);
            CONFIG::LOGGING {
            Log.warn("HLS Error event received, dispatching MediaError " + errorCode + "," + errorMsg);
            }
            updateLoadTrait(_loadTrait, LoadState.LOAD_ERROR);
            _loadTrait.dispatchEvent(new MediaErrorEvent(MediaErrorEvent.MEDIA_ERROR, false, false, new MediaError(errorCode, errorMsg)));
        }
    }
}

Fix bug : dispatch MediaErrorEvent on the _loadTrait (see OSMF F4MLoader class)


package aerys.minko.render.geometry.stream.format
{
	import flash.utils.ByteArray;

	public final class VertexComponent
	{
		private static const INSTANCIATED_COMPONENTS	: Object = new Object();

		public static const XYZ			: VertexComponent 	= create(["x", "y", "z"], VertexComponentType.FLOAT_3);
		public static const XY			: VertexComponent 	= create(["x", "y"], VertexComponentType.FLOAT_2);
		public static const UV			: VertexComponent 	= create(["u", "v"], VertexComponentType.FLOAT_2);
		public static const RGB			: VertexComponent 	= create(["r", "g", "b"], VertexComponentType.FLOAT_3);
		public static const RGBA		: VertexComponent 	= create(["r", "g", "b", "a"], VertexComponentType.FLOAT_4);
		public static const NORMAL		: VertexComponent 	= create(["nx", "ny", "nz"], VertexComponentType.FLOAT_3);
		public static const ST			: VertexComponent 	= create(["s", "t"], VertexComponentType.FLOAT_2);
		public static const ID			: VertexComponent 	= create(["id"], VertexComponentType.FLOAT_1);

		public static const TANGENT		: VertexComponent	= create(["tx", "ty", "tz"], VertexComponentType.FLOAT_3);

		public static const BONE_0_1	: VertexComponent	= create(["boneId0", "boneWeight0", "boneId1", "boneWeight1"], VertexComponentType.FLOAT_4);
		public static const BONE_2_3	: VertexComponent	= create(["boneId2", "boneWeight2", "boneId3", "boneWeight3"], VertexComponentType.FLOAT_4);
		public static const BONE_4_5	: VertexComponent	= create(["boneId4", "boneWeight4", "boneId5", "boneWeight5"], VertexComponentType.FLOAT_4);
		public static const BONE_6_7	: VertexComponent	= create(["boneId6", "boneWeight6", "boneId7", "boneWeight7"], VertexComponentType.FLOAT_4);
		public static const BONE_8_9	: VertexComponent	= create(["boneId8", "boneWeight8", "boneId9", "boneWeight9"], VertexComponentType.FLOAT_4);
		public static const BONE_10_11	: VertexComponent	= create(["boneId10", "boneWeight10", "boneId11", "boneWeight11"], VertexComponentType.FLOAT_4);
		public static const BONE_S		: VertexComponent	= create(["boneIdS", "boneWeightS"], VertexComponentType.FLOAT_2);

		public static const BONES		: Vector.<VertexComponent> = new <VertexComponent>[
			BONE_0_1, BONE_2_3, BONE_4_5, BONE_6_7, BONE_8_9, BONE_10_11
		];

		private var _nativeFormat		: int;
		private var _fields				: Vector.<String>;
		private var _offsets			: Object;
		private var _vertexComponentId	: String;	// used to avoid array comparison

		public function get size()				: int 				{ return VertexComponentType.NB_DWORDS[_nativeFormat]; }
		public function get offsets()				: Object 			{ return _offsets; }
		public function get fields()				: Vector.<String> 	{ return _fields; }
		public function get nativeFormat()			: int				{ return _nativeFormat; }
		public function get nativeFormatString()	: String 			{ return VertexComponentType.STRINGS[_nativeFormat]; }

		public static function create(fields : Array, nativeFormat : uint) : VertexComponent
		{
			var implodedFields : String = nativeFormat.toString() + '_' + fields.join("_");

			if (!INSTANCIATED_COMPONENTS[implodedFields])
				INSTANCIATED_COMPONENTS[implodedFields] = new VertexComponent(fields, nativeFormat);

			return INSTANCIATED_COMPONENTS[implodedFields];
		}

		public function VertexComponent(fields : Array, nativeFormat : int)
		{
			var implodedFields : String = nativeFormat.toString() + '_' + fields.join("_");

			if (INSTANCIATED_COMPONENTS[implodedFields])
				throw new Error('This component was already defined. Use VertexComponent.create() instead');

			_offsets		= new Object();
			_nativeFormat	= nativeFormat;
			_fields			= Vector.<String>(fields);

			var numFields : uint = _fields.length;
			for (var offset : int = 0; offset < numFields; ++offset)
				_offsets[fields[offset]] = offset;
		}

		public function hasField(fieldName : String) : Boolean
		{
			return _offsets[fieldName] !== undefined;
		}

		public function toString() : String
		{
			return _fields.join(', ');
		}
	}
}

fix coding style

fix coding style


package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import flash.events.Event;
    import flash.utils.setTimeout;

    import rtmfp.CirrusSocket;
    import rtmfp.FacilitatorSocket;
    import rtmfp.ProxyPair;
    import rtmfp.events.CirrusSocketEvent;
    import rtmfp.events.FacilitatorSocketEvent;

    public class rtmfpcat extends Sprite
    {
        /* Adobe's Cirrus server and Nate's key */
        private const DEFAULT_CIRRUS_ADDR:String = "rtmfp://p2p.rtmfp.net";
        private const DEFAULT_CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;

        /* Nate's facilitator -- serves a crossdomain policy */
        private const DEFAULT_FACILITATOR_ADDR:Object = {
            host: "128.12.179.80",
            port: 9002
        };

        private const DEFAULT_TOR_CLIENT_ADDR:Object = {
            host: "127.0.0.1",
            port: 3333
        };

        /* David's relay (nickname 3VXRyxz67OeRoqHn) that also serves a
           crossdomain policy. */
        private const DEFAULT_TOR_RELAY_ADDR:Object = {
            host: "173.255.221.44",
            port: 9001
        };

        /* Poll facilitator every 10 sec */
        private const DEFAULT_FAC_POLL_INTERVAL:uint = 10000;

        // Socket to Cirrus server
        private var s_c:CirrusSocket;
        // Socket to facilitator.
        private var s_f:FacilitatorSocket;
        // Handle local-remote traffic
        private var p_p:ProxyPair;

        private var proxy_pairs:Array;

        private var debug_mode:Boolean;
        private var proxy_mode:Boolean;

        /* TextField for debug output. */
        private var output_text:TextField;

        /* Badge for display */
        private var badge:InternetFreedomBadge;

        private var fac_addr:Object;
        private var relay_addr:Object;

        public function rtmfpcat()
        {
            proxy_mode = false;
            debug_mode = false;

            // Absolute positioning.
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;

            // Wait until the query string parameters are loaded.
            this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
        }

        public function puts(s:String):void
        {
            if (output_text != null) {
                output_text.appendText(s + "\n");
                output_text.scrollV = output_text.maxScrollV;
            }
        }

        private function loaderinfo_complete(e:Event):void
        {
            var fac_spec:String;
            var relay_spec:String;

            debug_mode = (this.loaderInfo.parameters["debug"] != null)
            proxy_mode = (this.loaderInfo.parameters["proxy"] != null);
            if (proxy_mode && !debug_mode) {
                badge = new InternetFreedomBadge(this);
                badge.display();
            } else {
                output_text = new TextField();
                output_text.width = stage.stageWidth;
                output_text.height = stage.stageHeight;
                output_text.background = true;
                output_text.backgroundColor = 0x001f0f;
                output_text.textColor = 0x44cc44;
                addChild(output_text);
            }

            puts("Starting: parameters loaded.");

            /* TODO: use this to have multiple proxies going at once */
            proxy_pairs = new Array();

            fac_spec = this.loaderInfo.parameters["facilitator"];
            if (fac_spec) {
                puts("Facilitator spec: \"" + fac_spec + "\"");
                fac_addr = parse_addr_spec(fac_spec);
                if (!fac_addr) {
                    puts("Error: Facilitator spec must be in the form \"host:port\".");
                    return;
                }
            } else {
                fac_addr = DEFAULT_FACILITATOR_ADDR;
            }

            relay_spec = this.loaderInfo.parameters["relay"];
            if (relay_spec) {
                puts("Relay spec: \"" + relay_spec + "\"");
                relay_addr = parse_addr_spec(relay_spec);
                if (!relay_addr) {
                    puts("Error: Relay spec must be in the form \"host:port\".");
                    return;
                }
            } else {
                if (proxy_mode) {
                    relay_addr = DEFAULT_TOR_RELAY_ADDR;
                } else {
                    relay_addr = DEFAULT_TOR_CLIENT_ADDR;
                }
            }

            main();
        }

        /* The main logic begins here, after start-up issues are taken care of. */
        private function main():void
        {
            establish_cirrus_connection();
        }

        private function establish_cirrus_connection():void
        {
            s_c = new CirrusSocket();
            s_c.addEventListener(CirrusSocketEvent.CONNECT_SUCCESS, function (e:CirrusSocketEvent):void {
                puts("Cirrus: connected with id " + s_c.id + ".");
                establish_facilitator_connection();
            });
            s_c.addEventListener(CirrusSocketEvent.CONNECT_FAILED, function (e:CirrusSocketEvent):void {
                puts("Error: failed to connect to Cirrus.");
            });
            s_c.addEventListener(CirrusSocketEvent.CONNECT_CLOSED, function (e:CirrusSocketEvent):void {
                puts("Cirrus: closed connection.");
            });

            s_c.addEventListener(CirrusSocketEvent.HELLO_RECEIVED, function (e:CirrusSocketEvent):void {
                puts("Cirrus: received hello from peer " + e.peer);

                /* don't bother if we already have a proxy going */
                if (p_p != null && p_p.connected) {
                    return;
                }

                /* if we're in proxy mode, we should have already set
                   up a proxy pair */
                if (!proxy_mode) {
                    start_proxy_pair();
                    s_c.send_hello(e.peer);
                } else if (!debug_mode && badge != null) {
                    badge.total_proxy_pairs++;
                    badge.num_proxy_pairs++;
                }
                p_p.connect(e.peer, e.stream);
            });

            s_c.connect(DEFAULT_CIRRUS_ADDR, DEFAULT_CIRRUS_KEY);
        }

        private function establish_facilitator_connection():void
        {
            s_f = new FacilitatorSocket(fac_addr.host, fac_addr.port);
            s_f.addEventListener(FacilitatorSocketEvent.CONNECT_FAILED, function (e:Event):void {
                puts("Facilitator: connect failed.");
                setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
            });

            if (proxy_mode) {
                s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_RECEIVED, function (e:FacilitatorSocketEvent):void {
                    puts("Facilitator: got registration " + e.client);
                    start_proxy_pair();
                    s_c.send_hello(e.client);
                });
                s_f.addEventListener(FacilitatorSocketEvent.REGISTRATIONS_EMPTY, function (e:Event):void {
                    puts("Facilitator: no registrations available.");
                    setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
                });
                puts("Facilitator: getting registration.");
                s_f.get_registration();
            } else {
                s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_FAILED, function (e:Event):void {
                    puts("Facilitator: registration failed.");
                    setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
                });
                puts("Facilitator: posting registration.");
                s_f.post_registration(s_c.id);
            }
        }

        private function start_proxy_pair():void
        {
            puts("Starting proxy pair on stream " + s_c.local_stream_name);
            p_p = new ProxyPair(this, s_c, relay_addr.host, relay_addr.port);
            p_p.addEventListener(Event.CONNECT, function (e:Event):void {
                puts("ProxyPair: connected!");
            });
            p_p.addEventListener(Event.CLOSE, function (e:Event):void {
                puts("ProxyPair: connection closed.");
                p_p = null;
                if (proxy_mode && !debug_mode && badge != null) {
                    badge.num_proxy_pairs++;
                }
                establish_facilitator_connection();
            });
            p_p.listen(s_c.local_stream_name);
        }

        /* Parse an address in the form "host:port". Returns an Object with
           keys "host" (String) and "port" (int). Returns null on error. */
        private function parse_addr_spec(spec:String):Object
        {
            var parts:Array;
            var addr:Object;

            parts = spec.split(":", 2);
            if (parts.length != 2 || !parseInt(parts[1]))
                return null;
            addr = {}
            addr.host = parts[0];
            addr.port = parseInt(parts[1]);

            return addr;
        }
    }
}

import flash.text.TextField;
import flash.text.TextFormat;

class InternetFreedomBadge {

    private var ui:rtmfpcat;

    private var _num_proxy_pairs:uint;
    private var _total_proxy_pairs:uint;

    [Embed(source="badge.png")]
    private var BadgeImage:Class;
    private var tot_client_count_tf:TextField;
    private var tot_client_count_fmt:TextFormat;
    private var cur_client_count_tf:TextField;
    private var cur_client_count_fmt:TextFormat;

    public function InternetFreedomBadge(ui:rtmfpcat)
    {
        this.ui = ui;
        _num_proxy_pairs = 0;
        _total_proxy_pairs = 0;

        /* Setup client counter for badge. */
        tot_client_count_fmt = new TextFormat();
        tot_client_count_fmt.color = 0xFFFFFF;
        tot_client_count_fmt.align = "center";
        tot_client_count_fmt.font = "courier-new";
        tot_client_count_fmt.bold = true;
        tot_client_count_fmt.size = 10;
        tot_client_count_tf = new TextField();
        tot_client_count_tf.width = 20;
        tot_client_count_tf.height = 17;
        tot_client_count_tf.background = false;
        tot_client_count_tf.defaultTextFormat = tot_client_count_fmt;
        tot_client_count_tf.x=47;
        tot_client_count_tf.y=0;

        cur_client_count_fmt = new TextFormat();
        cur_client_count_fmt.color = 0xFFFFFF;
        cur_client_count_fmt.align = "center";
        cur_client_count_fmt.font = "courier-new";
        cur_client_count_fmt.bold = true;
        cur_client_count_fmt.size = 10;
        cur_client_count_tf = new TextField();
        cur_client_count_tf.width = 20;
        cur_client_count_tf.height = 17;
        cur_client_count_tf.background = false;
        cur_client_count_tf.defaultTextFormat = cur_client_count_fmt;
        cur_client_count_tf.x=47;
        cur_client_count_tf.y=6;

        /* Update the client counter on badge. */
        update_client_count();
    }

    public function display():void
    {
        ui.addChild(new BadgeImage());
        /* Tried unsuccessfully to add counter to badge. */
        /* For now, need two addChilds :( */
        ui.addChild(tot_client_count_tf);
        ui.addChild(cur_client_count_tf);
    }

    public function get num_proxy_pairs():uint
    {
        return _num_proxy_pairs;
    }

    public function set num_proxy_pairs(amount:uint):void
    {
        _num_proxy_pairs = amount;
        update_client_count();
    }

    public function get total_proxy_pairs():uint
    {
        return _total_proxy_pairs;
    }

    public function set total_proxy_pairs(amount:uint):void
    {
        _total_proxy_pairs = amount;
        /* note: doesn't update, so be sure to update this
           before you update num_proxy_pairs! */
    }

    private function update_client_count():void
    {
        /* Update total client count. */
        if (String(total_proxy_pairs).length == 1)
            tot_client_count_tf.text = "0" + String(total_proxy_pairs);
        else
            tot_client_count_tf.text = String(total_proxy_pairs);

        /* Update current client count. */
        cur_client_count_tf.text = "";
        for(var i:Number = 0; i < num_proxy_pairs; i++)
            cur_client_count_tf.appendText(".");
    }
}

package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import flash.events.Event;
    import flash.utils.setTimeout;

    import rtmfp.CirrusSocket;
    import rtmfp.FacilitatorSocket;
    import rtmfp.ProxyPair;
    import rtmfp.events.CirrusSocketEvent;
    import rtmfp.events.FacilitatorSocketEvent;

    public class rtmfpcat extends Sprite
    {
        /* Adobe's Cirrus server and Nate's key */
        private const DEFAULT_CIRRUS_ADDR:String = "rtmfp://p2p.rtmfp.net";
        private const DEFAULT_CIRRUS_KEY:String = RTMFP::CIRRUS_KEY;

        /* Nate's facilitator -- serves a crossdomain policy */
        private const DEFAULT_FACILITATOR_ADDR:Object = {
            host: "128.12.179.80",
            port: 9002
        };

        private const DEFAULT_TOR_CLIENT_ADDR:Object = {
            host: "127.0.0.1",
            port: 3333
        };

        /* David's relay (nickname 3VXRyxz67OeRoqHn) that also serves a
           crossdomain policy. */
        private const DEFAULT_TOR_RELAY_ADDR:Object = {
            host: "173.255.221.44",
            port: 9001
        };

        /* Poll facilitator every 10 sec */
        private const DEFAULT_FAC_POLL_INTERVAL:uint = 10000;

        // Socket to Cirrus server
        private var s_c:CirrusSocket;
        // Socket to facilitator.
        private var s_f:FacilitatorSocket;
        // Handle local-remote traffic
        private var p_p:ProxyPair;

        private var proxy_pairs:Array;

        private var debug_mode:Boolean;
        private var proxy_mode:Boolean;

        /* TextField for debug output. */
        private var output_text:TextField;

        /* Badge for display */
        private var badge:InternetFreedomBadge;

        private var fac_addr:Object;
        private var relay_addr:Object;

        public function rtmfpcat()
        {
            proxy_mode = false;
            debug_mode = false;

            // Absolute positioning.
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;

            // Wait until the query string parameters are loaded.
            this.loaderInfo.addEventListener(Event.COMPLETE, loaderinfo_complete);
        }

        public function puts(s:String):void
        {
            if (output_text != null) {
                output_text.appendText(s + "\n");
                output_text.scrollV = output_text.maxScrollV;
            }
        }

        private function loaderinfo_complete(e:Event):void
        {
            var fac_spec:String;
            var relay_spec:String;

            debug_mode = (this.loaderInfo.parameters["debug"] != null)
            proxy_mode = (this.loaderInfo.parameters["proxy"] != null);
            if (proxy_mode && !debug_mode) {
                badge = new InternetFreedomBadge(this);
                badge.display();
            } else {
                output_text = new TextField();
                output_text.width = stage.stageWidth;
                output_text.height = stage.stageHeight;
                output_text.background = true;
                output_text.backgroundColor = 0x001f0f;
                output_text.textColor = 0x44cc44;
                addChild(output_text);
            }

            puts("Starting: parameters loaded.");

            /* TODO: use this to have multiple proxies going at once */
            proxy_pairs = new Array();

            fac_spec = this.loaderInfo.parameters["facilitator"];
            if (fac_spec) {
                puts("Facilitator spec: \"" + fac_spec + "\"");
                fac_addr = parse_addr_spec(fac_spec);
                if (!fac_addr) {
                    puts("Error: Facilitator spec must be in the form \"host:port\".");
                    return;
                }
            } else {
                fac_addr = DEFAULT_FACILITATOR_ADDR;
            }

            relay_spec = this.loaderInfo.parameters["relay"];
            if (relay_spec) {
                puts("Relay spec: \"" + relay_spec + "\"");
                relay_addr = parse_addr_spec(relay_spec);
                if (!relay_addr) {
                    puts("Error: Relay spec must be in the form \"host:port\".");
                    return;
                }
            } else {
                if (proxy_mode) {
                    relay_addr = DEFAULT_TOR_RELAY_ADDR;
                } else {
                    relay_addr = DEFAULT_TOR_CLIENT_ADDR;
                }
            }

            main();
        }

        /* The main logic begins here, after start-up issues are taken care of. */
        private function main():void
        {
            establish_cirrus_connection();
        }

        private function establish_cirrus_connection():void
        {
            s_c = new CirrusSocket();
            s_c.addEventListener(CirrusSocketEvent.CONNECT_SUCCESS, function (e:CirrusSocketEvent):void {
                puts("Cirrus: connected with id " + s_c.id + ".");
                establish_facilitator_connection();
            });
            s_c.addEventListener(CirrusSocketEvent.CONNECT_FAILED, function (e:CirrusSocketEvent):void {
                puts("Error: failed to connect to Cirrus.");
            });
            s_c.addEventListener(CirrusSocketEvent.CONNECT_CLOSED, function (e:CirrusSocketEvent):void {
                puts("Cirrus: closed connection.");
            });

            s_c.addEventListener(CirrusSocketEvent.HELLO_RECEIVED, function (e:CirrusSocketEvent):void {
                puts("Cirrus: received hello from peer " + e.peer);

                /* don't bother if we already have a proxy going */
                if (p_p != null && p_p.connected) {
                    return;
                }

                /* if we're in proxy mode, we should have already set
                   up a proxy pair */
                if (!proxy_mode) {
                    start_proxy_pair();
                    s_c.send_hello(e.peer);
                } else if (!debug_mode && badge != null) {
                    badge.total_proxy_pairs++;
                    badge.num_proxy_pairs++;
                }
                p_p.connect(e.peer, e.stream);
            });

            s_c.connect(DEFAULT_CIRRUS_ADDR, DEFAULT_CIRRUS_KEY);
        }

        private function establish_facilitator_connection():void
        {
            s_f = new FacilitatorSocket(fac_addr.host, fac_addr.port);
            s_f.addEventListener(FacilitatorSocketEvent.CONNECT_FAILED, function (e:Event):void {
                puts("Facilitator: connect failed.");
                setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
            });

            if (proxy_mode) {
                s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_RECEIVED, function (e:FacilitatorSocketEvent):void {
                    puts("Facilitator: got registration " + e.client);
                    start_proxy_pair();
                    s_c.send_hello(e.client);
                });
                s_f.addEventListener(FacilitatorSocketEvent.REGISTRATIONS_EMPTY, function (e:Event):void {
                    puts("Facilitator: no registrations available.");
                    setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
                });
                puts("Facilitator: getting registration.");
                s_f.get_registration();
            } else {
                s_f.addEventListener(FacilitatorSocketEvent.REGISTRATION_FAILED, function (e:Event):void {
                    puts("Facilitator: registration failed.");
                    setTimeout(establish_facilitator_connection, DEFAULT_FAC_POLL_INTERVAL);
                });
                puts("Facilitator: posting registration.");
                s_f.post_registration(s_c.id);
            }
        }

        private function start_proxy_pair():void
        {
            puts("Starting proxy pair on stream " + s_c.local_stream_name);
            p_p = new ProxyPair(this, s_c, relay_addr.host, relay_addr.port);
            p_p.addEventListener(Event.CONNECT, function (e:Event):void {
                puts("ProxyPair: connected!");
            });
            p_p.addEventListener(Event.CLOSE, function (e:Event):void {
                puts("ProxyPair: connection closed.");
                p_p = null;
                if (proxy_mode && !debug_mode && badge != null) {
                    badge.num_proxy_pairs--;
                }
                establish_facilitator_connection();
            });
            p_p.listen(s_c.local_stream_name);
        }

        /* Parse an address in the form "host:port". Returns an Object with
           keys "host" (String) and "port" (int). Returns null on error. */
        private function parse_addr_spec(spec:String):Object
        {
            var parts:Array;
            var addr:Object;

            parts = spec.split(":", 2);
            if (parts.length != 2 || !parseInt(parts[1]))
                return null;
            addr = {}
            addr.host = parts[0];
            addr.port = parseInt(parts[1]);

            return addr;
        }
    }
}

import flash.text.TextField;
import flash.text.TextFormat;

class InternetFreedomBadge {

    private var ui:rtmfpcat;

    private var _num_proxy_pairs:uint;
    private var _total_proxy_pairs:uint;

    [Embed(source="badge.png")]
    private var BadgeImage:Class;
    private var tot_client_count_tf:TextField;
    private var tot_client_count_fmt:TextFormat;
    private var cur_client_count_tf:TextField;
    private var cur_client_count_fmt:TextFormat;

    public function InternetFreedomBadge(ui:rtmfpcat)
    {
        this.ui = ui;
        _num_proxy_pairs = 0;
        _total_proxy_pairs = 0;

        /* Setup client counter for badge. */
        tot_client_count_fmt = new TextFormat();
        tot_client_count_fmt.color = 0xFFFFFF;
        tot_client_count_fmt.align = "center";
        tot_client_count_fmt.font = "courier-new";
        tot_client_count_fmt.bold = true;
        tot_client_count_fmt.size = 10;
        tot_client_count_tf = new TextField();
        tot_client_count_tf.width = 20;
        tot_client_count_tf.height = 17;
        tot_client_count_tf.background = false;
        tot_client_count_tf.defaultTextFormat = tot_client_count_fmt;
        tot_client_count_tf.x=47;
        tot_client_count_tf.y=0;

        cur_client_count_fmt = new TextFormat();
        cur_client_count_fmt.color = 0xFFFFFF;
        cur_client_count_fmt.align = "center";
        cur_client_count_fmt.font = "courier-new";
        cur_client_count_fmt.bold = true;
        cur_client_count_fmt.size = 10;
        cur_client_count_tf = new TextField();
        cur_client_count_tf.width = 20;
        cur_client_count_tf.height = 17;
        cur_client_count_tf.background = false;
        cur_client_count_tf.defaultTextFormat = cur_client_count_fmt;
        cur_client_count_tf.x=47;
        cur_client_count_tf.y=6;

        /* Update the client counter on badge. */
        update_client_count();
    }

    public function display():void
    {
        ui.addChild(new BadgeImage());
        /* Tried unsuccessfully to add counter to badge. */
        /* For now, need two addChilds :( */
        ui.addChild(tot_client_count_tf);
        ui.addChild(cur_client_count_tf);
    }

    public function get num_proxy_pairs():uint
    {
        return _num_proxy_pairs;
    }

    public function set num_proxy_pairs(amount:uint):void
    {
        _num_proxy_pairs = amount;
        update_client_count();
    }

    public function get total_proxy_pairs():uint
    {
        return _total_proxy_pairs;
    }

    public function set total_proxy_pairs(amount:uint):void
    {
        _total_proxy_pairs = amount;
        /* note: doesn't update, so be sure to update this
           before you update num_proxy_pairs! */
    }

    private function update_client_count():void
    {
        /* Update total client count. */
        if (String(total_proxy_pairs).length == 1)
            tot_client_count_tf.text = "0" + String(total_proxy_pairs);
        else
            tot_client_count_tf.text = String(total_proxy_pairs);

        /* Update current client count. */
        cur_client_count_tf.text = "";
        for(var i:Number = 0; i < num_proxy_pairs; i++)
            cur_client_count_tf.appendText(".");
    }
}

Put ++ where I meant --

Put ++ where I meant --


/* 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.controller {
    import org.mangui.hls.HLS;
    import org.mangui.hls.HLSSettings;
    import org.mangui.hls.event.HLSEvent;

    CONFIG::LOGGING {
    import org.mangui.hls.utils.Log;
    }

    /** Class that manages automatic min/low buffer len **/
    public class AutoBufferController {
        /** Reference to the HLS controller. **/
        private var _hls : HLS;
        // max nb of samples used for bw checking. the bigger it is, the more conservative it is.
        private static const MAX_SAMPLES : int = 30;
        private var _bw : Vector.<Number>;
        private var _nb_samples : uint;
        private var _targetduration : Number;
        private var _minBufferLength : Number;

        /** Create the loader. **/
        public function AutoBufferController(hls : HLS) : void {
            _hls = hls;
            _hls.addEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler);
            _hls.addEventListener(HLSEvent.TAGS_LOADED, _fragmentLoadedHandler);
            _hls.addEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentLoadedHandler);
        };

        public function dispose() : void {
            _hls.removeEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler);
            _hls.removeEventListener(HLSEvent.TAGS_LOADED, _fragmentLoadedHandler);
            _hls.removeEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentLoadedHandler);
        }

        public function get minBufferLength() : Number {
            return _minBufferLength;
        }

        private function _manifestLoadedHandler(event : HLSEvent) : void {
            _nb_samples = 0;
            _targetduration = event.levels[_hls.startlevel].targetduration;
            _bw = new Vector.<Number>(MAX_SAMPLES);
            _minBufferLength = _targetduration;
        };

        private function _fragmentLoadedHandler(event : HLSEvent) : void {
            var cur_bw : Number = event.loadMetrics.bandwidth;
            _bw[_nb_samples % MAX_SAMPLES] = cur_bw;
            _nb_samples++;

            // compute min bw on MAX_SAMPLES
            var min_bw : Number = Number.POSITIVE_INFINITY;
            var samples_max : int = Math.min(_nb_samples, MAX_SAMPLES);
            for (var i : int = 0; i < samples_max; i++) {
                min_bw = Math.min(min_bw, _bw[i]);
            }

            // give more weight to current bandwidth
            var bw_ratio : Number = 2 * cur_bw / (min_bw + cur_bw);

            /* predict time to dl next segment using a conservative approach.
             *
             * heuristic is as follow :
             *
             * time to dl next segment = time to dl current segment *  (playlist target duration / current segment duration) * bw_ratio
             *                           \---------------------------------------------------------------------------------/
             *                                  this part is a simple rule by 3, assuming we keep same dl bandwidth
             *  bw ratio is the conservative factor, assuming that next segment will be downloaded with min bandwidth
             */
            _minBufferLength = event.loadMetrics.frag_processing_time * (_targetduration / event.loadMetrics.frag_duration) * bw_ratio;
            // avoid min > max
            if (HLSSettings.maxBufferLength) {
                _minBufferLength = Math.min(HLSSettings.maxBufferLength, _minBufferLength);
            }
            CONFIG::LOGGING {
            Log.debug("AutoBufferManager:minBufferLength:" + _minBufferLength);
            }
        };
    }
}

/* 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.controller {
    import org.mangui.hls.HLS;
    import org.mangui.hls.HLSSettings;
    import org.mangui.hls.event.HLSEvent;

    CONFIG::LOGGING {
    import org.mangui.hls.utils.Log;
    }

    /** Class that manages automatic min/low buffer len **/
    public class AutoBufferController {
        /** Reference to the HLS controller. **/
        private var _hls : HLS;
        // max nb of samples used for bw checking. the bigger it is, the more conservative it is.
        private static const MAX_SAMPLES : int = 30;
        private var _bw : Vector.<Number>;
        private var _nb_samples : uint;
        private var _targetduration : Number;
        private var _minBufferLength : Number;

        /** Create the loader. **/
        public function AutoBufferController(hls : HLS) : void {
            _hls = hls;
            _hls.addEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler);
            _hls.addEventListener(HLSEvent.TAGS_LOADED, _fragmentLoadedHandler);
            _hls.addEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentLoadedHandler);
        };

        public function dispose() : void {
            _hls.removeEventListener(HLSEvent.MANIFEST_LOADED, _manifestLoadedHandler);
            _hls.removeEventListener(HLSEvent.TAGS_LOADED, _fragmentLoadedHandler);
            _hls.removeEventListener(HLSEvent.FRAGMENT_LOADED, _fragmentLoadedHandler);
        }

        public function get minBufferLength() : Number {
            return _minBufferLength;
        }

        private function _manifestLoadedHandler(event : HLSEvent) : void {
            _nb_samples = 0;
            _targetduration = event.levels[_hls.startlevel].targetduration;
            _bw = new Vector.<Number>(MAX_SAMPLES);
            _minBufferLength = _targetduration;
        };

        private function _fragmentLoadedHandler(event : HLSEvent) : void {
            var cur_bw : Number = event.loadMetrics.bandwidth;
            _bw[_nb_samples % MAX_SAMPLES] = cur_bw;
            _nb_samples++;

            // compute min bw on MAX_SAMPLES
            var min_bw : Number = Number.POSITIVE_INFINITY;
            var samples_max : int = Math.min(_nb_samples, MAX_SAMPLES);
            for (var i : int = 0; i < samples_max; i++) {
                min_bw = Math.min(min_bw, _bw[i]);
            }

            // give more weight to current bandwidth
            var bw_ratio : Number = 2 * cur_bw / (min_bw + cur_bw);

            /* predict time to dl next segment using a conservative approach.
             *
             * heuristic is as follow :
             *
             * time to dl next segment = time to dl current segment *  (playlist target duration / current segment duration) * bw_ratio
             *                           \---------------------------------------------------------------------------------/
             *                                  this part is a simple rule by 3, assuming we keep same dl bandwidth
             *  bw ratio is the conservative factor, assuming that next segment will be downloaded with min bandwidth
             */
            _minBufferLength = event.loadMetrics.frag_processing_time * (_targetduration / event.loadMetrics.frag_duration) * bw_ratio;
            // avoid min > max
            if (HLSSettings.maxBufferLength) {
                _minBufferLength = Math.min(HLSSettings.maxBufferLength, _minBufferLength);
            }
            CONFIG::LOGGING {
            Log.debug2("AutoBufferController:minBufferLength:" + _minBufferLength);
            }
        };
    }
}

reduce verbosity

reduce verbosity


////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2008-2013 Esri. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
package com.esri.builder.controllers
{

import com.esri.builder.eventbus.AppEvent;
import com.esri.builder.model.LocaleModel;
import com.esri.builder.model.Model;
import com.esri.builder.model.WidgetTypeRegistryModel;
import com.esri.builder.supportClasses.LogUtil;

import mx.core.FlexGlobals;
import mx.logging.ILogger;
import mx.logging.Log;
import mx.resources.ResourceManager;
import mx.styles.CSSStyleDeclaration;
import mx.styles.IStyleManager2;
import mx.styles.StyleManager;

public class LocaleController
{
    private static const LOG:ILogger = LogUtil.createLogger(LocaleController);

    public function LocaleController()
    {
        AppEvent.addListener(AppEvent.SETTINGS_SAVED, settingsChangeHandler, false, 500); //high priority to prevent app using outdated locale settings
    }

    private function settingsChangeHandler(event:AppEvent):void
    {
        updateApplicationLocale();
    }

    private function updateApplicationLocale():void
    {
        var selectedLocale:String = Model.instance.locale;
        var localeChain:Array = ResourceManager.getInstance().localeChain;

        var selectedLocaleIndex:int = localeChain.indexOf(selectedLocale);
        localeChain.splice(selectedLocaleIndex, 1);
        localeChain.unshift(selectedLocale);

        if (Log.isDebug())
        {
            LOG.debug("Updating application locale: {0}", selectedLocale);
        }

        ResourceManager.getInstance().update();
        applyLocaleLayoutDirection(selectedLocale);
        setPreferredLocaleFonts(selectedLocale);
        setLocaleSpecificStyles(selectedLocale);
    }

    private function applyLocaleLayoutDirection(selectedLocale:String):void
    {
        var currentLayoutDirection:String = FlexGlobals.topLevelApplication.getStyle('layoutDirection');
        var localeLayoutDirection:String = LocaleModel.getInstance().getLocaleLayoutDirection(selectedLocale);
        if (localeLayoutDirection != currentLayoutDirection)
        {
            FlexGlobals.topLevelApplication.setStyle('direction', localeLayoutDirection);
            FlexGlobals.topLevelApplication.setStyle('layoutDirection', localeLayoutDirection);
        }

        var currentLocale:String = FlexGlobals.topLevelApplication.getStyle('locale');
        if (selectedLocale != currentLocale)
        {
            FlexGlobals.topLevelApplication.setStyle('locale', selectedLocale);
            WidgetTypeRegistryModel.getInstance().widgetTypeRegistry.sort();
        }
    }

    private function setPreferredLocaleFonts(selectedLocale:String):void
    {
        if (selectedLocale == 'ar')
        {
            FlexGlobals.topLevelApplication.setStyle('fontFamily', toFontFamily(LocaleModel.PREFERRED_ARABIC_FONTS));
        }
        else if (selectedLocale == 'ja_JP')
        {
            FlexGlobals.topLevelApplication.setStyle('fontFamily', toFontFamily(LocaleModel.PREFERRED_JAPANESE_FONTS));
        }
        else if (selectedLocale == 'ko_KR')
        {
            FlexGlobals.topLevelApplication.setStyle('fontFamily', toFontFamily(LocaleModel.PREFERRED_KOREAN_FONTS));
        }
        else if (selectedLocale == 'zh_CN')
        {
            FlexGlobals.topLevelApplication.setStyle('fontFamily', toFontFamily(LocaleModel.PREFERRED_CHINESE_FONTS));
        }
        else
        {
            FlexGlobals.topLevelApplication.setStyle('fontFamily', undefined);
        }

        if (Log.isDebug())
        {
            LOG.debug("Current font family: {0}", FlexGlobals.topLevelApplication.getStyle('fontFamily'));
        }
    }

    private function toFontFamily(fontNames:Array):String
    {
        if (!fontNames)
        {
            return "";
        }

        var fallbackFontName:String = "_sans";
        fontNames.push(fallbackFontName);

        return fontNames.join(',');
    }

    private function setLocaleSpecificStyles(locale:String):void
    {
        var topLevelStyleManager:IStyleManager2 = StyleManager.getStyleManager(null);

        var isItalicInappropriateLocale:Boolean =
            locale == 'ja_JP' || locale == 'ko_KR' || locale == 'zh_CN'
            || locale == 'ar' || locale == 'he_IL';

        var emphasisStyle:CSSStyleDeclaration = topLevelStyleManager.getStyleDeclaration(".emphasisText");
        var emphasisFontStyle:String = isItalicInappropriateLocale ? "normal" : "italic";
        emphasisStyle.setStyle("fontStyle", emphasisFontStyle);

        var isBoldInappropriateLocale:Boolean =
            locale == 'ja_JP' || locale == 'ko_KR' || locale == 'zh_CN';

        var boldStyle:CSSStyleDeclaration = topLevelStyleManager.getStyleDeclaration(".boldText");
        var emphasisFontWeight:String = isBoldInappropriateLocale ? "normal" : "bold";
        boldStyle.setStyle("fontWeight", emphasisFontWeight);
    }
}
}

////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2008-2013 Esri. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
package com.esri.builder.controllers
{

import com.esri.builder.eventbus.AppEvent;
import com.esri.builder.model.LocaleModel;
import com.esri.builder.model.Model;
import com.esri.builder.model.WidgetTypeRegistryModel;
import com.esri.builder.supportClasses.LogUtil;

import mx.core.FlexGlobals;
import mx.logging.ILogger;
import mx.logging.Log;
import mx.resources.ResourceManager;
import mx.styles.CSSStyleDeclaration;
import mx.styles.IStyleManager2;
import mx.styles.StyleManager;

public class LocaleController
{
    private static const LOG:ILogger = LogUtil.createLogger(LocaleController);

    public function LocaleController()
    {
        AppEvent.addListener(AppEvent.SETTINGS_SAVED, settingsChangeHandler, false, 500); //high priority to prevent app using outdated locale settings
    }

    private function settingsChangeHandler(event:AppEvent):void
    {
        updateApplicationLocale();
    }

    private function updateApplicationLocale():void
    {
        var selectedLocale:String = Model.instance.locale;
        var localeChain:Array = ResourceManager.getInstance().localeChain;

        var selectedLocaleIndex:int = localeChain.indexOf(selectedLocale);
        localeChain.splice(selectedLocaleIndex, 1);
        localeChain.unshift(selectedLocale);

        if (Log.isDebug())
        {
            LOG.debug("Updating application locale: {0}", selectedLocale);
        }

        ResourceManager.getInstance().update();
        applyLocaleLayoutDirection(selectedLocale);
        setPreferredLocaleFonts(selectedLocale);
        setLocaleSpecificStyles(selectedLocale);
    }

    private function applyLocaleLayoutDirection(selectedLocale:String):void
    {
        var currentLayoutDirection:String = FlexGlobals.topLevelApplication.getStyle('layoutDirection');
        var localeLayoutDirection:String = LocaleModel.getInstance().getLocaleLayoutDirection(selectedLocale);
        if (localeLayoutDirection != currentLayoutDirection)
        {
            FlexGlobals.topLevelApplication.setStyle('direction', localeLayoutDirection);
            FlexGlobals.topLevelApplication.setStyle('layoutDirection', localeLayoutDirection);
        }

        var currentLocale:String = FlexGlobals.topLevelApplication.getStyle('locale');
        if (selectedLocale != currentLocale)
        {
            FlexGlobals.topLevelApplication.setStyle('locale', selectedLocale);
            WidgetTypeRegistryModel.getInstance().widgetTypeRegistry.sort();
        }
    }

    private function setPreferredLocaleFonts(selectedLocale:String):void
    {
        var mainApp:Object = FlexGlobals.topLevelApplication;

        if (selectedLocale == 'ar')
        {
            mainApp.setStyle('fontFamily', toFontFamily(LocaleModel.PREFERRED_ARABIC_FONTS));
        }
        else if (selectedLocale == 'ja_JP')
        {
            mainApp.setStyle('fontFamily', toFontFamily(LocaleModel.PREFERRED_JAPANESE_FONTS));
        }
        else if (selectedLocale == 'ko_KR')
        {
            mainApp.setStyle('fontFamily', toFontFamily(LocaleModel.PREFERRED_KOREAN_FONTS));
        }
        else if (selectedLocale == 'zh_CN')
        {
            mainApp.setStyle('fontFamily', toFontFamily(LocaleModel.PREFERRED_CHINESE_FONTS));
        }
        else
        {
            mainApp.setStyle('fontFamily', undefined);
        }

        if (Log.isDebug())
        {
            LOG.debug("Current font family: {0}", mainApp.getStyle('fontFamily'));
        }
    }

    private function toFontFamily(fontNames:Array):String
    {
        if (!fontNames)
        {
            return "";
        }

        var fallbackFontName:String = "_sans";
        fontNames.push(fallbackFontName);

        return fontNames.join(',');
    }

    private function setLocaleSpecificStyles(locale:String):void
    {
        var topLevelStyleManager:IStyleManager2 = StyleManager.getStyleManager(null);

        var isItalicInappropriateLocale:Boolean =
            locale == 'ja_JP' || locale == 'ko_KR' || locale == 'zh_CN'
            || locale == 'ar' || locale == 'he_IL';

        var emphasisStyle:CSSStyleDeclaration = topLevelStyleManager.getStyleDeclaration(".emphasisText");
        var emphasisFontStyle:String = isItalicInappropriateLocale ? "normal" : "italic";
        emphasisStyle.setStyle("fontStyle", emphasisFontStyle);

        var isBoldInappropriateLocale:Boolean =
            locale == 'ja_JP' || locale == 'ko_KR' || locale == 'zh_CN';

        var boldStyle:CSSStyleDeclaration = topLevelStyleManager.getStyleDeclaration(".boldText");
        var emphasisFontWeight:String = isBoldInappropriateLocale ? "normal" : "bold";
        boldStyle.setStyle("fontWeight", emphasisFontWeight);
    }
}
}

Clean up.

Clean up.


package aerys.minko.render.material.phong
{
	import aerys.minko.render.RenderTarget;
	import aerys.minko.render.material.basic.BasicShader;
	import aerys.minko.render.resource.texture.ITextureResource;
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.part.phong.LightAwareDiffuseShaderPart;
	import aerys.minko.render.shader.part.phong.PhongShaderPart;

	public class PhongShader extends BasicShader
	{
		private var _diffuse	: LightAwareDiffuseShaderPart;
		private var _phong		: PhongShaderPart;

		public function PhongShader(renderTarget	: RenderTarget		= null,
									priority		: Number			= 0.)
		{
			super(renderTarget, priority);

			// init shader parts
			_diffuse	= new LightAwareDiffuseShaderPart(this);
			_phong		= new PhongShaderPart(this);
		}

		override protected function getPixelColor() : SFloat
		{
			var color	 : SFloat = _diffuse.getDiffuseColor();
			var lighting : SFloat = _phong.getLightingColor();

			color = float4(multiply(lighting, color.rgb), color.a);

			return color;
		}
	}
}

package aerys.minko.render.material.phong
{
	import aerys.minko.render.RenderTarget;
	import aerys.minko.render.material.basic.BasicShader;
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.part.phong.LightAwareDiffuseShaderPart;
	import aerys.minko.render.shader.part.phong.PhongShaderPart;

	public class PhongShader extends BasicShader
	{
		private var _diffuse	: LightAwareDiffuseShaderPart;
		private var _phong		: PhongShaderPart;

		public function PhongShader(renderTarget	: RenderTarget		= null,
									priority		: Number			= 0.)
		{
			super(renderTarget, priority);

			// init shader parts
			_diffuse	= new LightAwareDiffuseShaderPart(this);
			_phong		= new PhongShaderPart(this);
		}

		override protected function getPixelColor() : SFloat
		{
			var color	 : SFloat = _diffuse.getDiffuseColor();
			var lighting : SFloat = _phong.getLightingColor();

			color = float4(multiply(lighting, color.rgb), color.a);

			return color;
		}
	}
}

remove useless imports

remove useless imports


/*
*  	Graffiti Touch
*  	______________________________________________________________________
*  	www.nocircleno.com/graffiti/
*/

/*
* 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* 	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* 	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* 	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* 	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* 	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* 	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* 	OTHER DEALINGS IN THE SOFTWARE.
*/
package com.nocircleno.graffiti.tools.brushes
{
   import com.nocircleno.graffiti.tools.BitmapCacheRenderMode;

	/**
	* Brush Class allows the user to paint anti-alias shapes to the Canvas.
	*
	* @langversion 3.0
   * @playerversion Flash 10 AIR 1.5
	*/
	public class Brush
   {
      protected var _size:Number;
      protected var _halfSize:Number;
      protected var _fourthSize:Number;
      protected var _eighthSize:Number;
      protected var _sixteenthSize:Number;
      protected var _color:uint;
      protected var _alpha:Number;
      protected var _bitmapCacheRenderMode:String;
      protected var commands:Vector.<int> = new Vector.<int>();
      protected var drawingData:Vector.<Number> = new Vector.<Number>();
      protected var _numberInteractions:int;

		/**
		* The Brush constructor.
		*
		* @param brushSize Size of the brush.
		* @param brushColor Color of the brush.
		* @param brushAlpha Alpha value of the brush.
		* @param bitmapCacheRenderMode Render mode used when caching brush content to canvas bitmap.
		*/
		public function Brush(brushSize:Number = 4, brushColor:uint = 0x000000, brushAlpha:Number = 1, bitmapCacheRenderMode:String = null)
      {
			size = brushSize;
			color = brushColor;
			alpha = brushAlpha;
			bitmapCacheRenderMode = bitmapCacheRenderMode;
		}

      /**
       * Drawing Mode
       */
      public function set bitmapCacheRenderMode(bitmapCacheRenderMode:String):void
      {
         if(bitmapCacheRenderMode != null && BitmapCacheRenderMode.validMode(bitmapCacheRenderMode)) {
            _bitmapCacheRenderMode = bitmapCacheRenderMode;
         } else {
            _bitmapCacheRenderMode = BitmapCacheRenderMode.NORMAL;
         }
      }

      public function get bitmapCacheRenderMode():String
      {
         return _bitmapCacheRenderMode;
      }

      /**
       * The clearLastPath method will reset the drawing data held by the brush.
       */
      public function clearLastPath():void
      {
         commands.length = 0;
         drawingData.length = 0;
      }

		/**
		* Size of the Brush
		*/
		public function set size(brushSize:Number):void
      {
			if(brushSize > 0)
         {
				// set brush size
				_size = brushSize;

				// calcuate divisions
				_halfSize = _size * .5;
				_fourthSize = _size * .25;
				_eighthSize = _size * .125;
				_sixteenthSize = _size * 0.0625;
			}
		}

		public function get size():Number
      {
			return _size;
		}

		/**
		* Color of the Brush
		*/
		public function set color(brushColor:uint):void
      {
			_color = brushColor;
		}

		public function get color():uint
      {
			return _color;
		}

		/**
		* Alpha of the Brush
		*/
		public function set alpha(brushAlpha:Number):void
      {
			if(brushAlpha < 0)
         {
				brushAlpha = 0;
			}
         else if(brushAlpha > 1)
         {
				brushAlpha = 1;
			}

			_alpha = brushAlpha;
		}

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

/*
*  	Graffiti Touch
*  	______________________________________________________________________
*  	www.nocircleno.com/graffiti/
*/

/*
* 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* 	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* 	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* 	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* 	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* 	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* 	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* 	OTHER DEALINGS IN THE SOFTWARE.
*/
package com.nocircleno.graffiti.tools.brushes
{
   import com.nocircleno.graffiti.tools.BitmapCacheRenderMode;

	/**
	* Brush Class allows the user to paint anti-alias shapes to the Canvas.
	*
	* @langversion 3.0
   * @playerversion Flash 10 AIR 1.5
	*/
	public class Brush
   {
      protected var _size:Number;
      protected var _halfSize:Number;
      protected var _fourthSize:Number;
      protected var _eighthSize:Number;
      protected var _sixteenthSize:Number;
      protected var _color:uint;
      protected var _alpha:Number;
      protected var _bitmapCacheRenderMode:String;
      protected var commands:Vector.<int> = new Vector.<int>();
      protected var drawingData:Vector.<Number> = new Vector.<Number>();
      protected var _numberInteractions:int;

		/**
		* The Brush constructor.
		*
		* @param brushSize Size of the brush.
		* @param brushColor Color of the brush.
		* @param brushAlpha Alpha value of the brush.
		* @param bitmapCacheRenderMode Render mode used when caching brush content to canvas bitmap.
		*/
		public function Brush(brushSize:Number = 4, brushColor:uint = 0x000000, brushAlpha:Number = 1, brushBitmapCacheRenderMode:String = null)
      {
			size = brushSize;
			color = brushColor;
			alpha = brushAlpha;
			bitmapCacheRenderMode = brushBitmapCacheRenderMode;
		}

      /**
       * Drawing Mode
       */
      public function set bitmapCacheRenderMode(bitmapCacheRenderMode:String):void
      {
         if(bitmapCacheRenderMode != null && BitmapCacheRenderMode.validMode(bitmapCacheRenderMode)) {
            _bitmapCacheRenderMode = bitmapCacheRenderMode;
         } else {
            _bitmapCacheRenderMode = BitmapCacheRenderMode.NORMAL;
         }
      }

      public function get bitmapCacheRenderMode():String
      {
         return _bitmapCacheRenderMode;
      }

      /**
       * The clearLastPath method will reset the drawing data held by the brush.
       */
      public function clearLastPath():void
      {
         commands.length = 0;
         drawingData.length = 0;
      }

		/**
		* Size of the Brush
		*/
		public function set size(brushSize:Number):void
      {
			if(brushSize > 0)
         {
				// set brush size
				_size = brushSize;

				// calcuate divisions
				_halfSize = _size * .5;
				_fourthSize = _size * .25;
				_eighthSize = _size * .125;
				_sixteenthSize = _size * 0.0625;
			}
		}

		public function get size():Number
      {
			return _size;
		}

		/**
		* Color of the Brush
		*/
		public function set color(brushColor:uint):void
      {
			_color = brushColor;
		}

		public function get color():uint
      {
			return _color;
		}

		/**
		* Alpha of the Brush
		*/
		public function set alpha(brushAlpha:Number):void
      {
			if(brushAlpha < 0)
         {
				brushAlpha = 0;
			}
         else if(brushAlpha > 1)
         {
				brushAlpha = 1;
			}

			_alpha = brushAlpha;
		}

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

Fix Eraser mode #5

Fix Eraser mode #5

Parameter was not visible - Erase mode now work fine


/*
 *  FRESteamWorks.as
 *  This file is part of FRESteamWorks.
 *
 *  Created by Ventero <http://github.com/Ventero>
 *  Copyright (c) 2012-2013 Level Up Labs, LLC. All rights reserved.
 */

package com.amanitadesign.steam {
	import flash.desktop.NativeProcess;
	import flash.desktop.NativeProcessStartupInfo;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.StatusEvent;
	import flash.filesystem.File;
	import flash.utils.ByteArray;
	import flash.utils.IDataInput;
	import flash.utils.IDataOutput;
	import flash.utils.clearInterval;
	import flash.utils.setInterval;

	public class FRESteamWorks extends EventDispatcher {
		[Event(name="steam_response", type="com.amanitadesign.steam.SteamEvent")]

		private static const PATH:String = "NativeApps/Linux/APIWrapper";

		private var _file:File;
		private var _process:NativeProcess;
		private var _tm:int;
		private var _error:Boolean = false;

		public var isReady:Boolean = false;

		private static const AIRSteam_Init:int = 0;
		private static const AIRSteam_RunCallbacks:int = 1;
		private static const AIRSteam_RequestStats:int = 2;
		private static const AIRSteam_SetAchievement:int = 3;
		private static const AIRSteam_ClearAchievement:int = 4;
		private static const AIRSteam_IsAchievement:int = 5;
		private static const AIRSteam_GetStatInt:int = 6;
		private static const AIRSteam_GetStatFloat:int = 7;
		private static const AIRSteam_SetStatInt:int = 8;
		private static const AIRSteam_SetStatFloat:int = 9;
		private static const AIRSteam_StoreStats:int = 10;
		private static const AIRSteam_ResetAllStats:int = 11;
		private static const AIRSteam_GetFileCount:int = 12;
		private static const AIRSteam_GetFileSize:int = 13;
		private static const AIRSteam_FileExists:int = 14;
		private static const AIRSteam_FileWrite:int = 15;
		private static const AIRSteam_FileRead:int = 16;
		private static const AIRSteam_FileDelete:int = 17;
		private static const AIRSteam_IsCloudEnabledForApp:int = 18;
		private static const AIRSteam_SetCloudEnabledForApp:int = 19;
		private static const AIRSteam_GetUserID:int = 20;
		private static const AIRSTeam_GetPersonaName:int = 21;

		public function FRESteamWorks (target:IEventDispatcher = null) {
			_file = File.applicationDirectory.resolvePath(PATH);
			_process = new NativeProcess();
			_process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, eventDispatched);
			_process.addEventListener(IOErrorEvent.STANDARD_INPUT_IO_ERROR, errorCallback);
			super(target);
		}

		public function dispose():void {
			if(_process.running) {
				_process.closeInput();
				_process.exit();
			}
			clearInterval(_tm);
			isReady = false;
		}

		private function startProcess():void {
			var startupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
			startupInfo.executable = _file;

			_process.start(startupInfo);
		}

		public function init():Boolean {
			if(!_file.exists) return false;
			startProcess();
			if(!_process.running) return false;

			if(!callWrapper(AIRSteam_Init)) return false;
			isReady = readBoolResponse();
			if(isReady) _tm = setInterval(runCallbacks, 100);
			return isReady;
		}

		private function errorCallback(e:IOErrorEvent):void {
			_error = true;
			// the process doesn't accept our input anymore, so just stop it
			clearInterval(_tm);

			if(_process.running) {
				try {
					_process.closeInput();
				} catch(e:*) {
					// no-op
				}

				_process.exit();
			}
		}

		private function callWrapper(funcName:int, params:Array = null):Boolean {
			_error = false;
			if(!_process.running) return false;

			var stdin:IDataOutput = _process.standardInput;
			stdin.writeUTFBytes(funcName + "\n");

			if (params) {
				for(var i:int = 0; i < params.length; ++i) {
					if(params[i] is ByteArray) {
						var length:uint = params[i].length;
						// length + 1 for the added newline
						stdin.writeUTFBytes(String(length + 1) + "\n");
						stdin.writeBytes(params[i]);
						stdin.writeUTFBytes("\n");
					} else {
						stdin.writeUTFBytes(String(params[i]) + "\n");
					}
				}
			}

			return !_error;
		}

		private function waitForData(output:IDataInput):uint {
			while(!output.bytesAvailable) {
				// wait
				if(!_process.running) return 0;
			}

			return output.bytesAvailable;
		}

		private function readBoolResponse():Boolean {
			if(!_process.running) return false;
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(1);
			return (response == "t");
		}

		private function readIntResponse():int {
			if(!_process.running) return 0;
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(avail);
			return parseInt(response, 10);
		}

		private function readFloatResponse():Number {
			if(!_process.running) return 0.0;
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(avail)
			return parseFloat(response);
		}

		private function readStringResponse():String {
			if(!_process.running) return "";
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(avail)
			return response;
		}

		private function eventDispatched(e:ProgressEvent):void {
			var stderr:IDataInput = _process.standardError;
			var avail:uint = stderr.bytesAvailable;
			var data:String = stderr.readUTFBytes(avail);

			var pattern:RegExp = /__event__<(\d+),(\d+)>/g;
			var result:Object;
			while((result = pattern.exec(data))) {
				var req_type:int = new int(result[1]);
				var response:int = new int(result[2]);
				var steamEvent:SteamEvent = new SteamEvent(SteamEvent.STEAM_RESPONSE, req_type, response);
				dispatchEvent(steamEvent);
			}
		}

		public function requestStats():Boolean {
			if(!callWrapper(AIRSteam_RequestStats)) return false;
			return readBoolResponse();
		}

		public function runCallbacks():Boolean {
			if(!callWrapper(AIRSteam_RunCallbacks)) return false;
			return true;
		}

		public function getUserID():String {
			if(!callWrapper(AIRSteam_GetUserID)) return "";
			return readStringResponse();
		}

		public function getPersonaName():String {
			if(!callWrapper(AIRSTeam_GetPersonaName)) return "";
			return readStringResponse();
		}

		public function setAchievement(id:String):Boolean {
			if(!callWrapper(AIRSteam_SetAchievement, [id])) return false;
			return readBoolResponse();
		}

		public function clearAchievement(id:String):Boolean {
			if(!callWrapper(AIRSteam_ClearAchievement, [id])) return false;
			return readBoolResponse();
		}

		public function isAchievement(id:String):Boolean {
			if(!callWrapper(AIRSteam_IsAchievement, [id])) return false;
			return readBoolResponse();
		}

		public function getStatInt(id:String):int {
			if(!callWrapper(AIRSteam_GetStatInt, [id])) return 0;
			return readIntResponse();
		}

		public function getStatFloat(id:String):Number {
			if(!callWrapper(AIRSteam_GetStatFloat, [id])) return 0.0;
			return readFloatResponse();
		}

		public function setStatInt(id:String, value:int):Boolean {
			if(!callWrapper(AIRSteam_SetStatInt, [id, value])) return false;
			return readBoolResponse();
		}

		public function setStatFloat(id:String, value:Number):Boolean {
			if(!callWrapper(AIRSteam_SetStatFloat, [id, value])) return false;
			return readBoolResponse();
		}

		public function storeStats():Boolean {
			if(!callWrapper(AIRSteam_StoreStats)) return false;
			return readBoolResponse();
		}

		public function resetAllStats(bAchievementsToo:Boolean):Boolean {
			if(!callWrapper(AIRSteam_ResetAllStats, [bAchievementsToo])) return false;
			return readBoolResponse();
		}

		public function getFileCount():int {
			if(!callWrapper(AIRSteam_GetFileCount)) return 0;
			return readIntResponse();
		}

		public function getFileSize(fileName:String):int {
			if(!callWrapper(AIRSteam_GetFileSize, [fileName])) return 0;
			return readIntResponse();
		}

		public function fileExists(fileName:String):Boolean {
			if(!callWrapper(AIRSteam_FileExists, [fileName])) return false;
			return readBoolResponse();
		}

		public function fileWrite(fileName:String, data:ByteArray):Boolean {
			if(!callWrapper(AIRSteam_FileWrite, [fileName, data])) return false;
			return readBoolResponse();
		}

		public function fileRead(fileName:String, data:ByteArray):Boolean {
			if(!callWrapper(AIRSteam_FileRead, [fileName])) return false;

			var success:Boolean = readBoolResponse();
			if(success) {
				var content:String = readStringResponse();
				data.writeUTFBytes(content);
				data.position = 0;
			}

			return success;
		}

		public function fileDelete(fileName:String):Boolean {
			if(!callWrapper(AIRSteam_FileDelete, [fileName])) return false;
			return readBoolResponse();
		}

		public function isCloudEnabledForApp():Boolean {
			if(!callWrapper(AIRSteam_IsCloudEnabledForApp)) return false;
			return readBoolResponse();
		}

		public function setCloudEnabledForApp(enabled:Boolean):Boolean {
			if(!callWrapper(AIRSteam_SetCloudEnabledForApp, [enabled])) return false;
			return readBoolResponse();
		}
	}
}

/*
 *  FRESteamWorks.as
 *  This file is part of FRESteamWorks.
 *
 *  Created by Ventero <http://github.com/Ventero>
 *  Copyright (c) 2012-2013 Level Up Labs, LLC. All rights reserved.
 */

package com.amanitadesign.steam {
	import flash.desktop.NativeProcess;
	import flash.desktop.NativeProcessStartupInfo;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.StatusEvent;
	import flash.filesystem.File;
	import flash.utils.ByteArray;
	import flash.utils.IDataInput;
	import flash.utils.IDataOutput;
	import flash.utils.clearInterval;
	import flash.utils.setInterval;

	public class FRESteamWorks extends EventDispatcher {
		[Event(name="steam_response", type="com.amanitadesign.steam.SteamEvent")]

		private static const PATH:String = "NativeApps/Linux/APIWrapper";

		private var _file:File;
		private var _process:NativeProcess;
		private var _tm:int;
		private var _error:Boolean = false;

		public var isReady:Boolean = false;

		private static const AIRSteam_Init:int = 0;
		private static const AIRSteam_RunCallbacks:int = 1;
		private static const AIRSteam_RequestStats:int = 2;
		private static const AIRSteam_SetAchievement:int = 3;
		private static const AIRSteam_ClearAchievement:int = 4;
		private static const AIRSteam_IsAchievement:int = 5;
		private static const AIRSteam_GetStatInt:int = 6;
		private static const AIRSteam_GetStatFloat:int = 7;
		private static const AIRSteam_SetStatInt:int = 8;
		private static const AIRSteam_SetStatFloat:int = 9;
		private static const AIRSteam_StoreStats:int = 10;
		private static const AIRSteam_ResetAllStats:int = 11;
		private static const AIRSteam_GetFileCount:int = 12;
		private static const AIRSteam_GetFileSize:int = 13;
		private static const AIRSteam_FileExists:int = 14;
		private static const AIRSteam_FileWrite:int = 15;
		private static const AIRSteam_FileRead:int = 16;
		private static const AIRSteam_FileDelete:int = 17;
		private static const AIRSteam_IsCloudEnabledForApp:int = 18;
		private static const AIRSteam_SetCloudEnabledForApp:int = 19;
		private static const AIRSteam_GetUserID:int = 20;
		private static const AIRSteam_GetPersonaName:int = 21;

		public function FRESteamWorks (target:IEventDispatcher = null) {
			_file = File.applicationDirectory.resolvePath(PATH);
			_process = new NativeProcess();
			_process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, eventDispatched);
			_process.addEventListener(IOErrorEvent.STANDARD_INPUT_IO_ERROR, errorCallback);
			super(target);
		}

		public function dispose():void {
			if(_process.running) {
				_process.closeInput();
				_process.exit();
			}
			clearInterval(_tm);
			isReady = false;
		}

		private function startProcess():void {
			var startupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
			startupInfo.executable = _file;

			_process.start(startupInfo);
		}

		public function init():Boolean {
			if(!_file.exists) return false;
			startProcess();
			if(!_process.running) return false;

			if(!callWrapper(AIRSteam_Init)) return false;
			isReady = readBoolResponse();
			if(isReady) _tm = setInterval(runCallbacks, 100);
			return isReady;
		}

		private function errorCallback(e:IOErrorEvent):void {
			_error = true;
			// the process doesn't accept our input anymore, so just stop it
			clearInterval(_tm);

			if(_process.running) {
				try {
					_process.closeInput();
				} catch(e:*) {
					// no-op
				}

				_process.exit();
			}
		}

		private function callWrapper(funcName:int, params:Array = null):Boolean {
			_error = false;
			if(!_process.running) return false;

			var stdin:IDataOutput = _process.standardInput;
			stdin.writeUTFBytes(funcName + "\n");

			if (params) {
				for(var i:int = 0; i < params.length; ++i) {
					if(params[i] is ByteArray) {
						var length:uint = params[i].length;
						// length + 1 for the added newline
						stdin.writeUTFBytes(String(length + 1) + "\n");
						stdin.writeBytes(params[i]);
						stdin.writeUTFBytes("\n");
					} else {
						stdin.writeUTFBytes(String(params[i]) + "\n");
					}
				}
			}

			return !_error;
		}

		private function waitForData(output:IDataInput):uint {
			while(!output.bytesAvailable) {
				// wait
				if(!_process.running) return 0;
			}

			return output.bytesAvailable;
		}

		private function readBoolResponse():Boolean {
			if(!_process.running) return false;
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(1);
			return (response == "t");
		}

		private function readIntResponse():int {
			if(!_process.running) return 0;
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(avail);
			return parseInt(response, 10);
		}

		private function readFloatResponse():Number {
			if(!_process.running) return 0.0;
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(avail)
			return parseFloat(response);
		}

		private function readStringResponse():String {
			if(!_process.running) return "";
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(avail)
			return response;
		}

		private function eventDispatched(e:ProgressEvent):void {
			var stderr:IDataInput = _process.standardError;
			var avail:uint = stderr.bytesAvailable;
			var data:String = stderr.readUTFBytes(avail);

			var pattern:RegExp = /__event__<(\d+),(\d+)>/g;
			var result:Object;
			while((result = pattern.exec(data))) {
				var req_type:int = new int(result[1]);
				var response:int = new int(result[2]);
				var steamEvent:SteamEvent = new SteamEvent(SteamEvent.STEAM_RESPONSE, req_type, response);
				dispatchEvent(steamEvent);
			}
		}

		public function requestStats():Boolean {
			if(!callWrapper(AIRSteam_RequestStats)) return false;
			return readBoolResponse();
		}

		public function runCallbacks():Boolean {
			if(!callWrapper(AIRSteam_RunCallbacks)) return false;
			return true;
		}

		public function getUserID():String {
			if(!callWrapper(AIRSteam_GetUserID)) return "";
			return readStringResponse();
		}

		public function getPersonaName():String {
			if(!callWrapper(AIRSteam_GetPersonaName)) return "";
			return readStringResponse();
		}

		public function setAchievement(id:String):Boolean {
			if(!callWrapper(AIRSteam_SetAchievement, [id])) return false;
			return readBoolResponse();
		}

		public function clearAchievement(id:String):Boolean {
			if(!callWrapper(AIRSteam_ClearAchievement, [id])) return false;
			return readBoolResponse();
		}

		public function isAchievement(id:String):Boolean {
			if(!callWrapper(AIRSteam_IsAchievement, [id])) return false;
			return readBoolResponse();
		}

		public function getStatInt(id:String):int {
			if(!callWrapper(AIRSteam_GetStatInt, [id])) return 0;
			return readIntResponse();
		}

		public function getStatFloat(id:String):Number {
			if(!callWrapper(AIRSteam_GetStatFloat, [id])) return 0.0;
			return readFloatResponse();
		}

		public function setStatInt(id:String, value:int):Boolean {
			if(!callWrapper(AIRSteam_SetStatInt, [id, value])) return false;
			return readBoolResponse();
		}

		public function setStatFloat(id:String, value:Number):Boolean {
			if(!callWrapper(AIRSteam_SetStatFloat, [id, value])) return false;
			return readBoolResponse();
		}

		public function storeStats():Boolean {
			if(!callWrapper(AIRSteam_StoreStats)) return false;
			return readBoolResponse();
		}

		public function resetAllStats(bAchievementsToo:Boolean):Boolean {
			if(!callWrapper(AIRSteam_ResetAllStats, [bAchievementsToo])) return false;
			return readBoolResponse();
		}

		public function getFileCount():int {
			if(!callWrapper(AIRSteam_GetFileCount)) return 0;
			return readIntResponse();
		}

		public function getFileSize(fileName:String):int {
			if(!callWrapper(AIRSteam_GetFileSize, [fileName])) return 0;
			return readIntResponse();
		}

		public function fileExists(fileName:String):Boolean {
			if(!callWrapper(AIRSteam_FileExists, [fileName])) return false;
			return readBoolResponse();
		}

		public function fileWrite(fileName:String, data:ByteArray):Boolean {
			if(!callWrapper(AIRSteam_FileWrite, [fileName, data])) return false;
			return readBoolResponse();
		}

		public function fileRead(fileName:String, data:ByteArray):Boolean {
			if(!callWrapper(AIRSteam_FileRead, [fileName])) return false;

			var success:Boolean = readBoolResponse();
			if(success) {
				var content:String = readStringResponse();
				data.writeUTFBytes(content);
				data.position = 0;
			}

			return success;
		}

		public function fileDelete(fileName:String):Boolean {
			if(!callWrapper(AIRSteam_FileDelete, [fileName])) return false;
			return readBoolResponse();
		}

		public function isCloudEnabledForApp():Boolean {
			if(!callWrapper(AIRSteam_IsCloudEnabledForApp)) return false;
			return readBoolResponse();
		}

		public function setCloudEnabledForApp(enabled:Boolean):Boolean {
			if(!callWrapper(AIRSteam_SetCloudEnabledForApp, [enabled])) return false;
			return readBoolResponse();
		}
	}
}

Fix typo

Fix typo