package com.kaltura.kdpfl
{
	import com.kaltura.kdpfl.controller.InitMacroCommand;
	import com.kaltura.kdpfl.controller.LayoutReadyCommand;
	import com.kaltura.kdpfl.controller.PlaybackCompleteCommand;
	import com.kaltura.kdpfl.controller.SequenceItemPlayEndCommand;
	import com.kaltura.kdpfl.controller.SequenceSkipNextCommand;
	import com.kaltura.kdpfl.controller.StartupCommand;
	import com.kaltura.kdpfl.controller.media.InitChangeMediaMacroCommand;
	import com.kaltura.kdpfl.controller.media.LiveStreamCommand;
	import com.kaltura.kdpfl.controller.media.MediaReadyCommand;
	import com.kaltura.kdpfl.events.DynamicEvent;
	import com.kaltura.kdpfl.model.ExternalInterfaceProxy;
	import com.kaltura.kdpfl.model.type.DebugLevel;
	import com.kaltura.kdpfl.model.type.NotificationType;
	import com.kaltura.kdpfl.view.controls.KTrace;
	import com.kaltura.kdpfl.view.media.KMediaPlayerMediator;
	import com.kaltura.puremvc.as3.core.KView;

	import flash.display.DisplayObject;

	import mx.utils.ObjectProxy;

	import org.osmf.media.MediaPlayerState;
	import org.puremvc.as3.interfaces.IFacade;
	import org.puremvc.as3.interfaces.IMediator;
	import org.puremvc.as3.interfaces.IProxy;
	import org.puremvc.as3.patterns.facade.Facade;

	public class ApplicationFacade extends Facade implements IFacade
	{
		/**
		 * The current version of the KDP.
		 */

		public var kdpVersion : String = "v3.8.1";

		/**
		 * save any mediator name that is registered to this array in order to delete at any time
		 * (the pure mvc don't support it as built-in function)
		 */
		private var _mediatorNameArray : Array = new Array();
		/**
		 * save any proxy name that is registered to this array in order to delete at any time
		 * (the pure mvc don't support it as built-in function)
		 */
		private var _proxyNameArray : Array = new Array();
		/**
		 * save any notification that create a command name that is registered to this array in order to delete at any time
		 * (the pure mvc don't support it as built-in function)
		 */
		private var _commandNameArray : Array = new Array();

		/**
		 * The bindObject create dynamicly all attributes that need to be binded on it
		 */
		public var bindObject:ObjectProxy = new ObjectProxy();
		/**
		 * a reference to KDP3 main application
		 */
		private var _app : DisplayObject;

		/**
		 * the url of the kdp
		 */
		public var appFolder : String;
		public var debugMode : Boolean = false;
		/**
		 *
		 * will affect the traces that will be sent. See DebugLevel enum
		 */
		public var debugLevel:int;

		private var externalInterface : ExternalInterfaceProxy;

		/**
		 * return the one and only instance of the ApplicationFacade,
		 * if not exist it will be created.
		 * @return
		 *
		 */
		public static function getInstance() : ApplicationFacade
		{
			if (instance == null) instance = new ApplicationFacade();
			return instance as ApplicationFacade;
		}

		/**
		 * All this simply does is fire a notification which is routed to
		 * "StartupCommand" via the "registerCommand" handlers
		 * @param app
		 *
		 */
		public function start(app:DisplayObject):void
		{
			CONFIG::isSDK46 {
				kdpVersion += ".sdk46";
			}

			_app = app;
			appFolder = app.root.loaderInfo.url;
			appFolder = appFolder.substr(0, appFolder.lastIndexOf('/') + 1);

			sendNotification(NotificationType.STARTUP, app);
			externalInterface = retrieveProxy(ExternalInterfaceProxy.NAME) as ExternalInterfaceProxy;
		}

		/**
		 * Created to trace all notifications for debug
		 * @param notificationName
		 * @param body
		 * @param type
		 *
		 */
		override public function sendNotification(notificationName:String, body:Object = null, type:String = null):void {
			if (debugMode) {
				var s:String;
				if ((notificationName == NotificationType.BYTES_DOWNLOADED_CHANGE && debugLevel == DebugLevel.HIGH) ||
					(notificationName == NotificationType.PLAYER_UPDATE_PLAYHEAD && (debugLevel == DebugLevel.HIGH || debugLevel == DebugLevel.MEDIUM)) ||
					(notificationName != NotificationType.PLAYER_UPDATE_PLAYHEAD && notificationName != NotificationType.BYTES_DOWNLOADED_CHANGE))
				 {
					if (notificationName == NotificationType.PLAYER_STATE_CHANGE)
						s = 'Sent ' + notificationName + ' ==> ' + body.toString();
					else {
						s = 'Sent ' + notificationName;
						if (body) {
							var found:Boolean = false;
							for (var o:* in body) {
								s += ", " + o + ":" + body[o];
								found = true;
							}
							if (!found) {
								s += ", " + body.toString();
							}
						}
					}
				}

				if (s && s != "null") {
					var curTime:Number = 0;
					var kmediaPlayerMediator:KMediaPlayerMediator = retrieveMediator(KMediaPlayerMediator.NAME) as KMediaPlayerMediator;
					if (kmediaPlayerMediator &&
						kmediaPlayerMediator.player &&
						kmediaPlayerMediator.player.state!=MediaPlayerState.LOADING &&
						kmediaPlayerMediator.player.state!=MediaPlayerState.UNINITIALIZED &&
						kmediaPlayerMediator.player.state!=MediaPlayerState.PLAYBACK_ERROR)
					{
						curTime = kmediaPlayerMediator.getCurrentTime();
					}
					var date:Date = new Date();

					KTrace.getInstance().log(date.toTimeString(), ":", s, ", playhead position:", curTime);
				}

			}

			super.sendNotification(notificationName, body, type);
			//For external Flash/Flex application application listening to the KDP events
			_app.dispatchEvent(new DynamicEvent(notificationName, body));

			//For external Javascript application listening to the KDP events
			if (externalInterface)
				externalInterface.notifyJs(notificationName, body);

		}

		/**
		 * controls the routing of notifications to our controllers,
		 * we all know them as commands
		 *
		 */
		override protected function initializeController():void
		{
			super.initializeController();
			registerCommand(NotificationType.STARTUP, StartupCommand);

			// we do both init start KDP life cycle, and start to load the entry simultaneously
			registerCommand(NotificationType.INITIATE_APP, InitMacroCommand);

			//There are several things that need to be done as soon as the layout of the kdp is ready.
			registerCommand(NotificationType.LAYOUT_READY, LayoutReadyCommand );
			//when one call change media we fire the load media command again
			registerCommand(NotificationType.CHANGE_MEDIA, InitChangeMediaMacroCommand);

			registerCommand (NotificationType.LIVE_ENTRY, LiveStreamCommand );

			registerCommand (NotificationType.MEDIA_LOADED, MediaReadyCommand );

			registerCommand (NotificationType.PLAYBACK_COMPLETE, PlaybackCompleteCommand);

			registerCommand(NotificationType.SEQUENCE_ITEM_PLAY_END, SequenceItemPlayEndCommand);

			registerCommand(NotificationType.SEQUENCE_SKIP_NEXT, SequenceSkipNextCommand);
		}

		override protected function initializeView():void
		{
			if ( view != null ) return;
			view = KView.getInstance();
		}

		override protected function initializeFacade():void
		{
			initializeView();
			initializeModel();
			initializeController();
		}

		/**
		 * Help to remove all commands, mediator, proxies from the facade
		 *
		 */
		public function dispose() : void
		{
			var i:int =0;

			for(i=0; i<_commandNameArray.length; i++)
				this.removeCommand( _commandNameArray[i] );

			for(i=0; i<_mediatorNameArray.length; i++)
				this.removeMediator( _mediatorNameArray[i] );

			for(i=0; i<_proxyNameArray.length; i++)
				this.removeProxy( _proxyNameArray[i] );

			_commandNameArray = new Array();
			_mediatorNameArray = new Array();
			_proxyNameArray = new Array();
		}

		/**
		 * after registartion add the notification name to a
		 * @param notificationName
		 * @param commandClassRef
		 *
		 */
		override public function registerCommand(notificationName:String, commandClassRef:Class):void
		{
			super.registerCommand(notificationName, commandClassRef);

			//save the notification name so we can delete it later
			_commandNameArray.push( notificationName );
		}

		override public function registerMediator(mediator:IMediator):void
		{
			super.registerMediator(mediator);

			//save the mediator name so we can delete it later
			_mediatorNameArray.push( mediator.getMediatorName() );
		}

		override public function registerProxy(proxy:IProxy):void
		{
			bindObject[proxy.getProxyName()] = proxy.getData();

			super.registerProxy(proxy);

			//save the proxy name so we can delete it later
			_proxyNameArray.push( proxy.getProxyName() );
		}

		/**
		 * add notification observer for a given mediator
		 * @param notification the notification to listen for
		 * @param notificationHandler handler to be called
		 * @param mediator
		 *
		 */
		public function addNotificationInterest(notification:String, notificationHandler:Function, mediator:IMediator):void {
			(view as KView).addNotificationInterest(notification, notificationHandler, mediator);
		}

		public function get app () : DisplayObject
		{
			return _app;
		}

		public function set app (disObj : DisplayObject) : void
		{
			_app = disObj;
		}

	}
}

package com.kaltura.kdpfl
{
	import com.kaltura.kdpfl.controller.InitMacroCommand;
	import com.kaltura.kdpfl.controller.LayoutReadyCommand;
	import com.kaltura.kdpfl.controller.PlaybackCompleteCommand;
	import com.kaltura.kdpfl.controller.SequenceItemPlayEndCommand;
	import com.kaltura.kdpfl.controller.SequenceSkipNextCommand;
	import com.kaltura.kdpfl.controller.StartupCommand;
	import com.kaltura.kdpfl.controller.media.InitChangeMediaMacroCommand;
	import com.kaltura.kdpfl.controller.media.LiveStreamCommand;
	import com.kaltura.kdpfl.controller.media.MediaReadyCommand;
	import com.kaltura.kdpfl.events.DynamicEvent;
	import com.kaltura.kdpfl.model.ExternalInterfaceProxy;
	import com.kaltura.kdpfl.model.type.DebugLevel;
	import com.kaltura.kdpfl.model.type.NotificationType;
	import com.kaltura.kdpfl.view.controls.KTrace;
	import com.kaltura.kdpfl.view.media.KMediaPlayerMediator;
	import com.kaltura.puremvc.as3.core.KView;

	import flash.display.DisplayObject;

	import mx.utils.ObjectProxy;

	import org.osmf.media.MediaPlayerState;
	import org.puremvc.as3.interfaces.IFacade;
	import org.puremvc.as3.interfaces.IMediator;
	import org.puremvc.as3.interfaces.IProxy;
	import org.puremvc.as3.patterns.facade.Facade;

	public class ApplicationFacade extends Facade implements IFacade
	{
		/**
		 * The current version of the KDP.
		 */

		public var kdpVersion : String = "v3.8.2";

		/**
		 * save any mediator name that is registered to this array in order to delete at any time
		 * (the pure mvc don't support it as built-in function)
		 */
		private var _mediatorNameArray : Array = new Array();
		/**
		 * save any proxy name that is registered to this array in order to delete at any time
		 * (the pure mvc don't support it as built-in function)
		 */
		private var _proxyNameArray : Array = new Array();
		/**
		 * save any notification that create a command name that is registered to this array in order to delete at any time
		 * (the pure mvc don't support it as built-in function)
		 */
		private var _commandNameArray : Array = new Array();

		/**
		 * The bindObject create dynamicly all attributes that need to be binded on it
		 */
		public var bindObject:ObjectProxy = new ObjectProxy();
		/**
		 * a reference to KDP3 main application
		 */
		private var _app : DisplayObject;

		/**
		 * the url of the kdp
		 */
		public var appFolder : String;
		public var debugMode : Boolean = false;
		/**
		 *
		 * will affect the traces that will be sent. See DebugLevel enum
		 */
		public var debugLevel:int;

		private var externalInterface : ExternalInterfaceProxy;

		/**
		 * return the one and only instance of the ApplicationFacade,
		 * if not exist it will be created.
		 * @return
		 *
		 */
		public static function getInstance() : ApplicationFacade
		{
			if (instance == null) instance = new ApplicationFacade();
			return instance as ApplicationFacade;
		}

		/**
		 * All this simply does is fire a notification which is routed to
		 * "StartupCommand" via the "registerCommand" handlers
		 * @param app
		 *
		 */
		public function start(app:DisplayObject):void
		{
			CONFIG::isSDK46 {
				kdpVersion += ".sdk46";
			}

			_app = app;
			appFolder = app.root.loaderInfo.url;
			appFolder = appFolder.substr(0, appFolder.lastIndexOf('/') + 1);

			sendNotification(NotificationType.STARTUP, app);
			externalInterface = retrieveProxy(ExternalInterfaceProxy.NAME) as ExternalInterfaceProxy;
		}

		/**
		 * Created to trace all notifications for debug
		 * @param notificationName
		 * @param body
		 * @param type
		 *
		 */
		override public function sendNotification(notificationName:String, body:Object = null, type:String = null):void {
			if (debugMode) {
				var s:String;
				if ((notificationName == NotificationType.BYTES_DOWNLOADED_CHANGE && debugLevel == DebugLevel.HIGH) ||
					(notificationName == NotificationType.PLAYER_UPDATE_PLAYHEAD && (debugLevel == DebugLevel.HIGH || debugLevel == DebugLevel.MEDIUM)) ||
					(notificationName != NotificationType.PLAYER_UPDATE_PLAYHEAD && notificationName != NotificationType.BYTES_DOWNLOADED_CHANGE))
				 {
					if (notificationName == NotificationType.PLAYER_STATE_CHANGE)
						s = 'Sent ' + notificationName + ' ==> ' + body.toString();
					else {
						s = 'Sent ' + notificationName;
						if (body) {
							var found:Boolean = false;
							for (var o:* in body) {
								s += ", " + o + ":" + body[o];
								found = true;
							}
							if (!found) {
								s += ", " + body.toString();
							}
						}
					}
				}

				if (s && s != "null") {
					var curTime:Number = 0;
					var kmediaPlayerMediator:KMediaPlayerMediator = retrieveMediator(KMediaPlayerMediator.NAME) as KMediaPlayerMediator;
					if (kmediaPlayerMediator &&
						kmediaPlayerMediator.player &&
						kmediaPlayerMediator.player.state!=MediaPlayerState.LOADING &&
						kmediaPlayerMediator.player.state!=MediaPlayerState.UNINITIALIZED &&
						kmediaPlayerMediator.player.state!=MediaPlayerState.PLAYBACK_ERROR)
					{
						curTime = kmediaPlayerMediator.getCurrentTime();
					}
					var date:Date = new Date();

					KTrace.getInstance().log(date.toTimeString(), ":", s, ", playhead position:", curTime);
				}

			}

			super.sendNotification(notificationName, body, type);
			//For external Flash/Flex application application listening to the KDP events
			_app.dispatchEvent(new DynamicEvent(notificationName, body));

			//For external Javascript application listening to the KDP events
			if (externalInterface)
				externalInterface.notifyJs(notificationName, body);

		}

		/**
		 * controls the routing of notifications to our controllers,
		 * we all know them as commands
		 *
		 */
		override protected function initializeController():void
		{
			super.initializeController();
			registerCommand(NotificationType.STARTUP, StartupCommand);

			// we do both init start KDP life cycle, and start to load the entry simultaneously
			registerCommand(NotificationType.INITIATE_APP, InitMacroCommand);

			//There are several things that need to be done as soon as the layout of the kdp is ready.
			registerCommand(NotificationType.LAYOUT_READY, LayoutReadyCommand );
			//when one call change media we fire the load media command again
			registerCommand(NotificationType.CHANGE_MEDIA, InitChangeMediaMacroCommand);

			registerCommand (NotificationType.LIVE_ENTRY, LiveStreamCommand );

			registerCommand (NotificationType.MEDIA_LOADED, MediaReadyCommand );

			registerCommand (NotificationType.PLAYBACK_COMPLETE, PlaybackCompleteCommand);

			registerCommand(NotificationType.SEQUENCE_ITEM_PLAY_END, SequenceItemPlayEndCommand);

			registerCommand(NotificationType.SEQUENCE_SKIP_NEXT, SequenceSkipNextCommand);
		}

		override protected function initializeView():void
		{
			if ( view != null ) return;
			view = KView.getInstance();
		}

		override protected function initializeFacade():void
		{
			initializeView();
			initializeModel();
			initializeController();
		}

		/**
		 * Help to remove all commands, mediator, proxies from the facade
		 *
		 */
		public function dispose() : void
		{
			var i:int =0;

			for(i=0; i<_commandNameArray.length; i++)
				this.removeCommand( _commandNameArray[i] );

			for(i=0; i<_mediatorNameArray.length; i++)
				this.removeMediator( _mediatorNameArray[i] );

			for(i=0; i<_proxyNameArray.length; i++)
				this.removeProxy( _proxyNameArray[i] );

			_commandNameArray = new Array();
			_mediatorNameArray = new Array();
			_proxyNameArray = new Array();
		}

		/**
		 * after registartion add the notification name to a
		 * @param notificationName
		 * @param commandClassRef
		 *
		 */
		override public function registerCommand(notificationName:String, commandClassRef:Class):void
		{
			super.registerCommand(notificationName, commandClassRef);

			//save the notification name so we can delete it later
			_commandNameArray.push( notificationName );
		}

		override public function registerMediator(mediator:IMediator):void
		{
			super.registerMediator(mediator);

			//save the mediator name so we can delete it later
			_mediatorNameArray.push( mediator.getMediatorName() );
		}

		override public function registerProxy(proxy:IProxy):void
		{
			bindObject[proxy.getProxyName()] = proxy.getData();

			super.registerProxy(proxy);

			//save the proxy name so we can delete it later
			_proxyNameArray.push( proxy.getProxyName() );
		}

		/**
		 * add notification observer for a given mediator
		 * @param notification the notification to listen for
		 * @param notificationHandler handler to be called
		 * @param mediator
		 *
		 */
		public function addNotificationInterest(notification:String, notificationHandler:Function, mediator:IMediator):void {
			(view as KView).addNotificationInterest(notification, notificationHandler, mediator);
		}

		public function get app () : DisplayObject
		{
			return _app;
		}

		public function set app (disObj : DisplayObject) : void
		{
			_app = disObj;
		}

	}
}

bump v3.8.2

bump v3.8.2


package asunit.core {

	import asunit.printers.TextPrinter;

	import flash.display.DisplayObjectContainer;

    /**
     * TextCore is just a simple helper class that
     * configures the base class AsUnitCore to use the
     * standard TextPrinter.
     *
     * The main idea is that you may want a completely
     * different text output without the default TextPrinter,
     * and if that's the case, you can go ahead and
     * instantiate AsUnitCore and configure it however you
     * wish.
     */
    public class TextCore extends AsUnitCore {

        public var textPrinter:TextPrinter;

        override protected function initializeObservers():void {
            super.initializeObservers();

            textPrinter = new TextPrinter();
            addListener(textPrinter);
        }

        override public function set visualContext(context:DisplayObjectContainer):void {
            super.visualContext = context;
            // Add the TextPrinter to the Display List:
            visualContext.addChild(textPrinter);
        }
    }
}

package asunit.core {

	import asunit.printers.ColorTracePrinter;
	import asunit.printers.TextPrinter;

	import flash.display.DisplayObjectContainer;

    /**
     * TextCore is just a simple helper class that
     * configures the base class AsUnitCore to use the
     * standard TextPrinter.
     *
     * The main idea is that you may want a completely
     * different text output without the default TextPrinter,
     * and if that's the case, you can go ahead and
     * instantiate AsUnitCore and configure it however you
     * wish.
     */
    public class TextCore extends AsUnitCore {

        public var textPrinter:TextPrinter;

        override protected function initializeObservers():void {
            super.initializeObservers();

            textPrinter = new TextPrinter();
			textPrinter.traceOnComplete = false;
            addListener(textPrinter);

			addListener(new ColorTracePrinter());
        }

        override public function set visualContext(context:DisplayObjectContainer):void {
            super.visualContext = context;
            // Add the TextPrinter to the Display List:
            visualContext.addChild(textPrinter);
        }
    }
}

modify TextCore to use ColorTracePrinter


package battlecode.client.viewer {
    import battlecode.client.viewer.render.DrawDominationBar;
    import battlecode.client.viewer.render.DrawHUD;
    import battlecode.client.viewer.render.DrawMap;
    import battlecode.client.viewer.render.RenderConfiguration;
    import battlecode.common.Team;
    import battlecode.events.MatchEvent;

    import flash.display.InteractiveObject;
    import flash.events.Event;
    import flash.events.KeyboardEvent;

    import mx.binding.utils.ChangeWatcher;
    import mx.containers.HBox;
    import mx.containers.VBox;
    import mx.events.FlexEvent;

    /*
     * ----------------------
     * |       Dom Bar      |
     * |--------------------|
     * |                    |
     * |       DrawMap      |
     * |                    |
     * |                    |
     * ----------------------
     */
    public class GameCanvas extends HBox {
        private var controller:MatchController;
        private var watchers:Vector.<ChangeWatcher>;

        private var vbox:VBox; // container for map
        private var drawDominationBar:DrawDominationBar;
        private var sideBoxA:VBox;
        private var sideBoxB:VBox;
        private var drawMap:DrawMap;

        public function GameCanvas(controller:MatchController) {
            super();

            this.percentWidth = 100;
            this.percentHeight = 100;

            this.vbox = new VBox();
            this.drawDominationBar = new DrawDominationBar(controller);
            this.drawMap = new DrawMap(controller);
            this.sideBoxA = new DrawHUD(controller, Team.A);
            this.sideBoxB = new DrawHUD(controller, Team.B);

            this.controller = controller;
            this.controller.addEventListener(MatchEvent.ROUND_CHANGE, onRoundChange);
            this.controller.addEventListener(MatchEvent.MATCH_CHANGE, onMatchChange);

            this.setStyle("paddingLeft", 0);
            this.setStyle("paddingTop", 0);
            this.setStyle("paddingBottom", 0);
            this.setStyle("paddingRight", 0);
            this.setStyle("horizontalGap", 0);
            this.setStyle("verticalGap", 0);

            vbox.percentWidth = 100;
            vbox.percentHeight = 100;
            vbox.autoLayout = false;
            vbox.setStyle("paddingLeft", 0);
            vbox.setStyle("paddingTop", 0);
            vbox.setStyle("paddingBottom", 0);
            vbox.setStyle("paddingRight", 0);

            this.addChild(sideBoxA);
            this.addChild(vbox);
            this.addChild(sideBoxB);
            vbox.addChild(drawDominationBar);
            vbox.addChild(drawMap);

            this.addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
        }

        private function centerMap():void {
            if (width == 0 || height == 0) return;

            var containerWidth:Number = vbox.width;
            var containerHeight:Number = vbox.height - drawDominationBar.height;

            var mapWidth:uint = drawMap.getMapWidth();
            var mapHeight:uint = drawMap.getMapHeight();
            var scalingFactor:Number = Math.min(containerWidth / mapWidth, containerHeight / mapHeight);

            RenderConfiguration.setScalingFactor(scalingFactor);
            drawMap.redrawAll();
            drawMap.x = (containerWidth - (mapWidth * scalingFactor)) / 2;
            drawMap.y = (containerHeight - (mapHeight * scalingFactor)) / 2 + drawDominationBar.height;

            drawDominationBar.x = 0;
            drawDominationBar.y = 0;
            drawDominationBar.width = vbox.width;
            drawDominationBar.redrawAll();
        }

        private function onCreationComplete(e:Event):void {
            this.watchers = new Vector.<ChangeWatcher>();
            this.watchers.push(ChangeWatcher.watch(this, "width", onSizeChange));
            this.watchers.push(ChangeWatcher.watch(this, "height", onSizeChange));
            this.watchers.push(ChangeWatcher.watch(vbox, "width", onSizeChange));
            this.watchers.push(ChangeWatcher.watch(vbox, "height", onSizeChange));
            this.watchers.push(ChangeWatcher.watch(drawDominationBar, "width", onSizeChange));
            this.watchers.push(ChangeWatcher.watch(drawDominationBar, "height", onSizeChange));

            centerMap();

            // can't be added until stage object is avail on creation complete
            this.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
        }

        private function onRoundChange(e:MatchEvent):void {

        }

        private function onMatchChange(e:MatchEvent):void {
            centerMap();
            controller.currentRound += 1;
        }

        // listens for width/height changes to recenter map
        private function onSizeChange(e:Event):void {
            centerMap();
        }

        // listens for key presses to update the render configuration
        private function onKeyDown(e:KeyboardEvent):void {
            if (e.ctrlKey || e.altKey) return;

            switch (String.fromCharCode(e.charCode)) {
                case "B":
                case "b":
                    RenderConfiguration.toggleBroadcast();
                    break;
                case "D":
                case "d":
                    RenderConfiguration.toggleDiscrete();
                    break;
                case "E":
                case "e":
                    RenderConfiguration.toggleEnergon();
                    break;
                case "F":
                case "f":
                    controller.fastForwarding = !controller.fastForwarding;
                    break;
                case "G":
                case "g":
                    RenderConfiguration.toggleGridlines();
                    break;
                case "H":
                case "h":
                    RenderConfiguration.toggleDrawHeight();
                    break;
                case "K":
                case "k":
                    controller.keyframeRate = (controller.keyframeRate) ? 0 : 50; // toggle keyframing
                    break;
                case "M":
                case "m":
                    RenderConfiguration.toggleOre();
                    break;
                case "O":
                case "o":
                    RenderConfiguration.toggleHats();
                    break;
                case "S":
                case "s":
                    if (!trySkip(200)) if (!trySkip(100)) trySkip(50); // skip ahead
                    break;
                case "X":
                case "x":
                    RenderConfiguration.toggleExplosions();
                    break;
                case " ":
                    var focusObj:InteractiveObject = this.stage.focus;
                    this.stage.focus = null; // hack to prevent space bar from activating other buttons
                    this.stage.focus = focusObj;
                    if (controller.currentRound == controller.match.getRounds() && controller.currentMatch < controller.totalMatches) {
                        controller.currentMatch++;
                    }
                    controller.playing = !controller.playing; // toggle play/pause
                    break;
            }
        }

        private function trySkip(rounds:uint):Boolean {
            if (controller.currentRound + rounds < controller.match.getRounds()) {
                controller.currentRound += rounds;
                return true;
            }
            return false;
        }
    }

}

package battlecode.client.viewer {
    import battlecode.client.viewer.render.DrawDominationBar;
    import battlecode.client.viewer.render.DrawHUD;
    import battlecode.client.viewer.render.DrawMap;
    import battlecode.client.viewer.render.RenderConfiguration;
    import battlecode.common.Team;
    import battlecode.events.MatchEvent;

    import flash.display.InteractiveObject;
    import flash.events.Event;
    import flash.events.KeyboardEvent;

    import mx.binding.utils.ChangeWatcher;
    import mx.containers.HBox;
    import mx.containers.VBox;
    import mx.events.FlexEvent;

    /*
     * ----------------------
     * |       Dom Bar      |
     * |--------------------|
     * |                    |
     * |       DrawMap      |
     * |                    |
     * |                    |
     * ----------------------
     */
    public class GameCanvas extends HBox {
        private var controller:MatchController;
        private var watchers:Vector.<ChangeWatcher>;

        private var vbox:VBox; // container for map
        private var sideBoxA:VBox;
        private var sideBoxB:VBox;
        private var drawMap:DrawMap;

        public function GameCanvas(controller:MatchController) {
            super();

            this.percentWidth = 100;
            this.percentHeight = 100;

            this.vbox = new VBox();
            this.drawMap = new DrawMap(controller);
            this.sideBoxA = new DrawHUD(controller, Team.A);
            this.sideBoxB = new DrawHUD(controller, Team.B);

            this.controller = controller;
            this.controller.addEventListener(MatchEvent.ROUND_CHANGE, onRoundChange);
            this.controller.addEventListener(MatchEvent.MATCH_CHANGE, onMatchChange);

            this.setStyle("paddingLeft", 0);
            this.setStyle("paddingTop", 0);
            this.setStyle("paddingBottom", 0);
            this.setStyle("paddingRight", 0);
            this.setStyle("horizontalGap", 0);
            this.setStyle("verticalGap", 0);

            vbox.percentWidth = 100;
            vbox.percentHeight = 100;
            vbox.autoLayout = false;
            vbox.setStyle("paddingLeft", 0);
            vbox.setStyle("paddingTop", 0);
            vbox.setStyle("paddingBottom", 0);
            vbox.setStyle("paddingRight", 0);

            this.addChild(sideBoxA);
            this.addChild(vbox);
            this.addChild(sideBoxB);
            vbox.addChild(drawMap);

            this.addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
        }

        private function centerMap():void {
            if (width == 0 || height == 0) return;

            var containerWidth:Number = vbox.width;
            var containerHeight:Number = vbox.height;

            var mapWidth:uint = drawMap.getMapWidth();
            var mapHeight:uint = drawMap.getMapHeight();
            var scalingFactor:Number = Math.min(containerWidth / mapWidth, containerHeight / mapHeight);

            RenderConfiguration.setScalingFactor(scalingFactor);
            drawMap.redrawAll();
            drawMap.x = (containerWidth - (mapWidth * scalingFactor)) / 2;
            drawMap.y = 0;
        }

        private function onCreationComplete(e:Event):void {
            this.watchers = new Vector.<ChangeWatcher>();
            this.watchers.push(ChangeWatcher.watch(this, "width", onSizeChange));
            this.watchers.push(ChangeWatcher.watch(this, "height", onSizeChange));
            this.watchers.push(ChangeWatcher.watch(vbox, "width", onSizeChange));
            this.watchers.push(ChangeWatcher.watch(vbox, "height", onSizeChange));

            centerMap();

            // can't be added until stage object is avail on creation complete
            this.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
        }

        private function onRoundChange(e:MatchEvent):void {

        }

        private function onMatchChange(e:MatchEvent):void {
            centerMap();
            controller.currentRound += 1;
        }

        // listens for width/height changes to recenter map
        private function onSizeChange(e:Event):void {
            centerMap();
        }

        // listens for key presses to update the render configuration
        private function onKeyDown(e:KeyboardEvent):void {
            if (e.ctrlKey || e.altKey) return;

            switch (String.fromCharCode(e.charCode)) {
                case "B":
                case "b":
                    RenderConfiguration.toggleBroadcast();
                    break;
                case "D":
                case "d":
                    RenderConfiguration.toggleDiscrete();
                    break;
                case "E":
                case "e":
                    RenderConfiguration.toggleEnergon();
                    break;
                case "F":
                case "f":
                    controller.fastForwarding = !controller.fastForwarding;
                    break;
                case "G":
                case "g":
                    RenderConfiguration.toggleGridlines();
                    break;
                case "H":
                case "h":
                    RenderConfiguration.toggleDrawHeight();
                    break;
                case "K":
                case "k":
                    controller.keyframeRate = (controller.keyframeRate) ? 0 : 50; // toggle keyframing
                    break;
                case "M":
                case "m":
                    RenderConfiguration.toggleOre();
                    break;
                case "O":
                case "o":
                    RenderConfiguration.toggleHats();
                    break;
                case "S":
                case "s":
                    if (!trySkip(200)) if (!trySkip(100)) trySkip(50); // skip ahead
                    break;
                case "X":
                case "x":
                    RenderConfiguration.toggleExplosions();
                    break;
                case " ":
                    var focusObj:InteractiveObject = this.stage.focus;
                    this.stage.focus = null; // hack to prevent space bar from activating other buttons
                    this.stage.focus = focusObj;
                    if (controller.currentRound == controller.match.getRounds() && controller.currentMatch < controller.totalMatches) {
                        controller.currentMatch++;
                    }
                    controller.playing = !controller.playing; // toggle play/pause
                    break;
            }
        }

        private function trySkip(rounds:uint):Boolean {
            if (controller.currentRound + rounds < controller.match.getRounds()) {
                controller.currentRound += rounds;
                return true;
            }
            return false;
        }
    }

}

remove domination bar from layout

remove domination bar from layout


package com.kaltura.hls.m2ts
{
    import flash.utils.ByteArray;
    import flash.net.ObjectEncoding;
    import flash.utils.ByteArray;
    import flash.utils.Endian;
    import flash.utils.IDataInput;
    import flash.utils.IDataOutput;

    /**
     * Responsible for emitting FLV data. Also handles AAC conversion
     * config and buffering.
     */
    public class FLVTranscoder
    {
        public const MIN_FILE_HEADER_BYTE_COUNT:int = 9;

        public var callback:Function;

        private var lastTagSize:uint = 0;

        private var _aacConfig:ByteArray;
        private var _aacRemainder:ByteArray;
        private var _aacTimestamp:Number = 0;

        public function clear(clearAACConfig:Boolean = false):void
        {
            if(clearAACConfig)
                _aacConfig = null;
            _aacRemainder = new ByteArray();
            _aacTimestamp = 0;
        }

        private static var tag:ByteArray = new ByteArray();

        private function sendFLVTag(flvts:uint, type:uint, codec:int, mode:int, bytes:ByteArray, offset:uint, length:uint):void
        {
            tag.position = 0;
            var msgLength:uint = length + ((codec >= 0) ? 1 : 0) + ((mode >= 0) ? 1 : 0);
            var cursor:uint = 0;

            if(msgLength > 0xffffff)
                return; // too big for the length field

            tag.length = FLVTags.HEADER_LENGTH + msgLength;
            tag[cursor++] = type;
            tag[cursor++] = (msgLength >> 16) & 0xff;
            tag[cursor++] = (msgLength >>  8) & 0xff;
            tag[cursor++] = (msgLength      ) & 0xff;
            tag[cursor++] = (flvts >> 16) & 0xff;
            tag[cursor++] = (flvts >>  8) & 0xff;
            tag[cursor++] = (flvts      ) & 0xff;
            tag[cursor++] = (flvts >> 24) & 0xff;
            tag[cursor++] = 0x00; // stream ID
            tag[cursor++] = 0x00;
            tag[cursor++] = 0x00;

            if(codec >= 0)
                tag[cursor++] = codec;
            if(mode >= 0)
                tag[cursor++] = mode;

            tag.position = cursor;
            tag.writeBytes(bytes, offset, length);

            cursor += length;
            msgLength += 11; // account for message header in back pointer

            tag.writeUnsignedInt(lastTagSize);

            // Dispatch tag.
            if(callback != null)
                callback(flvts, tag);

            lastTagSize = tag.length;
        }

        public function convertFLVTimestamp(pts:Number):Number
        {
            return pts / 90.0;
        }

        private static var flvGenerationBuffer:ByteArray = new ByteArray();

        /**
         * Convert and amit AVC NALU data.
         */
        public function convert(unit:NALU):void
        {
            // Emit an AVCC.
            var avcc:ByteArray = NALUProcessor.extractAVCC(unit);
            if(avcc)
                sendFLVTag(convertFLVTimestamp(unit.pts), FLVTags.TYPE_VIDEO, FLVTags.VIDEO_CODEC_AVC_KEYFRAME, FLVTags.AVC_MODE_AVCC, avcc, 0, avcc.length);

            // Accumulate NALUs into buffer.
            flvGenerationBuffer.length = 3;
            flvGenerationBuffer[0] = (tsu >> 16) & 0xff;
            flvGenerationBuffer[1] = (tsu >>  8) & 0xff;
            flvGenerationBuffer[2] = (tsu      ) & 0xff;
            flvGenerationBuffer.position = 3;

            // Check keyframe status.
            var keyFrame:Boolean = false;
            var totalAppended:int = 0;
            NALUProcessor.walkNALUs(unit.buffer, 0, function(bytes:ByteArray, cursor:uint, length:uint):void
            {
                // Check for a NALU that is keyframe type.
                var naluType:uint = bytes[cursor] & 0x1f;
                //trace(naluType + " length=" + length);
                switch(naluType)
                {
                    case 0x09: // "access unit delimiter"
                        switch((bytes[cursor + 1] >> 5) & 0x07) // access unit type
                        {
                            case 0:
                            case 3:
                            case 5:
                                keyFrame = true;
                                break;
                            default:
                                keyFrame = false;
                                break;
                        }
                        break;

                    default:
                        // Infer keyframe state.
                        if(naluType == 5)
                            keyFrame = true;
                        else if(naluType == 1)
                            keyFrame = false;
                }

                // Append.
                flvGenerationBuffer.writeUnsignedInt(length);
                flvGenerationBuffer.writeBytes(bytes, cursor, length);
                totalAppended += length;
            }, true );

            var flvts:uint = convertFLVTimestamp(unit.pts);
            var tsu:uint = convertFLVTimestamp(unit.pts - unit.dts);

            var codec:uint;
            if(keyFrame)
                codec = FLVTags.VIDEO_CODEC_AVC_KEYFRAME;
            else
                codec = FLVTags.VIDEO_CODEC_AVC_PREDICTIVEFRAME;

            //trace("ts=" + flvts + " tsu=" + tsu + " keyframe = " + keyFrame);

            sendFLVTag(flvts, FLVTags.TYPE_VIDEO, codec, FLVTags.AVC_MODE_PICTURE, flvGenerationBuffer, 0, flvGenerationBuffer.length);
        }

        private function compareBytesHelper(b1:ByteArray, b2:ByteArray):Boolean
        {
            var curPos:uint;

            if(b1.length != b2.length)
                return false;

            for(curPos = 0; curPos < b1.length; curPos++)
            {
                if(b1[curPos] != b2[curPos])
                    return false;
            }

            return true;
        }

        private function sendAACConfigFLVTag(flvts:uint, profile:uint, sampleRateIndex:uint, channelConfig:uint):void
        {
            var isNewConfig:Boolean = true;
            var audioSpecificConfig:ByteArray = new ByteArray();
            var audioObjectType:uint;

            audioSpecificConfig.length = 2;

            switch(profile)
            {
                case 0x00:
                    audioObjectType = 0x01;
                    break;
                case 0x01:
                    audioObjectType = 0x02;
                    break;
                case 0x02:
                    audioObjectType = 0x03;
                    break;
                default:
                    return;
            }

            audioSpecificConfig[0] = ((audioObjectType << 3) & 0xf8) + ((sampleRateIndex >> 1) & 0x07);
            audioSpecificConfig[1] = ((sampleRateIndex << 7) & 0x80) + ((channelConfig << 3) & 0x78);

            if(_aacConfig && compareBytesHelper(_aacConfig, audioSpecificConfig))
                isNewConfig = false;

            if(!isNewConfig)
                return;

            _aacConfig = audioSpecificConfig;
            sendFLVTag(flvts, FLVTags.TYPE_AUDIO, FLVTags.AUDIO_CODEC_AAC, FLVTags.AAC_MODE_CONFIG, _aacConfig, 0, _aacConfig.length);
        }

        /**
         * Convert and amit AAC data.
         */
        public function convertAAC(pes:PESPacket):void
        {
            var timeAccumulation:Number = 0.0;
            var limit:uint;
            var stream:ByteArray;
            var hadRemainder:Boolean = false;
            var cursor:int = 0;
            var length:int = pes.buffer.length;
            var bytes:ByteArray = pes.buffer;
            var timestamp:Number = pes.pts;

            if(_aacRemainder)
            {
                stream = _aacRemainder;
                stream.writeBytes(bytes, cursor, length);
                cursor = 0;
                length = stream.length;
                _aacRemainder = null;
                hadRemainder = true;
                timeAccumulation = _aacTimestamp - timestamp;
            }
            else
                stream = bytes;

            limit = cursor + length;

            // an AAC PES packet can contain multiple ADTS frames
            while(cursor < limit)
            {
                var remaining:uint = limit - cursor;
                var sampleRateIndex:uint;
                var sampleRate:Number = undefined;
                var profile:uint;
                var channelConfig:uint;
                var frameLength:uint;

                if(remaining < FLVTags.ADTS_FRAME_HEADER_LENGTH)
                    break;

                // search for syncword
                if(stream[cursor] != 0xff || (stream[cursor + 1] & 0xf0) != 0xf0)
                {
                    cursor++;
                    continue;
                }

                frameLength  = (stream[cursor + 3] & 0x03) << 11;
                frameLength += (stream[cursor + 4]) << 3;
                frameLength += (stream[cursor + 5] >> 5) & 0x07;

                // Check for an invalid ADTS header; if so look for next syncword.
                if(frameLength < FLVTags.ADTS_FRAME_HEADER_LENGTH)
                {
                    cursor++;
                    continue;
                }

                // Skip it till next PES packet.
                if(frameLength > remaining)
                    break;

                profile = (stream[cursor + 2] >> 6) & 0x03;

                sampleRateIndex = (stream[cursor + 2] >> 2) & 0x0f;
                switch(sampleRateIndex)
                {
                    case 0x00:
                        sampleRate = 96000.0;
                        break;
                    case 0x01:
                        sampleRate = 88200.0;
                        break;
                    case 0x02:
                        sampleRate = 64000.0;
                        break;
                    case 0x03:
                        sampleRate = 48000.0;
                        break;
                    case 0x04:
                        sampleRate = 44100.0;
                        break;
                    case 0x05:
                        sampleRate = 32000.0;
                        break;
                    case 0x06:
                        sampleRate = 24000.0;
                        break;
                    case 0x07:
                        sampleRate = 22050.0;
                        break;
                    case 0x08:
                        sampleRate = 16000.0;
                        break;
                    case 0x09:
                        sampleRate = 12000.0;
                        break;
                    case 0x0a:
                        sampleRate = 11025.0;
                        break;
                    case 0x0b:
                        sampleRate = 8000.0;
                        break;
                    case 0x0c:
                        sampleRate = 7350.0;
                        break;
                }

                channelConfig = ((stream[cursor + 2] & 0x01) << 2) + ((stream[cursor + 3] >> 6) & 0x03);

                if(sampleRate)
                {
                    var flvts:uint = convertFLVTimestamp(timestamp + timeAccumulation);

                    sendAACConfigFLVTag(flvts, profile, sampleRateIndex, channelConfig);
                    //trace("Sending AAC");
                    sendFLVTag(flvts, FLVTags.TYPE_AUDIO, FLVTags.AUDIO_CODEC_AAC, FLVTags.AAC_MODE_FRAME, stream, cursor + FLVTags.ADTS_FRAME_HEADER_LENGTH, frameLength - FLVTags.ADTS_FRAME_HEADER_LENGTH);

                    timeAccumulation += (1024.0 / sampleRate) * 90000.0; // account for the duration of this frame

                    if(hadRemainder)
                    {
                        timeAccumulation = 0.0;
                        hadRemainder = false;
                    }
                }

                cursor += frameLength;
            }

            if(cursor < limit)
            {
                //trace("AAC timestamp was " + _aacTimestamp);
                _aacRemainder = new ByteArray();
                _aacRemainder.writeBytes(stream, cursor, limit - cursor);
                _aacTimestamp = timestamp + timeAccumulation;
                //trace("AAC timestamp now " + _aacTimestamp);
            }
        }

        /**
         * Convert and amit MP3 data.
         */
        public function convertMP3(pes:PESPacket):void
        {
            sendFLVTag(convertFLVTimestamp(pes.pts), FLVTags.TYPE_AUDIO, FLVTags.AUDIO_CODEC_MP3, -1, pes.buffer, 0, pes.buffer.length);
        }

        private function generateScriptData(values:Array):ByteArray
        {
            var bytes:ByteArray = new ByteArray();
            bytes.objectEncoding = ObjectEncoding.AMF0;

            for each (var object:Object in values)
                bytes.writeObject(object);

            return bytes;
        }

        private function sendScriptDataFLVTag(flvts:uint, values:Array):void
        {
            var bytes:ByteArray = generateScriptData(values);
            sendFLVTag(flvts, FLVTags.TYPE_SCRIPTDATA, -1, -1, bytes, 0, bytes.length);
        }

        /**
         * Fire off a subtitle caption.
         */
        public function createAndSendCaptionMessage( timeStamp:Number, captionBuffer:String, lang:String="", textid:Number=99):void
        {
            var captionObject:Array = ["onCaptionInfo", { type:"WebVTT", data:captionBuffer }];
            //sendScriptDataFLVTag( timeStamp * 1000, captionObject);

            // We need to strip the timestamp off of the text data
            captionBuffer = captionBuffer.slice(captionBuffer.indexOf('\n') + 1);

            var subtitleObject:Array = ["onTextData", { text:captionBuffer, language:lang, trackid:textid }];
            sendScriptDataFLVTag( timeStamp * 1000, subtitleObject);
        }

    }
}

package com.kaltura.hls.m2ts
{
    import flash.utils.ByteArray;
    import flash.net.ObjectEncoding;
    import flash.utils.ByteArray;
    import flash.utils.Endian;
    import flash.utils.IDataInput;
    import flash.utils.IDataOutput;

    /**
     * Responsible for emitting FLV data. Also handles AAC conversion
     * config and buffering.
     */
    public class FLVTranscoder
    {
        public const MIN_FILE_HEADER_BYTE_COUNT:int = 9;

        public var callback:Function;

        private var lastTagSize:uint = 0;

        private var _aacConfig:ByteArray;
        private var _aacRemainder:ByteArray;
        private var _aacTimestamp:Number = 0;

        public function clear(clearAACConfig:Boolean = false):void
        {
            if(clearAACConfig)
                _aacConfig = null;
            _aacRemainder = null;
            _aacTimestamp = 0;
        }

        private static var tag:ByteArray = new ByteArray();

        private function sendFLVTag(flvts:uint, type:uint, codec:int, mode:int, bytes:ByteArray, offset:uint, length:uint):void
        {
            tag.position = 0;
            var msgLength:uint = length + ((codec >= 0) ? 1 : 0) + ((mode >= 0) ? 1 : 0);
            var cursor:uint = 0;

            if(msgLength > 0xffffff)
                return; // too big for the length field

            tag.length = FLVTags.HEADER_LENGTH + msgLength;
            tag[cursor++] = type;
            tag[cursor++] = (msgLength >> 16) & 0xff;
            tag[cursor++] = (msgLength >>  8) & 0xff;
            tag[cursor++] = (msgLength      ) & 0xff;
            tag[cursor++] = (flvts >> 16) & 0xff;
            tag[cursor++] = (flvts >>  8) & 0xff;
            tag[cursor++] = (flvts      ) & 0xff;
            tag[cursor++] = (flvts >> 24) & 0xff;
            tag[cursor++] = 0x00; // stream ID
            tag[cursor++] = 0x00;
            tag[cursor++] = 0x00;

            if(codec >= 0)
                tag[cursor++] = codec;
            if(mode >= 0)
                tag[cursor++] = mode;

            tag.position = cursor;
            tag.writeBytes(bytes, offset, length);

            cursor += length;
            msgLength += 11; // account for message header in back pointer

            tag.writeUnsignedInt(lastTagSize);

            // Dispatch tag.
            if(callback != null)
                callback(flvts, tag);

            lastTagSize = tag.length;
        }

        public function convertFLVTimestamp(pts:Number):Number
        {
            return pts / 90.0;
        }

        private static var flvGenerationBuffer:ByteArray = new ByteArray();

        /**
         * Convert and amit AVC NALU data.
         */
        public function convert(unit:NALU):void
        {
            // Emit an AVCC.
            var avcc:ByteArray = NALUProcessor.extractAVCC(unit);
            if(avcc)
                sendFLVTag(convertFLVTimestamp(unit.pts), FLVTags.TYPE_VIDEO, FLVTags.VIDEO_CODEC_AVC_KEYFRAME, FLVTags.AVC_MODE_AVCC, avcc, 0, avcc.length);

            // Accumulate NALUs into buffer.
            flvGenerationBuffer.length = 3;
            flvGenerationBuffer[0] = (tsu >> 16) & 0xff;
            flvGenerationBuffer[1] = (tsu >>  8) & 0xff;
            flvGenerationBuffer[2] = (tsu      ) & 0xff;
            flvGenerationBuffer.position = 3;

            // Check keyframe status.
            var keyFrame:Boolean = false;
            var totalAppended:int = 0;
            NALUProcessor.walkNALUs(unit.buffer, 0, function(bytes:ByteArray, cursor:uint, length:uint):void
            {
                // Check for a NALU that is keyframe type.
                var naluType:uint = bytes[cursor] & 0x1f;
                //trace(naluType + " length=" + length);
                switch(naluType)
                {
                    case 0x09: // "access unit delimiter"
                        switch((bytes[cursor + 1] >> 5) & 0x07) // access unit type
                        {
                            case 0:
                            case 3:
                            case 5:
                                keyFrame = true;
                                break;
                            default:
                                keyFrame = false;
                                break;
                        }
                        break;

                    default:
                        // Infer keyframe state.
                        if(naluType == 5)
                            keyFrame = true;
                        else if(naluType == 1)
                            keyFrame = false;
                }

                // Append.
                flvGenerationBuffer.writeUnsignedInt(length);
                flvGenerationBuffer.writeBytes(bytes, cursor, length);
                totalAppended += length;
            }, true );

            var flvts:uint = convertFLVTimestamp(unit.pts);
            var tsu:uint = convertFLVTimestamp(unit.pts - unit.dts);

            var codec:uint;
            if(keyFrame)
                codec = FLVTags.VIDEO_CODEC_AVC_KEYFRAME;
            else
                codec = FLVTags.VIDEO_CODEC_AVC_PREDICTIVEFRAME;

            //trace("ts=" + flvts + " tsu=" + tsu + " keyframe = " + keyFrame);

            sendFLVTag(flvts, FLVTags.TYPE_VIDEO, codec, FLVTags.AVC_MODE_PICTURE, flvGenerationBuffer, 0, flvGenerationBuffer.length);
        }

        private function compareBytesHelper(b1:ByteArray, b2:ByteArray):Boolean
        {
            var curPos:uint;

            if(b1.length != b2.length)
                return false;

            for(curPos = 0; curPos < b1.length; curPos++)
            {
                if(b1[curPos] != b2[curPos])
                    return false;
            }

            return true;
        }

        private function sendAACConfigFLVTag(flvts:uint, profile:uint, sampleRateIndex:uint, channelConfig:uint):void
        {
            var isNewConfig:Boolean = true;
            var audioSpecificConfig:ByteArray = new ByteArray();
            var audioObjectType:uint;

            audioSpecificConfig.length = 2;

            switch(profile)
            {
                case 0x00:
                    audioObjectType = 0x01;
                    break;
                case 0x01:
                    audioObjectType = 0x02;
                    break;
                case 0x02:
                    audioObjectType = 0x03;
                    break;
                default:
                    return;
            }

            audioSpecificConfig[0] = ((audioObjectType << 3) & 0xf8) + ((sampleRateIndex >> 1) & 0x07);
            audioSpecificConfig[1] = ((sampleRateIndex << 7) & 0x80) + ((channelConfig << 3) & 0x78);

            if(_aacConfig && compareBytesHelper(_aacConfig, audioSpecificConfig))
                isNewConfig = false;

            if(!isNewConfig)
                return;

            _aacConfig = audioSpecificConfig;
            sendFLVTag(flvts, FLVTags.TYPE_AUDIO, FLVTags.AUDIO_CODEC_AAC, FLVTags.AAC_MODE_CONFIG, _aacConfig, 0, _aacConfig.length);
        }

        /**
         * Convert and amit AAC data.
         */
        public function convertAAC(pes:PESPacket):void
        {
            var timeAccumulation:Number = 0.0;
            var limit:uint;
            var stream:ByteArray;
            var hadRemainder:Boolean = false;
            var cursor:int = 0;
            var length:int = pes.buffer.length;
            var bytes:ByteArray = pes.buffer;
            var timestamp:Number = pes.pts;

            if(_aacRemainder)
            {
                stream = _aacRemainder;
                stream.writeBytes(bytes, cursor, length);
                cursor = 0;
                length = stream.length;
                _aacRemainder = null;
                hadRemainder = true;
                timeAccumulation = _aacTimestamp - timestamp;
            }
            else
                stream = bytes;

            limit = cursor + length;

            // an AAC PES packet can contain multiple ADTS frames
            while(cursor < limit)
            {
                var remaining:uint = limit - cursor;
                var sampleRateIndex:uint;
                var sampleRate:Number = undefined;
                var profile:uint;
                var channelConfig:uint;
                var frameLength:uint;

                if(remaining < FLVTags.ADTS_FRAME_HEADER_LENGTH)
                    break;

                // search for syncword
                if(stream[cursor] != 0xff || (stream[cursor + 1] & 0xf0) != 0xf0)
                {
                    cursor++;
                    continue;
                }

                frameLength  = (stream[cursor + 3] & 0x03) << 11;
                frameLength += (stream[cursor + 4]) << 3;
                frameLength += (stream[cursor + 5] >> 5) & 0x07;

                // Check for an invalid ADTS header; if so look for next syncword.
                if(frameLength < FLVTags.ADTS_FRAME_HEADER_LENGTH)
                {
                    cursor++;
                    continue;
                }

                // Skip it till next PES packet.
                if(frameLength > remaining)
                    break;

                profile = (stream[cursor + 2] >> 6) & 0x03;

                sampleRateIndex = (stream[cursor + 2] >> 2) & 0x0f;
                switch(sampleRateIndex)
                {
                    case 0x00:
                        sampleRate = 96000.0;
                        break;
                    case 0x01:
                        sampleRate = 88200.0;
                        break;
                    case 0x02:
                        sampleRate = 64000.0;
                        break;
                    case 0x03:
                        sampleRate = 48000.0;
                        break;
                    case 0x04:
                        sampleRate = 44100.0;
                        break;
                    case 0x05:
                        sampleRate = 32000.0;
                        break;
                    case 0x06:
                        sampleRate = 24000.0;
                        break;
                    case 0x07:
                        sampleRate = 22050.0;
                        break;
                    case 0x08:
                        sampleRate = 16000.0;
                        break;
                    case 0x09:
                        sampleRate = 12000.0;
                        break;
                    case 0x0a:
                        sampleRate = 11025.0;
                        break;
                    case 0x0b:
                        sampleRate = 8000.0;
                        break;
                    case 0x0c:
                        sampleRate = 7350.0;
                        break;
                }

                channelConfig = ((stream[cursor + 2] & 0x01) << 2) + ((stream[cursor + 3] >> 6) & 0x03);

                if(sampleRate)
                {
                    var flvts:uint = convertFLVTimestamp(timestamp + timeAccumulation);

                    sendAACConfigFLVTag(flvts, profile, sampleRateIndex, channelConfig);
                    //trace("Sending AAC");
                    sendFLVTag(flvts, FLVTags.TYPE_AUDIO, FLVTags.AUDIO_CODEC_AAC, FLVTags.AAC_MODE_FRAME, stream, cursor + FLVTags.ADTS_FRAME_HEADER_LENGTH, frameLength - FLVTags.ADTS_FRAME_HEADER_LENGTH);

                    timeAccumulation += (1024.0 / sampleRate) * 90000.0; // account for the duration of this frame

                    if(hadRemainder)
                    {
                        timeAccumulation = 0.0;
                        hadRemainder = false;
                    }
                }

                cursor += frameLength;
            }

            if(cursor < limit)
            {
                //trace("AAC timestamp was " + _aacTimestamp);
                _aacRemainder = new ByteArray();
                _aacRemainder.writeBytes(stream, cursor, limit - cursor);
                _aacTimestamp = timestamp + timeAccumulation;
                //trace("AAC timestamp now " + _aacTimestamp);
            }
        }

        /**
         * Convert and amit MP3 data.
         */
        public function convertMP3(pes:PESPacket):void
        {
            sendFLVTag(convertFLVTimestamp(pes.pts), FLVTags.TYPE_AUDIO, FLVTags.AUDIO_CODEC_MP3, -1, pes.buffer, 0, pes.buffer.length);
        }

        private function generateScriptData(values:Array):ByteArray
        {
            var bytes:ByteArray = new ByteArray();
            bytes.objectEncoding = ObjectEncoding.AMF0;

            for each (var object:Object in values)
                bytes.writeObject(object);

            return bytes;
        }

        private function sendScriptDataFLVTag(flvts:uint, values:Array):void
        {
            var bytes:ByteArray = generateScriptData(values);
            sendFLVTag(flvts, FLVTags.TYPE_SCRIPTDATA, -1, -1, bytes, 0, bytes.length);
        }

        /**
         * Fire off a subtitle caption.
         */
        public function createAndSendCaptionMessage( timeStamp:Number, captionBuffer:String, lang:String="", textid:Number=99):void
        {
            var captionObject:Array = ["onCaptionInfo", { type:"WebVTT", data:captionBuffer }];
            //sendScriptDataFLVTag( timeStamp * 1000, captionObject);

            // We need to strip the timestamp off of the text data
            captionBuffer = captionBuffer.slice(captionBuffer.indexOf('\n') + 1);

            var subtitleObject:Array = ["onTextData", { text:captionBuffer, language:lang, trackid:textid }];
            sendScriptDataFLVTag( timeStamp * 1000, subtitleObject);
        }

    }
}

Fix for AAC packets getting 0 timestamps.


/**
 * User: MerlinDS
 * Date: 18.07.2014
 * Time: 15:14
 */
package com.merlinds.miracle_tool.controllers {
	import com.merlinds.debug.log;
	import com.merlinds.miracle.geom.Transformation;
	import com.merlinds.miracle_tool.events.ActionEvent;
	import com.merlinds.miracle_tool.events.DialogEvent;
	import com.merlinds.miracle_tool.models.ProjectModel;
	import com.merlinds.miracle_tool.models.vo.AnimationVO;
	import com.merlinds.miracle_tool.models.vo.ElementVO;
	import com.merlinds.miracle_tool.models.vo.FrameVO;
	import com.merlinds.miracle_tool.models.vo.SourceVO;
	import com.merlinds.miracle_tool.models.vo.TimelineVO;
	import com.merlinds.miracle_tool.services.ActionService;
	import com.merlinds.miracle_tool.services.FileSystemService;
	import com.merlinds.miracle_tool.utils.MeshUtils;
	import com.merlinds.unitls.Resolutions;

	import flash.display.BitmapData;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;

	import org.robotlegs.mvcs.Command;

	public class PublishCommand extends Command {

		[Inject]
		public var projectModel:ProjectModel;
		[Inject]
		public var fileSystemService:FileSystemService;
		[Inject]
		public var actionService:ActionService;
		[Inject]
		public var event:ActionEvent;

		private var _mesh:ByteArray;
		private var _png:ByteArray;
		private var _animations:ByteArray;

		private var _scale:Number;
		private var _elements:Object;
		//==============================================================================
		//{region							PUBLIC METHODS
		public function PublishCommand() {
			super();
		}

		override public function execute():void {
			log(this, "execute");
			if(event.body == null){
				var data:Object = {
					projectName:this.projectModel.name
				};
				this.actionService.addAcceptActions(new <String>[ActionEvent.PUBLISHING]);
				this.dispatch(new DialogEvent(DialogEvent.PUBLISH_SETTINGS, data));
			}else{
				var  projectName:String = event.body.projectName;
				_scale = Resolutions.width(this.projectModel.targetResolution) /
						Resolutions.width(this.projectModel.referenceResolution);
				this.createOutput();
				this.fileSystemService.writeTexture(projectName, _png, _mesh);
				this.fileSystemService.writeAnimation(_animations);
			}
		}

		//} endregion PUBLIC METHODS ===================================================

		//==============================================================================
		//{region						PRIVATE\PROTECTED METHODS
		private function createOutput():void{
			var buffer:BitmapData = new BitmapData(this.projectModel.outputSize, this.projectModel.outputSize, true, 0x0);
			_elements = {};
			var meshes:Array = [];
			var animations:Array = [];
			var n:int = this.projectModel.sources.length;
			for(var i:int = 0; i < n; i++){
				var mesh:Array = [];
				var source:SourceVO = this.projectModel.sources[i];
				var m:int = source.elements.length;
				for(var j:int = 0; j < m; j++){
					//push element view to buffer
					var element:ElementVO = source.elements[j];
					var depth:Point = new Point(element.x + this.projectModel.boundsOffset,
									element.y + this.projectModel.boundsOffset);
					buffer.copyPixels(element.bitmapData, element.bitmapData.rect, depth);
					//get mesh
					mesh.push({
						name:element.name,
						vertexes:MeshUtils.flipToY(element.vertexes),
						uv:MeshUtils.covertToRelative(element.uv, this.projectModel.outputSize),
						indexes:element.indexes
					});
					//save mesh bounds to buffer for animation bounds calculation
					_elements[element.name] = element.vertexes;
				}
				meshes.push({name:source.clearName, mesh:mesh});
				//get animation
				m = source.animations.length;
				for(j = 0; j < m; j++){
					var animation:Object = this.createAnimationOutput(source.animations[j], source.clearName);
					animations.push(animation);
				}
			}
			trace("mesh");
			var json:String = JSON.stringify(meshes);
			trace(json);
			_mesh = new ByteArray();
			_mesh.writeObject(meshes);
			_png = PNGEncoder.encode(buffer);
			_animations = new ByteArray();
			_animations.writeObject(animations);
		}

		private function createAnimationOutput(animationVO:AnimationVO, meshPrefix:String):Object {
			var data:Object = { name:meshPrefix + "." + animationVO.name,// name of the matrix
				totalFrames:animationVO.totalFrames,// Total animation frames
				bounds:animationVO.bounds.clone(),
				layers:[]};
			var n:int = animationVO.timelines.length;
			//find matrix sequence for current animation
			for(var i:int = 0; i < n; i++){
				var timelineVO:TimelineVO = animationVO.timelines[i];
				var m:int = timelineVO.frames.length;
				var layer:Layer = new Layer();
				for(var j:int = 0; j < m; j++){
					var frameVO:FrameVO = timelineVO.frames[j];
					//create matrix
					var transform:Transformation = frameVO.generateTransform(_scale,
							//get previous frame transformation object
							layer.matrixList.length > 0 ? layer.matrixList[ layer.matrixList.length - 1] : null
					);
					var index:int = transform == null ? -1 : layer.matrixList.push(transform) - 1;
					var framesArray:Array = this.createFramesInfo(index, frameVO.name,
							frameVO.duration, frameVO.type == "motion");
					layer.framesList = layer.framesList.concat(framesArray);
				}
				data.layers.unshift(layer);
			}
			trace(JSON.stringify(data));
			return data;
		}

		[Inline]
		private function createFramesInfo(index:int, polygonName:String,
		                                  duration:int, motion:Boolean):Array {
			var result:Array = new Array(duration);
			if(duration < 2){
				motion = false;
			}
			if(index > -1){
				var t:Number = 1 / duration;
				for(var i:int = 0; i < duration; i++){
					var frameInfoData:FrameInfoData = new FrameInfoData();
					frameInfoData.index = index;
					frameInfoData.polygonName = polygonName;
					frameInfoData.motion = motion;
					frameInfoData.t = motion ? t * i : 0;
					result[i] = frameInfoData;
				}
			}
			return result;
		}

		//} endregion PRIVATE\PROTECTED METHODS ========================================

		//==============================================================================
		//{region							EVENTS HANDLERS
		//} endregion EVENTS HANDLERS ==================================================

		//==============================================================================
		//{region							GETTERS/SETTERS
		//} endregion GETTERS/SETTERS ==================================================
	}
}
class Layer{
	public var matrixList:Array;
	public var framesList:Array;

	public function Layer() {
		this.framesList = [];
		this.matrixList = [];
	}
}

class FrameInfoData{
	public var polygonName:String;
	public var motion:Boolean;
	public var index:int;
	public var t:Number;
}

/**
 * User: MerlinDS
 * Date: 18.07.2014
 * Time: 15:14
 */
package com.merlinds.miracle_tool.controllers {
	import com.merlinds.debug.log;
	import com.merlinds.miracle.geom.Transformation;
	import com.merlinds.miracle_tool.events.ActionEvent;
	import com.merlinds.miracle_tool.events.DialogEvent;
	import com.merlinds.miracle_tool.models.ProjectModel;
	import com.merlinds.miracle_tool.models.vo.AnimationVO;
	import com.merlinds.miracle_tool.models.vo.ElementVO;
	import com.merlinds.miracle_tool.models.vo.FrameVO;
	import com.merlinds.miracle_tool.models.vo.SourceVO;
	import com.merlinds.miracle_tool.models.vo.TimelineVO;
	import com.merlinds.miracle_tool.services.ActionService;
	import com.merlinds.miracle_tool.services.FileSystemService;
	import com.merlinds.miracle_tool.utils.MeshUtils;
	import com.merlinds.unitls.Resolutions;

	import flash.display.BitmapData;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;

	import org.robotlegs.mvcs.Command;

	public class PublishCommand extends Command {

		[Inject]
		public var projectModel:ProjectModel;
		[Inject]
		public var fileSystemService:FileSystemService;
		[Inject]
		public var actionService:ActionService;
		[Inject]
		public var event:ActionEvent;

		private var _mesh:ByteArray;
		private var _png:ByteArray;
		private var _animations:ByteArray;

		private var _scale:Number;
		private var _elements:Object;
		//==============================================================================
		//{region							PUBLIC METHODS
		public function PublishCommand() {
			super();
		}

		override public function execute():void {
			log(this, "execute");
			if(event.body == null){
				var data:Object = {
					projectName:this.projectModel.name
				};
				this.actionService.addAcceptActions(new <String>[ActionEvent.PUBLISHING]);
				this.dispatch(new DialogEvent(DialogEvent.PUBLISH_SETTINGS, data));
			}else{
				var  projectName:String = event.body.projectName;
				_scale = Resolutions.width(this.projectModel.targetResolution) /
						Resolutions.width(this.projectModel.referenceResolution);
				this.createOutput();
				this.fileSystemService.writeTexture(projectName, _png, _mesh);
				this.fileSystemService.writeAnimation(_animations);
			}
		}

		//} endregion PUBLIC METHODS ===================================================

		//==============================================================================
		//{region						PRIVATE\PROTECTED METHODS
		private function createOutput():void{
			var buffer:BitmapData = new BitmapData(this.projectModel.outputSize, this.projectModel.outputSize, true, 0x0);
			_elements = {};
			var meshes:Array = [];
			var animations:Array = [];
			var n:int = this.projectModel.sources.length;
			for(var i:int = 0; i < n; i++){
				var mesh:Array = [];
				var source:SourceVO = this.projectModel.sources[i];
				var m:int = source.elements.length;
				for(var j:int = 0; j < m; j++){
					//push element view to buffer
					var element:ElementVO = source.elements[j];
					var depth:Point = new Point(element.x + this.projectModel.boundsOffset,
									element.y + this.projectModel.boundsOffset);
					buffer.copyPixels(element.bitmapData, element.bitmapData.rect, depth);
					//get mesh
					mesh.push({
						name:element.name,
						vertexes:MeshUtils.flipToY(element.vertexes),
						uv:MeshUtils.covertToRelative(element.uv, this.projectModel.outputSize),
						indexes:element.indexes
					});
					//save mesh bounds to buffer for animation bounds calculation
					_elements[element.name] = element.vertexes;
				}
				meshes.push({name:source.clearName, mesh:mesh});
				//get animation
				m = source.animations.length;
				for(j = 0; j < m; j++){
					var animation:Object = this.createAnimationOutput(source.animations[j], source.clearName);
					animations.push(animation);
				}
			}
			trace("mesh");
			var json:String = JSON.stringify(meshes);
			trace(json);
			_mesh = new ByteArray();
			_mesh.writeObject(meshes);
			_png = PNGEncoder.encode(buffer);
			_animations = new ByteArray();
			_animations.writeObject(animations);
		}

		private function createAnimationOutput(animationVO:AnimationVO, meshPrefix:String):Object {
			var data:Object = { name:meshPrefix + "." + animationVO.name,// name of the matrix
				totalFrames:animationVO.totalFrames,// Total animation frames
				layers:[]};
			//scale bounds
			var bounds:Rectangle = animationVO.bounds.clone();
			bounds.x = bounds.x * _scale;
			bounds.y = bounds.y * _scale;
			bounds.width = bounds.width * _scale;
			bounds.height = bounds.height * _scale;
			data.bounds = bounds;
			//calculate frames
			var n:int = animationVO.timelines.length;
			//find matrix sequence for current animation
			for(var i:int = 0; i < n; i++){
				var timelineVO:TimelineVO = animationVO.timelines[i];
				var m:int = timelineVO.frames.length;
				var layer:Layer = new Layer();
				for(var j:int = 0; j < m; j++){
					var frameVO:FrameVO = timelineVO.frames[j];
					//create matrix
					var transform:Transformation = frameVO.generateTransform(_scale,
							//get previous frame transformation object
							layer.matrixList.length > 0 ? layer.matrixList[ layer.matrixList.length - 1] : null
					);
					var index:int = transform == null ? -1 : layer.matrixList.push(transform) - 1;
					var framesArray:Array = this.createFramesInfo(index, frameVO.name,
							frameVO.duration, frameVO.type == "motion");
					layer.framesList = layer.framesList.concat(framesArray);
				}
				data.layers.unshift(layer);
			}
			trace(JSON.stringify(data));
			return data;
		}

		[Inline]
		private function createFramesInfo(index:int, polygonName:String,
		                                  duration:int, motion:Boolean):Array {
			var result:Array = new Array(duration);
			if(duration < 2){
				motion = false;
			}
			if(index > -1){
				var t:Number = 1 / duration;
				for(var i:int = 0; i < duration; i++){
					var frameInfoData:FrameInfoData = new FrameInfoData();
					frameInfoData.index = index;
					frameInfoData.polygonName = polygonName;
					frameInfoData.motion = motion;
					frameInfoData.t = motion ? t * i : 0;
					result[i] = frameInfoData;
				}
			}
			return result;
		}

		//} endregion PRIVATE\PROTECTED METHODS ========================================

		//==============================================================================
		//{region							EVENTS HANDLERS
		//} endregion EVENTS HANDLERS ==================================================

		//==============================================================================
		//{region							GETTERS/SETTERS
		//} endregion GETTERS/SETTERS ==================================================
	}
}
class Layer{
	public var matrixList:Array;
	public var framesList:Array;

	public function Layer() {
		this.framesList = [];
		this.matrixList = [];
	}
}

class FrameInfoData{
	public var polygonName:String;
	public var motion:Boolean;
	public var index:int;
	public var t:Number;
}

Fix bounds scaling

Fix bounds scaling


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

    public class ImpetusSound
    {
        private var sound:Sound;

        private var channels:Vector.<ImpetusChannel>;

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

            this.channels = new Vector.<ImpetusChannel>;

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

        public function playNew():ImpetusChannel
        {
            var c:ImpetusChannel = new ImpetusChannel(this.sound.play(0));

            channels.push(c);

            return c;
        }

        public function stopAll():void
        {
            var len:int = this.channels.length;

            for(var i:int; i < len; i++)
            {
                this.channels[i].stop();
            }
        }
    }
}

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

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

        private var channels:Vector.<ImpetusChannel>;

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

            this.channels = new Vector.<ImpetusChannel>;

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

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

        public function playNew():ImpetusChannel
        {
            var c:ImpetusChannel = new ImpetusChannel(this.sound.play(0));

            channels.push(c);

            return c;
        }

        public function stopAll():void
        {
            var len:int = this.channels.length;

            for(var i:int; i < len; i++)
            {
                this.channels[i].stop();
            }
        }
    }
}

Store url & add getUrl() getter

Store url & add getUrl() getter


////////////////////////////////////////////////////////////////////////////////
//
//  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
{

/**
 *  @private
 *  This class is used to link additional classes into framework.swc
 *  beyond those that are found by dependecy analysis starting
 *  from the classes specified in manifest.xml.
 *  For example, Button does not have a reference to ButtonSkin,
 *  but ButtonSkin needs to be in framework.swc along with Button.
 */
internal class FrameworkClasses
{
	import mx.binding.ArrayElementWatcher; ArrayElementWatcher;
	import mx.binding.BindabilityInfo; BindabilityInfo;
	import mx.binding.EvalBindingResponder; EvalBindingResponder;
	import mx.binding.FunctionReturnWatcher; FunctionReturnWatcher;
	import mx.binding.IBindingClient; IBindingClient;
	import mx.binding.IWatcherSetupUtil; IWatcherSetupUtil;
	import mx.binding.IWatcherSetupUtil2; IWatcherSetupUtil2;
	import mx.binding.PropertyWatcher; PropertyWatcher;
	import mx.binding.RepeatableBinding; RepeatableBinding;
	import mx.binding.RepeaterComponentWatcher; RepeaterComponentWatcher;
	import mx.binding.RepeaterItemWatcher; RepeaterItemWatcher;
	import mx.binding.StaticPropertyWatcher; StaticPropertyWatcher;
	import mx.binding.XMLWatcher; XMLWatcher;
	import mx.binding.utils.BindingUtils; BindingUtils;
	import mx.binding.utils.ChangeWatcher; ChangeWatcher;
	import mx.collections.ItemWrapper; ItemWrapper;
	import mx.containers.errors.ConstraintError; ConstraintError;
	import mx.containers.utilityClasses.Flex; Flex;
	import mx.collections.ModifiedCollectionView; ModifiedCollectionView;
	import mx.containers.utilityClasses.FlexChildInfo; FlexChildInfo;
	import mx.containers.utilityClasses.IConstraintLayout; IConstraintLayout;
    import mx.containers.utilityClasses.PostScaleAdapter; PostScaleAdapter;
	import mx.controls.ButtonLabelPlacement; ButtonLabelPlacement;
	import mx.controls.MovieClipSWFLoader; MovieClipSWFLoader;
	import mx.controls.ProgressBarDirection; ProgressBarDirection;
	import mx.controls.ProgressBarLabelPlacement; ProgressBarLabelPlacement;
	import mx.controls.ProgressBarMode; ProgressBarMode;
	import mx.controls.colorPickerClasses.WebSafePalette; WebSafePalette;
	import mx.controls.menuClasses.IMenuDataDescriptor; IMenuDataDescriptor;
	import mx.controls.listClasses.IDropInListItemRenderer; IDropInListItemRenderer;
	import mx.controls.listClasses.IListItemRenderer; IListItemRenderer;
	import mx.core.BitmapAsset; BitmapAsset;
	import mx.core.ButtonAsset; ButtonAsset;
	import mx.core.ByteArrayAsset; ByteArrayAsset;
	import mx.core.ClassFactory; ClassFactory;
	import mx.core.ContainerGlobals; ContainerGlobals;
	import mx.core.ContextualClassFactory; ContextualClassFactory;
	import mx.core.CrossDomainRSLItem; CrossDomainRSLItem;
    import mx.core.DebuggableWorker; DebuggableWorker;
	import mx.core.DeferredInstanceFromClass; DeferredInstanceFromClass;
	import mx.core.DeferredInstanceFromFunction; DeferredInstanceFromFunction;
	import mx.core.DesignLayer; DesignLayer;
    import mx.core.EmbeddedFontRegistry; EmbeddedFontRegistry;
	import mx.core.FlexLoader; FlexLoader;
	import mx.core.FontAsset; FontAsset;
	import mx.core.IDataRenderer; IDataRenderer;
	import mx.core.IDeferredInstance; IDeferredInstance;
	import mx.core.INavigatorContent; INavigatorContent;
	import mx.core.ISelectableList; ISelectableList;
	import mx.core.ISystemCursorClient; ISystemCursorClient;
	import mx.core.ITextInput; ITextInput;
    import mx.core.InteractionMode; InteractionMode;
	import mx.core.IUID; IUID;
	import mx.core.MovieClipAsset; MovieClipAsset;
	import mx.core.MovieClipLoaderAsset; MovieClipLoaderAsset;
	import mx.core.MXMLObjectAdapter; MXMLObjectAdapter;
	import mx.core.ScrollPolicy; ScrollPolicy;
	import mx.core.SimpleApplication; SimpleApplication;
	import mx.core.SoundAsset; SoundAsset;
	import mx.core.TextFieldAsset; TextFieldAsset;
	import mx.core.TextFieldFactory; TextFieldFactory;
	import mx.effects.easing.Back; Back;
	import mx.effects.easing.Bounce; Bounce;
	import mx.effects.easing.Circular; Circular;
	import mx.effects.easing.Elastic; Elastic;
	import mx.effects.easing.Exponential; Exponential;
	import mx.events.CloseEvent; CloseEvent;
	import mx.events.DropdownEvent; DropdownEvent;
    import mx.events.IndexChangedEvent; IndexChangedEvent;
	import mx.events.ItemClickEvent; ItemClickEvent;
	import mx.events.ModuleEvent; ModuleEvent;
    import mx.events.TouchInteractionEvent; TouchInteractionEvent;
    import mx.events.TouchInteractionReason; TouchInteractionReason;
	import mx.filters.BaseFilter; BaseFilter;
	import mx.filters.BaseDimensionFilter; BaseDimensionFilter;
	import mx.filters.IBitmapFilter; IBitmapFilter;
    import mx.formatters.IFormatter; IFormatter;
	import mx.graphics.ImageSnapshot; ImageSnapshot;
	import mx.graphics.codec.PNGEncoder; PNGEncoder;
	import mx.graphics.codec.JPEGEncoder; JPEGEncoder;
    import mx.graphics.shaderClasses.ColorBurnShader; ColorBurnShader;
    import mx.graphics.shaderClasses.ColorDodgeShader; ColorDodgeShader;
    import mx.graphics.shaderClasses.ColorShader; ColorShader;
    import mx.graphics.shaderClasses.ExclusionShader; ExclusionShader;
    import mx.graphics.shaderClasses.HueShader; HueShader;
    import mx.graphics.shaderClasses.LuminosityShader; LuminosityShader;
    import mx.graphics.shaderClasses.LuminosityMaskShader; LuminosityMaskShader;
    import mx.graphics.shaderClasses.SaturationShader; SaturationShader;
    import mx.graphics.shaderClasses.SoftLightShader; SoftLightShader;
	import mx.logging.ILogger; ILogger;
	import mx.logging.Log; Log;
	import mx.logging.targets.TraceTarget; TraceTarget;
	import mx.managers.DragManager; DragManager;
	import mx.managers.HistoryManager; HistoryManager;
	import mx.managers.IHistoryManagerClient; IHistoryManagerClient;
	import mx.managers.marshalClasses.CursorManagerMarshalMixin; CursorManagerMarshalMixin;
	import mx.managers.marshalClasses.DragManagerMarshalMixin; DragManagerMarshalMixin;
	import mx.managers.marshalClasses.FocusManagerMarshalMixin; FocusManagerMarshalMixin;
	import mx.managers.marshalClasses.PopUpManagerMarshalMixin; PopUpManagerMarshalMixin;
	import mx.managers.marshalClasses.ToolTipManagerMarshalMixin; ToolTipManagerMarshalMixin;
    import mx.managers.PopUpManager; PopUpManager;
	import mx.managers.systemClasses.ActiveWindowManager; ActiveWindowManager;
	import mx.managers.systemClasses.ChildManager; ChildManager;
	import mx.managers.systemClasses.MarshallingSupport; MarshallingSupport;
	import mx.messaging.config.LoaderConfig; LoaderConfig;
	import mx.modules.IModuleInfo; IModuleInfo;
	import mx.modules.ModuleBase; ModuleBase;
	import mx.modules.ModuleManager; ModuleManager;
    import mx.preloaders.DownloadProgressBar; DownloadProgressBar;
    import mx.preloaders.SparkDownloadProgressBar; SparkDownloadProgressBar;
	import mx.printing.FlexPrintJob; FlexPrintJob;
	import mx.resources.Locale; Locale;
	import mx.rpc.IResponder; IResponder;
	import mx.skins.Border; Border;
	import mx.skins.halo.BrokenImageBorderSkin; BrokenImageBorderSkin;
	import mx.skins.halo.BusyCursor; BusyCursor;
	import mx.skins.halo.DefaultDragImage; DefaultDragImage;
	import mx.skins.halo.HaloFocusRect; HaloFocusRect;
	import mx.skins.halo.ListDropIndicator; ListDropIndicator;
	import mx.skins.halo.ToolTipBorder; ToolTipBorder;
	import mx.skins.ProgrammaticSkin; ProgrammaticSkin;
	import mx.skins.RectangularBorder; RectangularBorder;
	import mx.styles.IStyleModule; IStyleModule;
	import mx.styles.AdvancedStyleClient; AdvancedStyleClient;
	import mx.utils.ArrayUtil; ArrayUtil;
	import mx.utils.Base64Decoder; Base64Decoder;
	import mx.utils.Base64Encoder; Base64Encoder;
	import mx.utils.BitFlagUtil; BitFlagUtil;
	import mx.utils.DescribeTypeCache; DescribeTypeCache;
	import mx.utils.DescribeTypeCacheRecord; DescribeTypeCacheRecord;
	import mx.utils.DisplayUtil; DisplayUtil;
    import mx.utils.GetTimerUtil; GetTimerUtil;
    import mx.utils.HSBColor; HSBColor;
    import mx.utils.LinkedList; LinkedList;
	import mx.utils.LinkedListNode; LinkedListNode;
	import mx.utils.OnDemandEventDispatcher; OnDemandEventDispatcher;
	import mx.utils.OrderedObject; OrderedObject;
    import mx.utils.PopUpUtil; PopUpUtil;
	import mx.utils.XMLUtil; XMLUtil;
	import mx.validators.Validator; Validator;
	// Maintain alphabetical order
}

}

////////////////////////////////////////////////////////////////////////////////
//
//  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
{

/**
 *  @private
 *  This class is used to link additional classes into framework.swc
 *  beyond those that are found by dependecy analysis starting
 *  from the classes specified in manifest.xml.
 *  For example, Button does not have a reference to ButtonSkin,
 *  but ButtonSkin needs to be in framework.swc along with Button.
 */
internal class FrameworkClasses
{
	import mx.binding.ArrayElementWatcher; ArrayElementWatcher;
	import mx.binding.BindabilityInfo; BindabilityInfo;
	import mx.binding.EvalBindingResponder; EvalBindingResponder;
	import mx.binding.FunctionReturnWatcher; FunctionReturnWatcher;
	import mx.binding.IBindingClient; IBindingClient;
	import mx.binding.IWatcherSetupUtil; IWatcherSetupUtil;
	import mx.binding.IWatcherSetupUtil2; IWatcherSetupUtil2;
	import mx.binding.PropertyWatcher; PropertyWatcher;
	import mx.binding.RepeatableBinding; RepeatableBinding;
	import mx.binding.RepeaterComponentWatcher; RepeaterComponentWatcher;
	import mx.binding.RepeaterItemWatcher; RepeaterItemWatcher;
	import mx.binding.StaticPropertyWatcher; StaticPropertyWatcher;
	import mx.binding.XMLWatcher; XMLWatcher;
	import mx.binding.utils.BindingUtils; BindingUtils;
	import mx.binding.utils.ChangeWatcher; ChangeWatcher;
	import mx.collections.ItemWrapper; ItemWrapper;
	import mx.containers.errors.ConstraintError; ConstraintError;
	import mx.containers.utilityClasses.Flex; Flex;
	import mx.collections.ModifiedCollectionView; ModifiedCollectionView;
	import mx.containers.utilityClasses.FlexChildInfo; FlexChildInfo;
	import mx.containers.utilityClasses.IConstraintLayout; IConstraintLayout;
    import mx.containers.utilityClasses.PostScaleAdapter; PostScaleAdapter;
	import mx.controls.ButtonLabelPlacement; ButtonLabelPlacement;
	import mx.controls.MovieClipSWFLoader; MovieClipSWFLoader;
	import mx.controls.ProgressBarDirection; ProgressBarDirection;
	import mx.controls.ProgressBarLabelPlacement; ProgressBarLabelPlacement;
	import mx.controls.ProgressBarMode; ProgressBarMode;
	import mx.controls.colorPickerClasses.WebSafePalette; WebSafePalette;
	import mx.controls.menuClasses.IMenuDataDescriptor; IMenuDataDescriptor;
	import mx.controls.listClasses.IDropInListItemRenderer; IDropInListItemRenderer;
	import mx.controls.listClasses.IListItemRenderer; IListItemRenderer;
	import mx.core.BitmapAsset; BitmapAsset;
	import mx.core.ButtonAsset; ButtonAsset;
	import mx.core.ByteArrayAsset; ByteArrayAsset;
	import mx.core.ClassFactory; ClassFactory;
	import mx.core.ContainerGlobals; ContainerGlobals;
	import mx.core.ContextualClassFactory; ContextualClassFactory;
	import mx.core.CrossDomainRSLItem; CrossDomainRSLItem;
    import mx.core.DebuggableWorker; DebuggableWorker;
	import mx.core.DeferredInstanceFromClass; DeferredInstanceFromClass;
	import mx.core.DeferredInstanceFromFunction; DeferredInstanceFromFunction;
	import mx.core.DesignLayer; DesignLayer;
    import mx.core.EmbeddedFontRegistry; EmbeddedFontRegistry;
	import mx.core.FlexLoader; FlexLoader;
	import mx.core.FontAsset; FontAsset;
	import mx.core.IDataRenderer; IDataRenderer;
	import mx.core.IDeferredInstance; IDeferredInstance;
	import mx.core.INavigatorContent; INavigatorContent;
	import mx.core.ISelectableList; ISelectableList;
	import mx.core.ISystemCursorClient; ISystemCursorClient;
	import mx.core.ITextInput; ITextInput;
    import mx.core.InteractionMode; InteractionMode;
	import mx.core.IUID; IUID;
	import mx.core.MovieClipAsset; MovieClipAsset;
	import mx.core.MovieClipLoaderAsset; MovieClipLoaderAsset;
	import mx.core.MXMLObjectAdapter; MXMLObjectAdapter;
	import mx.core.ScrollPolicy; ScrollPolicy;
	import mx.core.SimpleApplication; SimpleApplication;
	import mx.core.SoundAsset; SoundAsset;
	import mx.core.TextFieldAsset; TextFieldAsset;
	import mx.core.TextFieldFactory; TextFieldFactory;
	import mx.effects.easing.Back; Back;
	import mx.effects.easing.Bounce; Bounce;
	import mx.effects.easing.Circular; Circular;
	import mx.effects.easing.Elastic; Elastic;
	import mx.effects.easing.Exponential; Exponential;
	import mx.events.CloseEvent; CloseEvent;
	import mx.events.DropdownEvent; DropdownEvent;
    import mx.events.IndexChangedEvent; IndexChangedEvent;
	import mx.events.ItemClickEvent; ItemClickEvent;
	import mx.events.ModuleEvent; ModuleEvent;
    import mx.events.TouchInteractionEvent; TouchInteractionEvent;
    import mx.events.TouchInteractionReason; TouchInteractionReason;
	import mx.filters.BaseFilter; BaseFilter;
	import mx.filters.BaseDimensionFilter; BaseDimensionFilter;
	import mx.filters.IBitmapFilter; IBitmapFilter;
    import mx.formatters.IFormatter; IFormatter;
	import mx.graphics.ImageSnapshot; ImageSnapshot;
	import mx.graphics.codec.PNGEncoder; PNGEncoder;
	import mx.graphics.codec.JPEGEncoder; JPEGEncoder;
    import mx.graphics.shaderClasses.ColorBurnShader; ColorBurnShader;
    import mx.graphics.shaderClasses.ColorDodgeShader; ColorDodgeShader;
    import mx.graphics.shaderClasses.ColorShader; ColorShader;
    import mx.graphics.shaderClasses.ExclusionShader; ExclusionShader;
    import mx.graphics.shaderClasses.HueShader; HueShader;
    import mx.graphics.shaderClasses.LuminosityShader; LuminosityShader;
    import mx.graphics.shaderClasses.LuminosityMaskShader; LuminosityMaskShader;
    import mx.graphics.shaderClasses.SaturationShader; SaturationShader;
    import mx.graphics.shaderClasses.SoftLightShader; SoftLightShader;
	import mx.logging.ILogger; ILogger;
	import mx.logging.Log; Log;
	import mx.logging.targets.TraceTarget; TraceTarget;
	import mx.managers.DragManager; DragManager;
	import mx.managers.HistoryManager; HistoryManager;
	import mx.managers.IHistoryManagerClient; IHistoryManagerClient;
	import mx.managers.marshalClasses.CursorManagerMarshalMixin; CursorManagerMarshalMixin;
	import mx.managers.marshalClasses.DragManagerMarshalMixin; DragManagerMarshalMixin;
	import mx.managers.marshalClasses.FocusManagerMarshalMixin; FocusManagerMarshalMixin;
	import mx.managers.marshalClasses.PopUpManagerMarshalMixin; PopUpManagerMarshalMixin;
	import mx.managers.marshalClasses.ToolTipManagerMarshalMixin; ToolTipManagerMarshalMixin;
    import mx.managers.PopUpManager; PopUpManager;
	import mx.managers.systemClasses.ActiveWindowManager; ActiveWindowManager;
	import mx.managers.systemClasses.ChildManager; ChildManager;
	import mx.managers.systemClasses.MarshallingSupport; MarshallingSupport;
	import mx.messaging.config.LoaderConfig; LoaderConfig;
	import mx.modules.IModuleInfo; IModuleInfo;
	import mx.modules.ModuleBase; ModuleBase;
	import mx.modules.ModuleManager; ModuleManager;
    import mx.preloaders.DownloadProgressBar; DownloadProgressBar;
    import mx.preloaders.SparkDownloadProgressBar; SparkDownloadProgressBar;
	import mx.printing.FlexPrintJob; FlexPrintJob;
	import mx.resources.Locale; Locale;
	import mx.rpc.IResponder; IResponder;
	import mx.skins.Border; Border;
	import mx.skins.halo.BrokenImageBorderSkin; BrokenImageBorderSkin;
	import mx.skins.halo.BusyCursor; BusyCursor;
	import mx.skins.halo.DefaultDragImage; DefaultDragImage;
	import mx.skins.halo.HaloFocusRect; HaloFocusRect;
	import mx.skins.halo.ListDropIndicator; ListDropIndicator;
	import mx.skins.halo.ToolTipBorder; ToolTipBorder;
	import mx.skins.ProgrammaticSkin; ProgrammaticSkin;
	import mx.skins.RectangularBorder; RectangularBorder;
	import mx.styles.IStyleModule; IStyleModule;
	import mx.styles.AdvancedStyleClient; AdvancedStyleClient;
	import mx.utils.ArrayUtil; ArrayUtil;
	import mx.utils.AndroidPlatformVersionOverride; AndroidPlatformVersionOverride;
	import mx.utils.Base64Decoder; Base64Decoder;
	import mx.utils.Base64Encoder; Base64Encoder;
	import mx.utils.BitFlagUtil; BitFlagUtil;
	import mx.utils.DescribeTypeCache; DescribeTypeCache;
	import mx.utils.DescribeTypeCacheRecord; DescribeTypeCacheRecord;
	import mx.utils.DisplayUtil; DisplayUtil;
    import mx.utils.GetTimerUtil; GetTimerUtil;
    import mx.utils.HSBColor; HSBColor;
    import mx.utils.LinkedList; LinkedList;
	import mx.utils.LinkedListNode; LinkedListNode;
	import mx.utils.OnDemandEventDispatcher; OnDemandEventDispatcher;
	import mx.utils.OrderedObject; OrderedObject;
    import mx.utils.PopUpUtil; PopUpUtil;
	import mx.utils.XMLUtil; XMLUtil;
	import mx.validators.Validator; Validator;
	// Maintain alphabetical order
}

}

Add AndroidPlatformVersionOverride to FrameworkClasses