package {
	import flash.system.*;
	import flash.net.*;
	import flash.external.*;
	import flash.display.*;
	import flash.events.*;
	import fl.transitions.easing.*;
	import fl.transitions.Tween;
  import flash.globalization.CurrencyFormatter;

	public class ShopbeamWidget extends MovieClip {
		public function ShopbeamWidget() {
      brandName.alpha = 0;
      productName.alpha = 0;
      listPrice.alpha = 0;
      salePrice.alpha = 0;

			var SHOP_HERE_TWEEN_X: int = 180;
			var SHOP_HERE_INITIAL_X: int = hoverMovie.x;
			var bagActive: Sprite = hoverMovie.bagActive;
			var bagInactive: Sprite = hoverMovie.bagInactive;

      function tweenTo(object: DisplayObject, property: String, value: *, duration: int = 30, durationInSeconds: Boolean = false): Tween {
        return new Tween(object, property, Strong.easeOut, object[property], value, 30);
      }

      function tweenAlpha(object: DisplayObject, opacity: Number, duration: int = 30, durationInSeconds: Boolean = false): Tween {
        return tweenTo(object, 'alpha', opacity, duration, durationInSeconds);
      }

      function fadeIn(object: DisplayObject, duration: int = 30, durationInSeconds: Boolean = false): void {
        tweenAlpha(object, 1, duration, durationInSeconds)
      }

      function fadeOut(object: DisplayObject, duration: int = 30, durationInSeconds: Boolean = false): void {
        tweenAlpha(object, 0, duration, durationInSeconds)
      }

			hoverArea.addEventListener(MouseEvent.MOUSE_OVER, function(event:MouseEvent):void {
        fadeIn(listPrice);
        if (listPrice.text !== salePrice.text) {
          fadeIn(strikeThrough);
          fadeIn(salePrice);
        }

        fadeIn(brandName);
        fadeIn(productName);
        fadeIn(bagActive);
        fadeOut(bagInactive);
        tweenAlpha(backdrop, 0.6);
        tweenTo(hoverMovie, 'x', SHOP_HERE_TWEEN_X);
			});

			hoverArea.addEventListener(MouseEvent.MOUSE_OUT, function(event:MouseEvent):void {
        fadeOut(salePrice);
        fadeOut(listPrice);
        fadeOut(strikeThrough);

        fadeOut(brandName);
        fadeOut(productName);
        fadeOut(bagActive);
        fadeIn(bagInactive);
        fadeOut(backdrop);
        tweenTo(hoverMovie, 'x', SHOP_HERE_INITIAL_X);
			});

			function log(): void {
				ExternalInterface.call('console.log', arguments.join(' '));
			}

			function logError(): void {
				ExternalInterface.call('console.error', arguments.join(' '));
			}

			function executeJS(js): void {
				var wrapped = 'try {\n' + js + '\n}catch(err){console.error(err);console.error(err.stack);}';
				ExternalInterface.call('eval', wrapped);
			}

			Security.allowDomain('*');

			var widgetUuid: String = stage.loaderInfo.parameters.widgetUuid;
			var loader: Loader = new Loader();
			var widgetData: Object;

      ExternalInterface.addCallback('setWidgetData', function setWidgetData(data: String): void {
        widgetData = JSON.parse(data);
        brandName.text = widgetData.initialProduct.brandName;
        productName.text = widgetData.initialProduct.name;

        var dollarFormatter: CurrencyFormatter = new CurrencyFormatter('usd');
        listPrice.text = dollarFormatter.format((widgetData.initialVariant.listPrice / 100), true);
        //strikeThrough.width ...
        salePrice.text = dollarFormatter.format((widgetData.initialVariant.salePrice / 100), true);
      });

			stage.align = StageAlign.TOP_LEFT;
      stage.scaleMode = StageScaleMode.NO_SCALE;
			var button: Sprite = new Sprite();
      button.addChild(loader);

      //required for `.useHandCursor` to work
      hoverArea.buttonMode = true;
      hoverArea.useHandCursor = true;
      addChild(button);

			setChildIndex(button, 0);

			function loadingError(e: IOErrorEvent): void {
				logError('widget with id: ' + widgetUuid + ' failed to load image');
			}

			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadingError);

			function doneLoad(e: Event): void {
				loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, doneLoad);
				loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, loadingError);
			}
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, doneLoad);

			function loaderClickHandler(e: Event): void {
				log('widgetOpenLightbox' + widgetUuid);
				executeJS("Shopbeam.swfOpenLightbox('" + widgetUuid + "')");
			}

			hoverArea.addEventListener(MouseEvent.CLICK, loaderClickHandler);

			log('loading image: ' + stage.loaderInfo.parameters.imageUrl);
			loader.load(new URLRequest(stage.loaderInfo.parameters.imageUrl));
		}
	}
}

package {

import flash.system.*;
import flash.net.*;
import flash.external.*;
import flash.display.*;
import flash.events.*;

import fl.transitions.easing.*;
import fl.transitions.Tween;

import flash.globalization.CurrencyFormatter;

public class ShopbeamWidget extends MovieClip {
  public function ShopbeamWidget() {
    brandName.alpha = 0;
    productName.alpha = 0;
    listPrice.alpha = 0;
    salePrice.alpha = 0;

    var SHOP_HERE_TWEEN_X:int = 180;
    var SHOP_HERE_INITIAL_X:int = hoverMovie.x;
    var bagActive:Sprite = hoverMovie.bagActive;
    var bagInactive:Sprite = hoverMovie.bagInactive;

    function tweenTo(object:DisplayObject, property:String, value:*, duration:int = 30, durationInSeconds:Boolean = false):Tween {
      return new Tween(object, property, Strong.easeOut, object[property], value, 30);
    }

    function tweenAlpha(object:DisplayObject, opacity:Number, duration:int = 30, durationInSeconds:Boolean = false):Tween {
      return tweenTo(object, 'alpha', opacity, duration, durationInSeconds);
    }

    function fadeIn(object:DisplayObject, duration:int = 30, durationInSeconds:Boolean = false):void {
      tweenAlpha(object, 1, duration, durationInSeconds)
    }

    function fadeOut(object:DisplayObject, duration:int = 30, durationInSeconds:Boolean = false):void {
      tweenAlpha(object, 0, duration, durationInSeconds)
    }

    hoverArea.addEventListener(MouseEvent.MOUSE_OVER, function(event:MouseEvent):void {
      fadeIn(listPrice);
      if (listPrice.text !== salePrice.text) {
        fadeIn(strikeThrough);
        fadeIn(salePrice);
      }

      fadeIn(brandName);
      fadeIn(productName);
      fadeIn(bagActive);
      fadeOut(bagInactive);
      tweenAlpha(backdrop, 0.6);
      tweenTo(hoverMovie, 'x', SHOP_HERE_TWEEN_X);
    });

    hoverArea.addEventListener(MouseEvent.MOUSE_OUT, function(event:MouseEvent):void {
      fadeOut(salePrice);
      fadeOut(listPrice);
      fadeOut(strikeThrough);

      fadeOut(brandName);
      fadeOut(productName);
      fadeOut(bagActive);
      fadeIn(bagInactive);
      fadeOut(backdrop);
      tweenTo(hoverMovie, 'x', SHOP_HERE_INITIAL_X);
    });

    function log():void {
      ExternalInterface.call('console.log', arguments.join(' '));
    }

    function logError():void {
      ExternalInterface.call('console.error', arguments.join(' '));
    }

    function executeJS(js):void {
      var wrapped = 'try {\n' + js + '\n}catch(err){console.error(err);console.error(err.stack);}';
      ExternalInterface.call('eval', wrapped);
    }

    Security.allowDomain('*');

    var widgetUuid:String = stage.loaderInfo.parameters.widgetUuid;
    var loader:Loader = new Loader();
    var widgetData:Object;

    ExternalInterface.addCallback('setWidgetData', function setWidgetData(data:String):void {
      widgetData = JSON.parse(data);
      brandName.text = widgetData.initialProduct.brandName;
      productName.text = widgetData.initialProduct.name;

      var dollarFormatter:CurrencyFormatter = new CurrencyFormatter('usd');
      listPrice.text = dollarFormatter.format((widgetData.initialVariant.listPrice / 100), true);
      //strikeThrough.width ...
      salePrice.text = dollarFormatter.format((widgetData.initialVariant.salePrice / 100), true);
    });

    stage.align = StageAlign.TOP_LEFT;
    stage.scaleMode = StageScaleMode.NO_SCALE;
    var button:Sprite = new Sprite();
    button.addChild(loader);

    //required for `.useHandCursor` to work
    hoverArea.buttonMode = true;
    hoverArea.useHandCursor = true;
    addChild(button);

    setChildIndex(button, 0);

    function loadingError(e:IOErrorEvent):void {
      logError('widget with id: ' + widgetUuid + ' failed to load image');
    }

    loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadingError);

    function doneLoad(e:Event):void {
      loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, doneLoad);
      loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, loadingError);
    }

    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, doneLoad);

    function loaderClickHandler(e:Event):void {
      log('widgetOpenLightbox' + widgetUuid);
      executeJS("Shopbeam.swfOpenLightbox('" + widgetUuid + "')");
    }

    hoverArea.addEventListener(MouseEvent.CLICK, loaderClickHandler);

    log('loading image: ' + stage.loaderInfo.parameters.imageUrl);
    loader.load(new URLRequest(stage.loaderInfo.parameters.imageUrl));
  }
}
}

apply webstorm code formatting

apply webstorm code formatting


package aerys.minko.type
{
	import flash.events.IEventDispatcher;
	import flash.events.MouseEvent;
	import flash.ui.Mouse;

	public final class MouseManager
	{
		private var _x					: Number			= 0.;
		private var _y					: Number			= 0.;
		private var _deltaX				: Number			= 0.;
		private var _deltaY				: Number			= 0.;
		private var _deltaDistance		: Number			= 0.;

		private var _leftButtonDown		: Boolean			= false;
		private var _middleButtonDown	: Boolean			= false;
		private var _rightButtonDown	: Boolean			= false;

		private var _mouseDown			: Signal			= new Signal("mouseDown");
		private var _mouseUp			: Signal			= new Signal("mouseUp");

		private var _cursors			: Vector.<String>	= new <String>[];

		public function get x() : Number
		{
			return _x;
		}

		public function get y() : Number
		{
			return _y;
		}

		public function get deltaX() : Number
		{
			return _deltaX;
		}

		public function get deltaY() : Number
		{
			return _deltaY;
		}

		public function get deltaDistance() : Number
		{
			return _deltaDistance;
		}

		public function get leftButtonDown() : Boolean
		{
			return _leftButtonDown;
		}

		public function get middleButtonDown() : Boolean
		{
			return _middleButtonDown;
		}

		public function get rightButtonDown() : Boolean
		{
			return _rightButtonDown;
		}

		public function get cursor() : String
		{
			return Mouse.cursor;
		}

		public function get mouseDown() : Signal
		{
			return _mouseDown;
		}

		public function get mouseUp() : Signal
		{
			return _mouseUp;
		}

		public function bind(dispatcher : IEventDispatcher) : void
		{
			dispatcher.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			dispatcher.addEventListener(MouseEvent.MOUSE_DOWN, mouseLeftDownHandler);
			dispatcher.addEventListener(MouseEvent.MOUSE_UP, mouseLeftUpHandler);

			if (MouseEvent.RIGHT_CLICK != null)
			{
				dispatcher.addEventListener(MouseEvent.RIGHT_MOUSE_DOWN, mouseRightDownHandler);
				dispatcher.addEventListener(MouseEvent.RIGHT_MOUSE_UP, mouseRightUpHandler);
			}

			if (MouseEvent.MIDDLE_CLICK != null)
			{
				dispatcher.addEventListener(MouseEvent.MIDDLE_MOUSE_DOWN, mouseMiddleDownHandler);
				dispatcher.addEventListener(MouseEvent.MIDDLE_MOUSE_UP, mouseMiddleUpHandler);
			}
		}

		public function unbind(dispatcher : IEventDispatcher) : void
		{
			dispatcher.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			dispatcher.removeEventListener(MouseEvent.MOUSE_DOWN, mouseLeftDownHandler);
			dispatcher.removeEventListener(MouseEvent.MOUSE_UP, mouseLeftUpHandler);

			if (MouseEvent.RIGHT_CLICK != null)
			{
				dispatcher.removeEventListener(MouseEvent.RIGHT_MOUSE_DOWN, mouseRightDownHandler);
				dispatcher.removeEventListener(MouseEvent.RIGHT_MOUSE_UP, mouseRightUpHandler);
			}

			if (MouseEvent.MIDDLE_CLICK != null)
			{
				dispatcher.removeEventListener(MouseEvent.MIDDLE_MOUSE_DOWN, mouseMiddleDownHandler);
				dispatcher.removeEventListener(MouseEvent.MIDDLE_MOUSE_UP, mouseMiddleUpHandler);
			}
		}

		private function mouseMoveHandler(event : MouseEvent) : void
		{
			var localX : Number = event.localX;
			var localY : Number = event.localY;

			_deltaX = localX - _x;
			_deltaY = localY - _y;
			_deltaDistance = Math.sqrt(_deltaX * deltaX + deltaY * deltaY);

			_x = event.localX;
			_y = event.localY;
		}

		private function mouseLeftDownHandler(event : MouseEvent) : void
		{
			_leftButtonDown = true;
			_mouseDown.execute();
		}

		private function mouseLeftUpHandler(event : MouseEvent) : void
		{
			_leftButtonDown = false;
			_mouseUp.execute();
		}

		private function mouseMiddleDownHandler(event : MouseEvent) : void
		{
			_rightButtonDown = true;
		}

		private function mouseMiddleUpHandler(event : MouseEvent) : void
		{
			_rightButtonDown = false;
		}

		private function mouseRightDownHandler(event : MouseEvent) : void
		{
			_rightButtonDown = true;
		}

		private function mouseRightUpHandler(event : MouseEvent) : void
		{
			_rightButtonDown = false;
		}

		public function pushCursor(cursor : String) : MouseManager
		{
			_cursors.push(Mouse.cursor);
			Mouse.cursor = cursor;

			return this;
		}

		public function popCursor() : MouseManager
		{
			Mouse.cursor = _cursors.pop();

			return this;
		}
	}
}

package aerys.minko.type
{
	import flash.events.IEventDispatcher;
	import flash.events.MouseEvent;
	import flash.ui.Mouse;

	public final class MouseManager
	{
		private var _x					: Number			= 0.;
		private var _y					: Number			= 0.;
		private var _deltaX				: Number			= 0.;
		private var _deltaY				: Number			= 0.;
		private var _deltaDistance		: Number			= 0.;

		private var _leftButtonDown		: Boolean			= false;
		private var _middleButtonDown	: Boolean			= false;
		private var _rightButtonDown	: Boolean			= false;

		private var _mouseDown			: Signal			= new Signal("mouseDown");
		private var _mouseUp			: Signal			= new Signal("mouseUp");

		private var _cursors			: Vector.<String>	= new <String>[];

		public function get x() : Number
		{
			return _x;
		}

		public function get y() : Number
		{
			return _y;
		}

		public function get deltaX() : Number
		{
			return _deltaX;
		}

		public function get deltaY() : Number
		{
			return _deltaY;
		}

		public function get deltaDistance() : Number
		{
			return _deltaDistance;
		}

		public function get leftButtonDown() : Boolean
		{
			return _leftButtonDown;
		}

		public function get middleButtonDown() : Boolean
		{
			return _middleButtonDown;
		}

		public function get rightButtonDown() : Boolean
		{
			return _rightButtonDown;
		}

		public function get cursor() : String
		{
			return Mouse.cursor;
		}

		public function get mouseDown() : Signal
		{
			return _mouseDown;
		}

		public function get mouseUp() : Signal
		{
			return _mouseUp;
		}

		public function bind(dispatcher : IEventDispatcher) : void
		{
			dispatcher.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			dispatcher.addEventListener(MouseEvent.MOUSE_DOWN, mouseLeftDownHandler);
			dispatcher.addEventListener(MouseEvent.MOUSE_UP, mouseLeftUpHandler);

			if (MouseEvent.RIGHT_CLICK != null)
			{
				dispatcher.addEventListener(MouseEvent.RIGHT_MOUSE_DOWN, mouseRightDownHandler);
				dispatcher.addEventListener(MouseEvent.RIGHT_MOUSE_UP, mouseRightUpHandler);
			}

			if (MouseEvent.MIDDLE_CLICK != null)
			{
				dispatcher.addEventListener(MouseEvent.MIDDLE_MOUSE_DOWN, mouseMiddleDownHandler);
				dispatcher.addEventListener(MouseEvent.MIDDLE_MOUSE_UP, mouseMiddleUpHandler);
			}
		}

		public function unbind(dispatcher : IEventDispatcher) : void
		{
			dispatcher.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			dispatcher.removeEventListener(MouseEvent.MOUSE_DOWN, mouseLeftDownHandler);
			dispatcher.removeEventListener(MouseEvent.MOUSE_UP, mouseLeftUpHandler);

			if (MouseEvent.RIGHT_CLICK != null)
			{
				dispatcher.removeEventListener(MouseEvent.RIGHT_MOUSE_DOWN, mouseRightDownHandler);
				dispatcher.removeEventListener(MouseEvent.RIGHT_MOUSE_UP, mouseRightUpHandler);
			}

			if (MouseEvent.MIDDLE_CLICK != null)
			{
				dispatcher.removeEventListener(MouseEvent.MIDDLE_MOUSE_DOWN, mouseMiddleDownHandler);
				dispatcher.removeEventListener(MouseEvent.MIDDLE_MOUSE_UP, mouseMiddleUpHandler);
			}
		}

		private function mouseMoveHandler(event : MouseEvent) : void
		{
			var localX : Number = event.localX;
			var localY : Number = event.localY;

			_deltaX = localX - _x;
			_deltaY = localY - _y;
			_deltaDistance = Math.sqrt(_deltaX * deltaX + deltaY * deltaY);

			_x = event.localX;
			_y = event.localY;
		}

		private function mouseLeftDownHandler(event : MouseEvent) : void
		{
			_leftButtonDown = true;
			_mouseDown.execute();
		}

		private function mouseLeftUpHandler(event : MouseEvent) : void
		{
			_leftButtonDown = false;
			_mouseUp.execute();
		}

		private function mouseMiddleDownHandler(event : MouseEvent) : void
		{
			_middleButtonDown = true;
		}

		private function mouseMiddleUpHandler(event : MouseEvent) : void
		{
			_middleButtonDown = false;
		}

		private function mouseRightDownHandler(event : MouseEvent) : void
		{
			_rightButtonDown = true;
		}

		private function mouseRightUpHandler(event : MouseEvent) : void
		{
			_rightButtonDown = false;
		}

		public function pushCursor(cursor : String) : MouseManager
		{
			_cursors.push(Mouse.cursor);
			Mouse.cursor = cursor;

			return this;
		}

		public function popCursor() : MouseManager
		{
			Mouse.cursor = _cursors.pop();

			return this;
		}
	}
}

Update src/aerys/minko/type/MouseManager.as

Fixed bug in middle mouse button handler.


package goplayer
{
  public class ConfigurationParser
  {
    public static const DEFAULT_API_URL : String
      = "http://staging.streamio.com/api"
    public static const DEFAULT_SKIN_URL : String = "goplayer-skin.swf"
    public static const DEFAULT_TRACKER_ID : String = "global"

    public static const VALID_PARAMETERS : Array = [
      "api", "tracker", "skin", "video", "bitrate",
      "enablertmp", "autoplay", "loop",
      "skin:showchrome", "skin:showtitle" ]

    private const result : Configuration = new Configuration

    private var parameters : Object
    private var originalParameterNames : Object

    public function ConfigurationParser
      (parameters : Object, originalParameterNames : Object)
    {
      this.parameters = parameters
      this.originalParameterNames = originalParameterNames
    }

    public function execute() : void
    {
      result.apiURL = getString("api", DEFAULT_API_URL)
      result.trackerID = getString("tracker", DEFAULT_TRACKER_ID)
      result.skinURL = getString("skin", DEFAULT_SKIN_URL)
      result.movieID = getString("video", null)
      result.bitratePolicy = getBitratePolicy("bitrate", BitratePolicy.BEST)
      result.enableRTMP = getBoolean("enablertmp", true)
      result.enableAutoplay = getBoolean("autoplay", false)
      result.enableLooping = getBoolean("loop", false)
      result.enableChrome = getBoolean("skin:showchrome", true)
      result.enableTitle = getBoolean("skin:showtitle", true)
    }

    public static function parse(parameters : Object) : Configuration
    {
      const normalizedParameters : Object = {}
      const originalParameterNames : Object = {}

      for (var name : String in parameters)
        if (VALID_PARAMETERS.indexOf(normalize(name)) == -1)
          reportUnknownParameter(name)
        else
          normalizedParameters[normalize(name)] = parameters[name],
            originalParameterNames[normalize(name)] = name

      const parser : ConfigurationParser = new ConfigurationParser
        (normalizedParameters, originalParameterNames)

      parser.execute()

      return parser.result
    }

    private static function normalize(name : String) : String
    { return name.toLowerCase().replace(/[^a-z:]/g, "") }

    private static function reportUnknownParameter(name : String) : void
    { debug("Error: Unknown parameter: " + name) }

    // -----------------------------------------------------

    private function getString(name : String, fallback : String) : String
    { return name in parameters ? parameters[name] : fallback }

    private function getBoolean
      (name : String, fallback : Boolean) : Boolean
    {
      if (name in parameters)
        return $getBoolean(name, parameters[name], fallback)
      else
        return fallback
    }

    private function $getBoolean
      (name : String, value : String, fallback : Boolean) : Boolean
    {
      try
        { return $$getBoolean(value) }
      catch (error : Error)
        {
          reportInvalidParameter(name, value, ["true", "false"])

          return fallback
        }

      throw new Error
    }

    private function $$getBoolean(value : String) : Boolean
    {
      if (value == "true")
        return true
      else if (value == "false")
        return false
      else
        throw new Error
    }

    // -----------------------------------------------------

    private function getBitratePolicy
      (name : String, fallback : BitratePolicy) : BitratePolicy
    {
      if (name in parameters)
        return $getBitratePolicy(name, parameters[name], fallback)
      else
        return fallback
    }

    private function $getBitratePolicy
      (name : String, value : String,
       fallback : BitratePolicy) : BitratePolicy
    {
      try
        { return $$getBitratePolicy(value) }
      catch (error : Error)
        {
          reportInvalidParameter(name, value, BITRATE_POLICY_VALUES)

          return fallback
        }

      throw new Error
    }

    private const BITRATE_POLICY_VALUES : Array =
      ["<number>kbps", "min", "max", "best"]

    private function $$getBitratePolicy(value : String) : BitratePolicy
    {
      if (value == "max")
        return BitratePolicy.MAX
      else if (value == "min")
        return BitratePolicy.MIN
      else if (value == "best")
        return BitratePolicy.BEST
      else if (Bitrate.parse(value))
        return BitratePolicy.specific(Bitrate.parse(value))
      else
        throw new Error
    }

    // -----------------------------------------------------

    private function reportInvalidParameter
      (name : String, value : String, validValues : Array) : void
    {
      debug("Error: Invalid parameter: " +
            "“" + originalParameterNames[name] + "=" + value + "”; " +
            getInvalidParameterHint(validValues) + ".")
    }

    private function getInvalidParameterHint(values : Array) : String
    { return $getInvalidParameterHint(getQuotedValues(values)) }

    private function $getInvalidParameterHint(values : Array) : String
    {
      return "please use " +
        "either " + values.slice(0, -1).join(", ") + " " +
        "or " + values[values.length - 1]
    }

    private function getQuotedValues(values : Array) : Array
    {
      var result : Array = []

      for each (var value : String in values)
        result.push("“" + value + "”")

      return result
    }
  }
}

package goplayer
{
  public class ConfigurationParser
  {
    public static const DEFAULT_STREAMIO_API_URL : String
      = "http://staging.streamio.com/api"
    public static const DEFAULT_SKIN_URL : String = "goplayer-skin.swf"
    public static const DEFAULT_TRACKER_ID : String = "global"

    public static const VALID_PARAMETERS : Array = [
      "streamio:api", "tracker", "skin", "video", "bitrate",
      "enablertmp", "autoplay", "loop",
      "skin:showchrome", "skin:showtitle" ]

    private const result : Configuration = new Configuration

    private var parameters : Object
    private var originalParameterNames : Object

    public function ConfigurationParser
      (parameters : Object, originalParameterNames : Object)
    {
      this.parameters = parameters
      this.originalParameterNames = originalParameterNames
    }

    public function execute() : void
    {
      result.apiURL = getString("streamio:api", DEFAULT_STREAMIO_API_URL)
      result.trackerID = getString("tracker", DEFAULT_TRACKER_ID)
      result.skinURL = getString("skin", DEFAULT_SKIN_URL)
      result.movieID = getString("video", null)
      result.bitratePolicy = getBitratePolicy("bitrate", BitratePolicy.BEST)
      result.enableRTMP = getBoolean("enablertmp", true)
      result.enableAutoplay = getBoolean("autoplay", false)
      result.enableLooping = getBoolean("loop", false)
      result.enableChrome = getBoolean("skin:showchrome", true)
      result.enableTitle = getBoolean("skin:showtitle", true)
    }

    public static function parse(parameters : Object) : Configuration
    {
      const normalizedParameters : Object = {}
      const originalParameterNames : Object = {}

      for (var name : String in parameters)
        if (VALID_PARAMETERS.indexOf(normalize(name)) == -1)
          reportUnknownParameter(name)
        else
          normalizedParameters[normalize(name)] = parameters[name],
            originalParameterNames[normalize(name)] = name

      const parser : ConfigurationParser = new ConfigurationParser
        (normalizedParameters, originalParameterNames)

      parser.execute()

      return parser.result
    }

    private static function normalize(name : String) : String
    { return name.toLowerCase().replace(/[^a-z:]/g, "") }

    private static function reportUnknownParameter(name : String) : void
    { debug("Error: Unknown parameter: " + name) }

    // -----------------------------------------------------

    private function getString(name : String, fallback : String) : String
    { return name in parameters ? parameters[name] : fallback }

    private function getBoolean
      (name : String, fallback : Boolean) : Boolean
    {
      if (name in parameters)
        return $getBoolean(name, parameters[name], fallback)
      else
        return fallback
    }

    private function $getBoolean
      (name : String, value : String, fallback : Boolean) : Boolean
    {
      try
        { return $$getBoolean(value) }
      catch (error : Error)
        {
          reportInvalidParameter(name, value, ["true", "false"])

          return fallback
        }

      throw new Error
    }

    private function $$getBoolean(value : String) : Boolean
    {
      if (value == "true")
        return true
      else if (value == "false")
        return false
      else
        throw new Error
    }

    // -----------------------------------------------------

    private function getBitratePolicy
      (name : String, fallback : BitratePolicy) : BitratePolicy
    {
      if (name in parameters)
        return $getBitratePolicy(name, parameters[name], fallback)
      else
        return fallback
    }

    private function $getBitratePolicy
      (name : String, value : String,
       fallback : BitratePolicy) : BitratePolicy
    {
      try
        { return $$getBitratePolicy(value) }
      catch (error : Error)
        {
          reportInvalidParameter(name, value, BITRATE_POLICY_VALUES)

          return fallback
        }

      throw new Error
    }

    private const BITRATE_POLICY_VALUES : Array =
      ["<number>kbps", "min", "max", "best"]

    private function $$getBitratePolicy(value : String) : BitratePolicy
    {
      if (value == "max")
        return BitratePolicy.MAX
      else if (value == "min")
        return BitratePolicy.MIN
      else if (value == "best")
        return BitratePolicy.BEST
      else if (Bitrate.parse(value))
        return BitratePolicy.specific(Bitrate.parse(value))
      else
        throw new Error
    }

    // -----------------------------------------------------

    private function reportInvalidParameter
      (name : String, value : String, validValues : Array) : void
    {
      debug("Error: Invalid parameter: " +
            "“" + originalParameterNames[name] + "=" + value + "”; " +
            getInvalidParameterHint(validValues) + ".")
    }

    private function getInvalidParameterHint(values : Array) : String
    { return $getInvalidParameterHint(getQuotedValues(values)) }

    private function $getInvalidParameterHint(values : Array) : String
    {
      return "please use " +
        "either " + values.slice(0, -1).join(", ") + " " +
        "or " + values[values.length - 1]
    }

    private function getQuotedValues(values : Array) : Array
    {
      var result : Array = []

      for each (var value : String in values)
        result.push("“" + value + "”")

      return result
    }
  }
}

Rename `api' parameter to `streamio:api'.


package
{
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.net.Socket;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.events.SecurityErrorEvent;
    import flash.utils.ByteArray;
    import flash.utils.setTimeout;

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

        // Milliseconds.
        private const FACILITATOR_POLL_INTERVAL:int = 1000;

        // Socket to facilitator.
        private var s_f:Socket;

        private var output_text:TextField;

        private var fac_addr:Object;

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

        public function swfcat()
        {
            output_text = new TextField();
            output_text.width = 400;
            output_text.height = 300;
            output_text.background = true;
            output_text.backgroundColor = 0x001f0f;
            output_text.textColor = 0x44CC44;
            addChild(output_text);

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

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

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

            main();
        }

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

            s_f.addEventListener(Event.CONNECT, fac_connected);
            s_f.addEventListener(Event.CLOSE, function (e:Event):void {
                puts("Facilitator: closed connection.");
            });
            s_f.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Facilitator: I/O error: " + e.text + ".");
            });
            s_f.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Facilitator: security error: " + e.text + ".");
            });

            puts("Facilitator: connecting to " + fac_addr.host + ":" + fac_addr.port + ".");
            s_f.connect(fac_addr.host, fac_addr.port);
        }

        private function fac_connected(e:Event):void
        {
            puts("Facilitator: connected.");

            s_f.addEventListener(ProgressEvent.SOCKET_DATA, fac_data);

            s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
        }

        private function fac_data(e:ProgressEvent):void
        {
            var client_spec:String;
            var client_addr:Object;
            var proxy_pair:Object;

            client_spec = s_f.readMultiByte(e.bytesLoaded, "utf-8");
            puts("Facilitator: got \"" + client_spec + "\"");

            client_addr = parse_addr_spec(client_spec);
            if (!client_addr) {
                puts("Error: Client spec must be in the form \"host:port\".");
                setTimeout(main, FACILITATOR_POLL_INTERVAL);
                return;
            }
            if (client_addr.host == "0.0.0.0" && client_addr.port == 0) {
                puts("Error: Facilitator has no clients.");
                setTimeout(main, FACILITATOR_POLL_INTERVAL);
                return;
            }

            proxy_pair = new ProxyPair(this, client_addr, DEFAULT_TOR_ADDR);
            proxy_pair.connect();

            setTimeout(main, FACILITATOR_POLL_INTERVAL);
        }

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

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

            return addr;
        }
    }
}

import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.Socket;
import flash.utils.ByteArray;

/* An instance of a client-relay connection. */
class ProxyPair
{
    // Address ({host, port}) of client.
    private var addr_c:Object;
    // Address ({host, port}) of relay.
    private var addr_r:Object;

    // Socket to client.
    private var s_c:Socket;
    // Socket to relay.
    private var s_r:Socket;

    // Parent swfcat, for UI updates.
    private var ui:swfcat;

    private function log(msg:String):void
    {
        ui.puts(id() + ": " + msg)
    }

    // String describing this pair for output.
    private function id():String
    {
        return "<" + this.addr_c.host + ":" + this.addr_c.port +
            "," + this.addr_r.host + ":" + this.addr_r.port + ">";
    }

    public function ProxyPair(ui:swfcat, addr_c:Object, addr_r:Object)
    {
        this.ui = ui;
        this.addr_c = addr_c;
        this.addr_r = addr_r;
    }

    public function connect():void
    {
        s_r = new Socket();

        s_r.addEventListener(Event.CONNECT, tor_connected);
        s_r.addEventListener(Event.CLOSE, function (e:Event):void {
            log("Tor: closed.");
            if (s_c.connected)
                s_c.close();
        });
        s_r.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
            log("Tor: I/O error: " + e.text + ".");
            if (s_c.connected)
                s_c.close();
        });
        s_r.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
            log("Tor: security error: " + e.text + ".");
            if (s_c.connected)
                s_c.close();
        });

        log("Tor: connecting to " + addr_r.host + ":" + addr_r.port + ".");
        s_r.connect(addr_r.host, addr_r.port);
    }

    private function tor_connected(e:Event):void
    {
        log("Tor: connected.");

        s_c = new Socket();

        s_c.addEventListener(Event.CONNECT, client_connected);
        s_c.addEventListener(Event.CLOSE, function (e:Event):void {
            log("Client: closed.");
            if (s_r.connected)
                s_r.close();
        });
        s_c.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
            log("Client: I/O error: " + e.text + ".");
            if (s_r.connected)
                s_r.close();
        });
        s_c.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
            log("Client: security error: " + e.text + ".");
            if (s_r.connected)
                s_r.close();
        });

        log("Client: connecting to " + addr_c.host + ":" + addr_c.port + ".");
        s_c.connect(addr_c.host, addr_c.port);
    }

    private function client_connected(e:Event):void
    {
        log("Client: connected.");

        s_r.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
            var bytes:ByteArray = new ByteArray();
            s_r.readBytes(bytes, 0, e.bytesLoaded);
            log("Tor: read " + bytes.length + ".");
            s_c.writeBytes(bytes);
        });
        s_c.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
            var bytes:ByteArray = new ByteArray();
            s_c.readBytes(bytes, 0, e.bytesLoaded);
            log("Client: read " + bytes.length + ".");
            s_r.writeBytes(bytes);
        });
    }
}

package
{
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.net.Socket;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.events.SecurityErrorEvent;
    import flash.utils.ByteArray;
    import flash.utils.setTimeout;

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

        // Milliseconds.
        private const FACILITATOR_POLL_INTERVAL:int = 1000;

        // Socket to facilitator.
        private var s_f:Socket;

        private var output_text:TextField;

        private var fac_addr:Object;

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

        public function swfcat()
        {
            output_text = new TextField();
            output_text.width = 400;
            output_text.height = 300;
            output_text.background = true;
            output_text.backgroundColor = 0x001f0f;
            output_text.textColor = 0x44CC44;
            addChild(output_text);

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

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

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

            main();
        }

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

            s_f.addEventListener(Event.CONNECT, fac_connected);
            s_f.addEventListener(Event.CLOSE, function (e:Event):void {
                puts("Facilitator: closed connection.");
                setTimeout(main, FACILITATOR_POLL_INTERVAL);
            });
            s_f.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
                puts("Facilitator: I/O error: " + e.text + ".");
            });
            s_f.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
                puts("Facilitator: security error: " + e.text + ".");
            });

            puts("Facilitator: connecting to " + fac_addr.host + ":" + fac_addr.port + ".");
            s_f.connect(fac_addr.host, fac_addr.port);
        }

        private function fac_connected(e:Event):void
        {
            puts("Facilitator: connected.");

            s_f.addEventListener(ProgressEvent.SOCKET_DATA, fac_data);

            s_f.writeUTFBytes("GET / HTTP/1.0\r\n\r\n");
        }

        private function fac_data(e:ProgressEvent):void
        {
            var client_spec:String;
            var client_addr:Object;
            var proxy_pair:Object;

            client_spec = s_f.readMultiByte(e.bytesLoaded, "utf-8");
            puts("Facilitator: got \"" + client_spec + "\"");

            client_addr = parse_addr_spec(client_spec);
            if (!client_addr) {
                puts("Error: Client spec must be in the form \"host:port\".");
                return;
            }
            if (client_addr.host == "0.0.0.0" && client_addr.port == 0) {
                puts("Error: Facilitator has no clients.");
                return;
            }

            proxy_pair = new ProxyPair(this, client_addr, DEFAULT_TOR_ADDR);
            proxy_pair.connect();
        }

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

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

            return addr;
        }
    }
}

import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.Socket;
import flash.utils.ByteArray;

/* An instance of a client-relay connection. */
class ProxyPair
{
    // Address ({host, port}) of client.
    private var addr_c:Object;
    // Address ({host, port}) of relay.
    private var addr_r:Object;

    // Socket to client.
    private var s_c:Socket;
    // Socket to relay.
    private var s_r:Socket;

    // Parent swfcat, for UI updates.
    private var ui:swfcat;

    private function log(msg:String):void
    {
        ui.puts(id() + ": " + msg)
    }

    // String describing this pair for output.
    private function id():String
    {
        return "<" + this.addr_c.host + ":" + this.addr_c.port +
            "," + this.addr_r.host + ":" + this.addr_r.port + ">";
    }

    public function ProxyPair(ui:swfcat, addr_c:Object, addr_r:Object)
    {
        this.ui = ui;
        this.addr_c = addr_c;
        this.addr_r = addr_r;
    }

    public function connect():void
    {
        s_r = new Socket();

        s_r.addEventListener(Event.CONNECT, tor_connected);
        s_r.addEventListener(Event.CLOSE, function (e:Event):void {
            log("Tor: closed.");
            if (s_c.connected)
                s_c.close();
        });
        s_r.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
            log("Tor: I/O error: " + e.text + ".");
            if (s_c.connected)
                s_c.close();
        });
        s_r.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
            log("Tor: security error: " + e.text + ".");
            if (s_c.connected)
                s_c.close();
        });

        log("Tor: connecting to " + addr_r.host + ":" + addr_r.port + ".");
        s_r.connect(addr_r.host, addr_r.port);
    }

    private function tor_connected(e:Event):void
    {
        log("Tor: connected.");

        s_c = new Socket();

        s_c.addEventListener(Event.CONNECT, client_connected);
        s_c.addEventListener(Event.CLOSE, function (e:Event):void {
            log("Client: closed.");
            if (s_r.connected)
                s_r.close();
        });
        s_c.addEventListener(IOErrorEvent.IO_ERROR, function (e:IOErrorEvent):void {
            log("Client: I/O error: " + e.text + ".");
            if (s_r.connected)
                s_r.close();
        });
        s_c.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function (e:SecurityErrorEvent):void {
            log("Client: security error: " + e.text + ".");
            if (s_r.connected)
                s_r.close();
        });

        log("Client: connecting to " + addr_c.host + ":" + addr_c.port + ".");
        s_c.connect(addr_c.host, addr_c.port);
    }

    private function client_connected(e:Event):void
    {
        log("Client: connected.");

        s_r.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
            var bytes:ByteArray = new ByteArray();
            s_r.readBytes(bytes, 0, e.bytesLoaded);
            log("Tor: read " + bytes.length + ".");
            s_c.writeBytes(bytes);
        });
        s_c.addEventListener(ProgressEvent.SOCKET_DATA, function (e:ProgressEvent):void {
            var bytes:ByteArray = new ByteArray();
            s_c.readBytes(bytes, 0, e.bytesLoaded);
            log("Client: read " + bytes.length + ".");
            s_r.writeBytes(bytes);
        });
    }
}

Reschedule a facilitator connection upon close, not upon data read.


/*
 *  Copyright: (c) 2015. Turtsevich Alexander
 *
 *  Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.html
 */

package com.kemsky.support
{
    /**
     * Stream error class
     */
    public class StreamError extends Error
    {
        /**
         * @inheritDoc
         */
        public function StreamError(message:String = null, errorID:int = 0)
        {
            super(message, errorID);
        }
    }
}

/*
 *  Copyright: (c) 2015. Turtsevich Alexander
 *
 *  Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.html
 */

package com.kemsky.support
{
    /**
     * Stream error class
     */
    public class StreamError extends Error
    {
        /**
         * Constructor.
         * @param message error description.
         * @param errorID error number.
         */
        public function StreamError(message:String = null, errorID:int = 0)
        {
            super(message, errorID);
        }
    }
}

clean up

clean up


/* ***** BEGIN LICENSE BLOCK *****
 *
 * This file is part of Weave.
 *
 * The Initial Developer of Weave is the Institute for Visualization
 * and Perception Research at the University of Massachusetts Lowell.
 * Portions created by the Initial Developer are Copyright (C) 2008-2015
 * the Initial Developer. All Rights Reserved.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * ***** END LICENSE BLOCK ***** */

package weave.menus
{
	import weave.Weave;
	import weave.compiler.Compiler;
	import weave.core.LinkableCallbackScript;
	import weave.core.LinkableFunction;
	import weave.visualization.tools.ExternalTool;

	public class ExportMenu extends WeaveMenuItem
	{
		public function ExportMenu()
		{
			super({
				shown: function():Boolean { return shown; },
				label: lang("Weave 2.0"),
				children: [
					{
						label: lang("Export to HTML5"),
						click: export
					},
					{
						enabled: function():Boolean { return exported; },
						label: lang("Copy layout from HTML5"),
						click: function():void {
							JavaScript.exec(
								jsVars(false),
								'var obj = window[WEAVE_EXTERNAL_TOOLS][windowName];',
								'this.path("Layout").request("FlexibleLayout").state(obj.window.weave.path("Layout").getState())'
							);
						}
					}
				]
			});
		}

		private static const windowName:String = ExternalTool.generateWindowName();

		public static function get shown():Boolean
		{
			return Weave.properties.version.value == 'Custom';
		}

		private static function jsVars(catchErrors:Boolean):Object
		{
			return {
				WEAVE_EXTERNAL_TOOLS: ExternalTool.WEAVE_EXTERNAL_TOOLS,
				'windowName': windowName,
				'catch': catchErrors && function():*{}
			};
		}

		public static function get exported():Boolean
		{
			return JavaScript.exec(
				jsVars(true),
				'var obj = window[WEAVE_EXTERNAL_TOOLS][windowName];',
				'return !!obj.window.weave;'
			);
		}

		public static var url:String = "/weave-html5/";

		public static function export():void
		{
			ExternalTool.launch(WeaveAPI.globalHashMap, url, windowName);
		}

		public static function disableScripts(exportUrl:String = null):void
		{
			LinkableFunction.enabled = false;
			LinkableCallbackScript.enabled = false;

			if (exportUrl)
				ExportMenu.url = exportUrl;
			else
				exportUrl = ExportMenu.url;

			var names:Array = WeaveAPI.globalHashMap.getNames();
			var lcs:LinkableCallbackScript = WeaveAPI.globalHashMap.requestObject("_disableFlashScripts", LinkableCallbackScript, false);
			//  put new script first
			WeaveAPI.globalHashMap.setNameOrder(names);
			lcs.groupedCallback.value = false;
			lcs.script.value = "if (typeof ExportMenu != 'undefined') {\n" +
				"\tExportMenu.disableScripts(" + Compiler.stringify(exportUrl) + ");\n" +
				"\tExportMenu.export();\n" +
				"\tSessionStateEditor.openDefaultEditor();\n" +
				"}";
		}

		/*
		public static function flush():void
		{
			if (!exported)
			{
				export();
				return;
			}
			JavaScript.exec(
				jsVars(false),
				<![CDATA[
					var obj = window[WEAVE_EXTERNAL_TOOLS][windowName];
					var content = atob(obj.path.getValue('btoa(Weave.createWeaveFileContent())'));
					obj.window.weavejs.core.WeaveArchive.loadFileContent(obj.window.weave, content);
				]]>
			);
		}
		*/
	}
}

/* ***** BEGIN LICENSE BLOCK *****
 *
 * This file is part of Weave.
 *
 * The Initial Developer of Weave is the Institute for Visualization
 * and Perception Research at the University of Massachusetts Lowell.
 * Portions created by the Initial Developer are Copyright (C) 2008-2015
 * the Initial Developer. All Rights Reserved.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * ***** END LICENSE BLOCK ***** */

package weave.menus
{
	import weave.Weave;
	import weave.compiler.Compiler;
	import weave.core.LinkableCallbackScript;
	import weave.core.LinkableFunction;
	import weave.visualization.tools.ExternalTool;

	public class ExportMenu extends WeaveMenuItem
	{
		public function ExportMenu()
		{
			super({
				shown: function():Boolean { return ExportMenu.shown; },
				label: lang("Weave 2.0"),
				children: [
					{
						label: lang("Export to HTML5"),
						click: export
					},
					{
						enabled: function():Boolean { return exported; },
						label: lang("Copy layout from HTML5"),
						click: function():void {
							JavaScript.exec(
								jsVars(false),
								'var obj = window[WEAVE_EXTERNAL_TOOLS][windowName];',
								'this.path("Layout").request("FlexibleLayout").state(obj.window.weave.path("Layout").getState())'
							);
						}
					}
				]
			});
		}

		private static const windowName:String = ExternalTool.generateWindowName();

		public static function get shown():Boolean
		{
			return Weave.properties.version.value == 'Custom';
		}

		private static function jsVars(catchErrors:Boolean):Object
		{
			return {
				WEAVE_EXTERNAL_TOOLS: ExternalTool.WEAVE_EXTERNAL_TOOLS,
				'windowName': windowName,
				'catch': catchErrors && function():*{}
			};
		}

		public static function get exported():Boolean
		{
			return JavaScript.exec(
				jsVars(true),
				'var obj = window[WEAVE_EXTERNAL_TOOLS][windowName];',
				'return !!obj.window.weave;'
			);
		}

		public static var url:String = "/weave-html5/";

		public static function export():void
		{
			ExternalTool.launch(WeaveAPI.globalHashMap, url, windowName);
		}

		public static function disableScripts(exportUrl:String = null):void
		{
			LinkableFunction.enabled = false;
			LinkableCallbackScript.enabled = false;

			if (exportUrl)
				ExportMenu.url = exportUrl;
			else
				exportUrl = ExportMenu.url;

			var names:Array = WeaveAPI.globalHashMap.getNames();
			var lcs:LinkableCallbackScript = WeaveAPI.globalHashMap.requestObject("_disableFlashScripts", LinkableCallbackScript, false);
			//  put new script first
			WeaveAPI.globalHashMap.setNameOrder(names);
			lcs.groupedCallback.value = false;
			lcs.script.value = "if (typeof ExportMenu != 'undefined') {\n" +
				"\tExportMenu.disableScripts(" + Compiler.stringify(exportUrl) + ");\n" +
				"\tExportMenu.export();\n" +
				"\tSessionStateEditor.openDefaultEditor();\n" +
				"}";
		}

		/*
		public static function flush():void
		{
			if (!exported)
			{
				export();
				return;
			}
			JavaScript.exec(
				jsVars(false),
				<![CDATA[
					var obj = window[WEAVE_EXTERNAL_TOOLS][windowName];
					var content = atob(obj.path.getValue('btoa(Weave.createWeaveFileContent())'));
					obj.window.weavejs.core.WeaveArchive.loadFileContent(obj.window.weave, content);
				]]>
			);
		}
		*/
	}
}

fix for ExportMenu shown property.

fix for ExportMenu shown property.


package org.mangui.HLS.parsing {

    import flash.events.*;
    import flash.net.*;
    import org.mangui.HLS.utils.*;

    /** Helpers for parsing M3U8 files. **/
    public class Manifest {

        /** Starttag for a fragment. **/
        public static const FRAGMENT:String = '#EXTINF:';
        /** Header tag that must be at the first line. **/
        public static const HEADER:String = '#EXTM3U';
        /** Starttag for a level. **/
        public static const LEVEL:String = '#EXT-X-STREAM-INF:';
        /** Tag that delimits the end of a playlist. **/
        public static const ENDLIST:String = '#EXT-X-ENDLIST';
        /** Tag that provides the sequence number. **/
        private static const SEQNUM:String = '#EXT-X-MEDIA-SEQUENCE:';
        /** Tag that provides the target duration for each segment. **/
        private static const TARGETDURATION:String = '#EXT-X-TARGETDURATION:';
        /** Tag that indicates discontinuity in the stream */
        private static const DISCONTINUITY:String = '#EXT-X-DISCONTINUITY';
        /** Tag that provides date/time information */
        private static const PROGRAMDATETIME:String = '#EXT-X-PROGRAM-DATE-TIME';

        /** Index in the array with levels. **/
        private var _index:Number;
        /** URLLoader instance. **/
        private var _urlloader:URLLoader;
        /** Function to callback loading to. **/
        private var _success:Function;
        /** URL of an M3U8 playlist. **/
        private var _url:String;

        /** Load a playlist M3U8 file. **/
        public function loadPlaylist(url:String,success:Function,error:Function,index:Number):void {
            _url = url;
            _success = success;
            _index = index;
            _urlloader = new URLLoader();
            _urlloader.addEventListener(Event.COMPLETE,_loaderHandler);
            _urlloader.addEventListener(IOErrorEvent.IO_ERROR,error);
            _urlloader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,error);
            _urlloader.load(new URLRequest(url));
        };

        /** The M3U8 playlist was loaded. **/
        private function _loaderHandler(event:Event):void {
            _success(String(event.target.data),_url,_index);
        };

        /** Extract fragments from playlist data. **/
        public static function getFragments(data:String,base:String=''):Array {
            var fragments:Array = [];
            var lines:Array = data.split("\n");
            //fragment seqnum
            var seqnum:Number = 0;
            // fragment start time (in sec)
            var start_time:Number = 0;
            var program_date:Number=0;
            // fragment continuity index incremented at each discontinuity
            var continuity_index:Number = 0;
            var i:Number = 0;

            // first look for sequence number
            while (i < lines.length) {
                if(lines[i].indexOf(Manifest.SEQNUM) == 0) {
                    seqnum = Number(lines[i].substr(Manifest.SEQNUM.length));
                    break;
                 }
                 i++;
               }
            i = 0;
            while (i < lines.length) {
              if(lines[i].indexOf(Manifest.PROGRAMDATETIME) == 0) {
                //Log.txt(lines[i]);
                var year:Number    = lines[i].substr(25,4);
                var month:Number   = lines[i].substr(30,2);
                var day:Number     = lines[i].substr(33,2);
                var hour:Number    = lines[i].substr(36,2);
                var minutes:Number = lines[i].substr(39,2);
                var seconds:Number = lines[i].substr(42,2);
                program_date = new Date(year,month,day,hour,minutes,seconds).getTime();
              } else if(lines[i].indexOf(Manifest.FRAGMENT) == 0) {
                var comma_position:Number = lines[i].indexOf(',');
                var duration:Number = (comma_position == -1) ? lines[i].substr(Manifest.FRAGMENT.length) : lines[i].substr(Manifest.FRAGMENT.length,comma_position-Manifest.FRAGMENT.length);
                // Look for next non-blank line, for url
                i++;
                while(lines[i].match(/^\s*$/)) {
                  i++;
                }
                var url:String = Manifest._extractURL(lines[i],base);
                fragments.push(new Fragment(url,duration,seqnum++,start_time,continuity_index,program_date));
                start_time+=duration;
                program_date = 0;
              } else if(lines[i].indexOf(Manifest.DISCONTINUITY) == 0) {
                continuity_index++;
                Log.txt("discontinuity found at seqnum " + seqnum);
              }
              i++;
            }
            if(fragments.length == 0) {
                //throw new Error("No TS fragments found in " + base);
                Log.txt("No TS fragments found in " + base);
            }
            return fragments;
        };

        /** Extract levels from manifest data. **/
        public static function extractLevels(data:String,base:String=''):Array {
            var levels:Array = [];
            var lines:Array = data.split("\n");
            var i:Number = 0;
            while (i<lines.length) {
                if(lines[i].indexOf(Manifest.LEVEL) == 0) {
                    var level:Level = new Level();
                    var params:Array = lines[i].substr(Manifest.LEVEL.length).split(',');
                    for(var j:Number = 0; j<params.length; j++) {
                        if(params[j].indexOf('BANDWIDTH') > -1) {
                            level.bitrate = params[j].split('=')[1];
                            if(level.bitrate < 150000) {
                                level.audio = true;
                            }
                        } else if (params[j].indexOf('RESOLUTION') > -1) {
                            level.height  = params[j].split('=')[1].split('x')[1];
                            level.width = params[j].split('=')[1].split('x')[0];
                        } else if (params[j].indexOf('CODECS') > -1 && lines[i].indexOf('avc1') == -1) {
                            level.audio = true;
                        }
                    }
					// Look for next non-blank line, for url
                    i++;
					while(lines[i].match(/^\s*$/)) {
						i++;
					}
                    level.url = Manifest._extractURL(lines[i],base);
                    levels.push(level);
                }
                i++;
            }
            if(levels.length == 0) {
                throw new Error("No playlists found in Manifest: " + base);
            }
            levels.start_seqnum = -1;
            levels.end_seqnum = -1;
            levels.sortOn('bitrate',Array.NUMERIC);
            return levels;
        };

        /** Extract whether the stream is live or ondemand. **/
        public static function hasEndlist(data:String):Boolean {
            if(data.indexOf(Manifest.ENDLIST) > 0) {
                return true;
            } else {
                return false;
            }
        };

        public static function getTargetDuration(data:String):Number {
            var lines:Array = data.split("\n");
            var i:Number = 0;
            var targetduration:Number = 0;

            // first look for target duration
            while (i < lines.length) {
                if(lines[i].indexOf(Manifest.TARGETDURATION) == 0) {
                    targetduration = Number(lines[i].substr(Manifest.TARGETDURATION.length));
                    break;
                 }
                 i++;
            }
            return targetduration;
       }

        /** Extract URL (check if absolute or not). **/
        private static function _extractURL(path:String,base:String):String {
         var _prefix:String = null;
         var _suffix:String = null;
          if(path.substr(0,7) == 'http://' || path.substr(0,8) == 'https://') {
            return path;
          } else {
            // Remove querystring
            if(base.indexOf('?') > -1) {
              base = base.substr(0,base.indexOf('?'));
            }
            // domain-absolute
            if(path.substr(0,1) == '/') {
              // base = http[s]://domain/subdomain:1234/otherstuff
              // prefix = http[s]://
              // suffix = domain/subdomain:1234/otherstuff
              _prefix=base.substr(0,base.indexOf("//")+2);
              _suffix=base.substr(base.indexOf("//")+2);
              // return http[s]://domain/subdomain:1234/path
              return _prefix+_suffix.substr(0,_suffix.indexOf("/"))+path;
            } else {
              return base.substr(0,base.lastIndexOf('/') + 1) + path;
            }
          }
        };

    }

}

package org.mangui.HLS.parsing {

    import flash.events.*;
    import flash.net.*;
    import org.mangui.HLS.utils.*;

    /** Helpers for parsing M3U8 files. **/
    public class Manifest {

        /** Starttag for a fragment. **/
        public static const FRAGMENT:String = '#EXTINF:';
        /** Header tag that must be at the first line. **/
        public static const HEADER:String = '#EXTM3U';
        /** Starttag for a level. **/
        public static const LEVEL:String = '#EXT-X-STREAM-INF:';
        /** Tag that delimits the end of a playlist. **/
        public static const ENDLIST:String = '#EXT-X-ENDLIST';
        /** Tag that provides the sequence number. **/
        private static const SEQNUM:String = '#EXT-X-MEDIA-SEQUENCE:';
        /** Tag that provides the target duration for each segment. **/
        private static const TARGETDURATION:String = '#EXT-X-TARGETDURATION:';
        /** Tag that indicates discontinuity in the stream */
        private static const DISCONTINUITY:String = '#EXT-X-DISCONTINUITY';
        /** Tag that provides date/time information */
        private static const PROGRAMDATETIME:String = '#EXT-X-PROGRAM-DATE-TIME';

        /** Index in the array with levels. **/
        private var _index:Number;
        /** URLLoader instance. **/
        private var _urlloader:URLLoader;
        /** Function to callback loading to. **/
        private var _success:Function;
        /** URL of an M3U8 playlist. **/
        private var _url:String;

        /** Load a playlist M3U8 file. **/
        public function loadPlaylist(url:String,success:Function,error:Function,index:Number):void {
            _url = url;
            _success = success;
            _index = index;
            _urlloader = new URLLoader();
            _urlloader.addEventListener(Event.COMPLETE,_loaderHandler);
            _urlloader.addEventListener(IOErrorEvent.IO_ERROR,error);
            _urlloader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,error);
            _urlloader.load(new URLRequest(url));
        };

        /** The M3U8 playlist was loaded. **/
        private function _loaderHandler(event:Event):void {
            _success(String(event.target.data),_url,_index);
        };

        /** Extract fragments from playlist data. **/
        public static function getFragments(data:String,base:String=''):Array {
            var fragments:Array = [];
            var lines:Array = data.split("\n");
            //fragment seqnum
            var seqnum:Number = 0;
            // fragment start time (in sec)
            var start_time:Number = 0;
            var program_date:Number=0;
            // fragment continuity index incremented at each discontinuity
            var continuity_index:Number = 0;
            var i:Number = 0;

            // first look for sequence number
            while (i < lines.length) {
                if(lines[i].indexOf(Manifest.SEQNUM) == 0) {
                    seqnum = Number(lines[i].substr(Manifest.SEQNUM.length));
                    break;
                 }
                 i++;
               }
            i = 0;
            while (i < lines.length) {
              if(lines[i].indexOf(Manifest.PROGRAMDATETIME) == 0) {
                //Log.txt(lines[i]);
                var year:Number    = lines[i].substr(25,4);
                var month:Number   = lines[i].substr(30,2);
                var day:Number     = lines[i].substr(33,2);
                var hour:Number    = lines[i].substr(36,2);
                var minutes:Number = lines[i].substr(39,2);
                var seconds:Number = lines[i].substr(42,2);
                program_date = new Date(year,month,day,hour,minutes,seconds).getTime();
              } else if(lines[i].indexOf(Manifest.FRAGMENT) == 0) {
                var comma_position:Number = lines[i].indexOf(',');
                var duration:Number = (comma_position == -1) ? lines[i].substr(Manifest.FRAGMENT.length) : lines[i].substr(Manifest.FRAGMENT.length,comma_position-Manifest.FRAGMENT.length);
                // Look for next non-blank line, for url
                i++;
                while(lines[i].match(/^\s*$/)) {
                  i++;
                }
                var url:String = Manifest._extractURL(lines[i],base);
                fragments.push(new Fragment(url,duration,seqnum++,start_time,continuity_index,program_date));
                start_time+=duration;
                program_date = 0;
              } else if(lines[i].indexOf(Manifest.DISCONTINUITY) == 0) {
                continuity_index++;
                Log.txt("discontinuity found at seqnum " + seqnum);
              }
              i++;
            }
            if(fragments.length == 0) {
                //throw new Error("No TS fragments found in " + base);
                Log.txt("No TS fragments found in " + base);
            }
            return fragments;
        };

        /** Extract levels from manifest data. **/
        public static function extractLevels(data:String,base:String=''):Array {
            var levels:Array = [];
            var lines:Array = data.split("\n");
            var i:Number = 0;
            while (i<lines.length) {
                if(lines[i].indexOf(Manifest.LEVEL) == 0) {
                    var level:Level = new Level();
                    var params:Array = lines[i].substr(Manifest.LEVEL.length).split(',');
                    for(var j:Number = 0; j<params.length; j++) {
                        if(params[j].indexOf('BANDWIDTH') > -1) {
                            level.bitrate = params[j].split('=')[1];
                        } else if (params[j].indexOf('RESOLUTION') > -1) {
                            level.height  = params[j].split('=')[1].split('x')[1];
                            level.width = params[j].split('=')[1].split('x')[0];
                        } else if (params[j].indexOf('CODECS') > -1 && lines[i].indexOf('avc1') == -1) {
                            level.audio = true;
                        }
                    }
					// Look for next non-blank line, for url
                    i++;
					while(lines[i].match(/^\s*$/)) {
						i++;
					}
                    level.url = Manifest._extractURL(lines[i],base);
                    levels.push(level);
                }
                i++;
            }
            if(levels.length == 0) {
                throw new Error("No playlists found in Manifest: " + base);
            }
            levels.start_seqnum = -1;
            levels.end_seqnum = -1;
            levels.sortOn('bitrate',Array.NUMERIC);
            return levels;
        };

        /** Extract whether the stream is live or ondemand. **/
        public static function hasEndlist(data:String):Boolean {
            if(data.indexOf(Manifest.ENDLIST) > 0) {
                return true;
            } else {
                return false;
            }
        };

        public static function getTargetDuration(data:String):Number {
            var lines:Array = data.split("\n");
            var i:Number = 0;
            var targetduration:Number = 0;

            // first look for target duration
            while (i < lines.length) {
                if(lines[i].indexOf(Manifest.TARGETDURATION) == 0) {
                    targetduration = Number(lines[i].substr(Manifest.TARGETDURATION.length));
                    break;
                 }
                 i++;
            }
            return targetduration;
       }

        /** Extract URL (check if absolute or not). **/
        private static function _extractURL(path:String,base:String):String {
         var _prefix:String = null;
         var _suffix:String = null;
          if(path.substr(0,7) == 'http://' || path.substr(0,8) == 'https://') {
            return path;
          } else {
            // Remove querystring
            if(base.indexOf('?') > -1) {
              base = base.substr(0,base.indexOf('?'));
            }
            // domain-absolute
            if(path.substr(0,1) == '/') {
              // base = http[s]://domain/subdomain:1234/otherstuff
              // prefix = http[s]://
              // suffix = domain/subdomain:1234/otherstuff
              _prefix=base.substr(0,base.indexOf("//")+2);
              _suffix=base.substr(base.indexOf("//")+2);
              // return http[s]://domain/subdomain:1234/path
              return _prefix+_suffix.substr(0,_suffix.indexOf("/"))+path;
            } else {
              return base.substr(0,base.lastIndexOf('/') + 1) + path;
            }
          }
        };

    }

}

remove implicit rules that force playlist to be audio only


m4_pattern_allow([^URBI_(PATH|SERVER)$])         -*- shell-script -*-
URBI_INIT

# Avoid zombies and preserve debugging information.
cleanup ()
{
  exit_status=$?

  # We can be killed even before children are spawned.
  test -n "$children" ||
    exit $exit_status

  # In case we were caught by set -e, kill the children.
  children_kill
  children_harvest
  children_report

  children_sta=$(children_status remote)
  # Don't clean before calling children_status...
  test x$VERBOSE != x || children_clean

  case $exit_status:$children_sta in
    (0:0) ;;
    (0:*) # Maybe a children exited for SKIP etc.
	 exit $children_sta;;
    (*:*) # If the checker failed, there is a big problem.
	 error SOFTWARE "$0 itself failed with $exit_status";;
  esac
  # rst_expect sets exit=false if it saw a failure.
  $exit
}
trap cleanup 0

# Overriden to include the test name.
stderr ()
{
  echo >&2 "$(basename $0): $me: $@"
  echo >&2
}

# Sleep some time, but taking into account the fact that
# instrumentation slows down a lot.
my_sleep ()
{
  if $INSTRUMENT; then
    sleep $(($1 * 5))
  else
    sleep $1
  fi
}

## -------------- ##
## Main program.  ##
## -------------- ##

exec 3>&2

check_dir abs_builddir bin/liburbi-check

# Make it absolute.
chk=$(absolute "$1")
if test ! -f "$chk.cc"; then
  fatal "no such file: $chk.cc"
fi

# ./../../../tests/2.x/andexp-pipeexp.chk -> 2.x
medir=$(basename $(dirname "$chk"))
# ./../../../tests/2.x/andexp-pipeexp.chk -> 2.x/andexp-pipeexp
me=$medir/$(basename "$chk" ".cc")
# ./../../../tests/2.x/andexp-pipeexp.chk -> andexp-pipeexp
meraw=$(basename $me)    # MERAW!

srcdir=$(absolute $srcdir)
export srcdir
# Move to a private dir.
mkcd $me.dir

# Help debugging
set | rst_pre "$me variables"

# Leaves trailing files, so run it in subdir.
find_urbi_server

# Compute expected output.
sed -n -e 's,//= ,,p' $chk.cc >output.exp
touch error.exp
echo 0 >status.exp

# Start it.
spawn_urbi_server

# Start the test.
valgrind=$(instrument "remote.val")
cmd="$valgrind ../../bin/tests$EXEEXT --port-file server.port $meraw"
echo "$cmd" >remote.cmd
$cmd >remote.out.raw 2>remote.err &
children_register remote

# Let some time to run the tests.
children_wait 10

# Ignore the "client errors".
sed -e '/^E client error/d' remote.out.raw >remote.out.eff
# Compare expected output with actual output.
rst_expect output remote.out
rst_pre "Error output" remote.err

# Display Valgrind report.
rst_pre "Valgrind" remote.val

# Exit with success: liburbi-check made its job.  But now clean (on
# trap 0) will check $exit to see if there is a failure in the tests
# and adjust the exit status accordingly.
exit 0

m4_pattern_allow([^URBI_(PATH|SERVER)$])         -*- shell-script -*-
URBI_INIT

# Avoid zombies and preserve debugging information.
cleanup ()
{
  exit_status=$?

  # We can be killed even before children are spawned.
  test -n "$children" ||
    exit $exit_status

  # In case we were caught by set -e, kill the children.
  children_kill
  children_harvest
  children_report

  children_sta=$(children_status remote)
  # Don't clean before calling children_status...
  test x$VERBOSE != x || children_clean

  case $exit_status:$children_sta in
    (0:0) ;;
    (0:*) # Maybe a children exited for SKIP etc.
	 exit $children_sta;;
    (*:*) # If the checker failed, there is a big problem.
	 error SOFTWARE "$0 itself failed with $exit_status";;
  esac
  # rst_expect sets exit=false if it saw a failure.
  $exit
}
trap cleanup 0

# Overriden to include the test name.
stderr ()
{
  local i
  for i
  do
    echo >&2 "$(basename $0): $me: $i"
  done
  echo >&2
}

# Sleep some time, but taking into account the fact that
# instrumentation slows down a lot.
my_sleep ()
{
  if $INSTRUMENT; then
    sleep $(($1 * 5))
  else
    sleep $1
  fi
}

## -------------- ##
## Main program.  ##
## -------------- ##

exec 3>&2

check_dir abs_builddir bin/liburbi-check

# Make it absolute.
chk=$(absolute "$1")
if test ! -f "$chk.cc"; then
  fatal "no such file: $chk.cc"
fi

# ./../../../tests/2.x/andexp-pipeexp.chk -> 2.x
medir=$(basename $(dirname "$chk"))
# ./../../../tests/2.x/andexp-pipeexp.chk -> 2.x/andexp-pipeexp
me=$medir/$(basename "$chk" ".cc")
# ./../../../tests/2.x/andexp-pipeexp.chk -> andexp-pipeexp
meraw=$(basename $me)    # MERAW!

srcdir=$(absolute $srcdir)
export srcdir
# Move to a private dir.
mkcd $me.dir

# Help debugging
set | rst_pre "$me variables"

# Leaves trailing files, so run it in subdir.
find_urbi_server

# Compute expected output.
sed -n -e 's,//= ,,p' $chk.cc >output.exp
touch error.exp
echo 0 >status.exp

# Start it.
spawn_urbi_server

# Start the test.
valgrind=$(instrument "remote.val")
cmd="$valgrind ../../bin/tests$EXEEXT --port-file server.port $meraw"
echo "$cmd" >remote.cmd
$cmd >remote.out.raw 2>remote.err &
children_register remote

# Let some time to run the tests.
children_wait 10

# Ignore the "client errors".
sed -e '/^E client error/d' remote.out.raw >remote.out.eff
# Compare expected output with actual output.
rst_expect output remote.out
rst_pre "Error output" remote.err

# Display Valgrind report.
rst_pre "Valgrind" remote.val

# Exit with success: liburbi-check made its job.  But now clean (on
# trap 0) will check $exit to see if there is a failure in the tests
# and adjust the exit status accordingly.
exit 0

Fix stderr().

Fix stderr().

	* src/tests/bin/liburbi-check.as: Output should be on several lines.


package sample
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.text.TextField;

	public class Act203 extends Sprite
	{
		public function Act203()
		{
			super();
			addEventListener(Event.ADDED_TO_STAGE,init);
		}

		private function init(event:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE,init);

			var url:String = 'http://192.168.24.24/php/api.ph';
//			var url:String = 'http://192.168.24.24/php/api.php';

			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE,onLoaded);
			loader.addEventListener(IOErrorEvent.IO_ERROR,onLoadError);
			loader.dataFormat = URLLoaderDataFormat.TEXT;
			loader.load(new URLRequest(url));
		}

		private function onLoaded(event:Event):void
		{
			var loader:URLLoader = event.currentTarget as URLLoader;
			var text:String = loader.data as String;
			trace('API retun ' + text);
			showText(text);
		}

		private function onLoadError(event:IOErrorEvent):void
		{
			showText('an error occured.');
		}

		private function showText(message:String):void
		{
			var text:TextField = new TextField();
			text.text = message;
			text.width = 200;
			text.x = (stage.stageWidth - text.width) / 2;
			text.y = (stage.stageHeight - text.height) / 2;
			addChild(text);
		}
	}
}

package sample
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.text.TextField;

	public class Act203 extends Sprite
	{
		public function Act203()
		{
			super();
			addEventListener(Event.ADDED_TO_STAGE,init);
		}

		private function init(event:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE,init);

			var url:String = 'http://192.168.24.24/php/api.ph';
//			var url:String = 'http://192.168.24.24/php/api.php';

			var loader:URLLoader = new URLLoader();

			//↓これは使わない方がいい。対象のファイルが無い時にTryCatchが効かない
//			loader.dataFormat = URLLoaderDataFormat.VARIABLES;

			loader.addEventListener(Event.COMPLETE,onLoaded);
			loader.addEventListener(IOErrorEvent.IO_ERROR,onLoadError);
			loader.dataFormat = URLLoaderDataFormat.TEXT;
			loader.load(new URLRequest(url));
		}

		private function onLoaded(event:Event):void
		{
			var loader:URLLoader = event.currentTarget as URLLoader;
			var text:String = loader.data as String;
			trace('API retun ' + text);
			showText(text);
		}

		private function onLoadError(event:IOErrorEvent):void
		{
			showText('an error occured.');
		}

		private function showText(message:String):void
		{
			var text:TextField = new TextField();
			text.text = message;
			text.width = 200;
			text.x = (stage.stageWidth - text.width) / 2;
			text.y = (stage.stageHeight - text.height) / 2;
			addChild(text);
		}
	}
}

Update Act203.as

Update Act203.as

コメント追加


//
// $Id$

package com.threerings.flex {

import flash.display.DisplayObjectContainer;

import flash.events.Event;
import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.TextEvent;

import flash.ui.Keyboard;

import mx.containers.HBox;

import mx.core.Application;

import mx.controls.TextInput;

import mx.events.FlexEvent;

import com.threerings.util.ArrayUtil;
import com.threerings.util.StringUtil;

import com.threerings.flex.CommandButton;
import com.threerings.flex.CommandMenu;

import com.threerings.crowd.chat.client.ChatDirector;
import com.threerings.crowd.chat.data.ChatCodes;

import com.threerings.crowd.util.CrowdContext;

/**
 * The chat control widget.
 */
public class ChatControl extends HBox
{
    /**
     * Request focus for the oldest ChatControl.
     */
    public static function grabFocus () :void
    {
        if (_controls.length > 0) {
            (_controls[0] as ChatControl).setFocus();
        }
    }

    public function ChatControl (
        ctx :CrowdContext, sendButtonLabel :String = "send",
        height :Number = NaN, controlHeight :Number = NaN)
    {
        _ctx = ctx;
        _chatDtr = _ctx.getChatDirector();

        this.height = height;
        styleName = "chatControl";

        addChild(_txt = new ChatInput());
        _txt.addEventListener(FlexEvent.ENTER, sendChat, false, 0, true);

        _but = new CommandButton(sendButtonLabel, sendChat);
        addChild(_but);

        if (!isNaN(controlHeight)) {
            _txt.height = controlHeight;
            _but.height = controlHeight;
        }

        addEventListener(Event.ADDED_TO_STAGE, handleAddRemove);
        addEventListener(Event.REMOVED_FROM_STAGE, handleAddRemove);
    }

    /**
     * Provides access to the text field we use to accept chat.
     */
    public function get chatInput () :ChatInput
    {
        return _txt;
    }

    /**
     * Provides access to the send button.
     */
    public function get sendButton () :CommandButton
    {
        return _but;
    }

    /**
     * Request focus to this chat control.
     */
    override public function setFocus () :void
    {
        _txt.setFocus();
    }

    /**
     * Enables or disables our chat input.
     */
    public function setEnabled (enabled :Boolean) :void
    {
        _txt.enabled = enabled;
        _but.enabled = enabled;
    }

    /**
     * Configures the chat director to which we should send our chat. Pass null to restore our
     * default chat director.
     */
    public function setChatDirector (chatDtr :ChatDirector) :void
    {
        _chatDtr = (chatDtr == null) ? _ctx.getChatDirector() : chatDtr;
    }

    /**
     * Configures the background color of the text entry area.
     */
    public function setChatColor (color :int) :void
    {
        _txt.setStyle("backgroundColor", color);
    }

    /**
     * Handles FlexEvent.ENTER and the action from the send button.
     */
    protected function sendChat (... ignored) :void
    {
        var message :String = StringUtil.trim(_txt.text);
        if ("" == message) {
            return;
        }

        var result :String = _chatDtr.requestChat(null, message, true);
        if (result != ChatCodes.SUCCESS) {
            _chatDtr.displayFeedback(null, result);
            return;
        }

        // if there was no error, clear the entry area in prep for the next entry event
        _txt.text = "";
    }

    /**
     * Handles Event.ADDED_TO_STAGE and Event.REMOVED_FROM_STAGE.
     */
    protected function handleAddRemove (event :Event) :void
    {
        if (event.type == Event.ADDED_TO_STAGE) {
            // set up any already-configured text
            _txt.text = _curLine;

            // request focus
            callLater(_txt.setFocus);
            _controls.push(this);

        } else {
            _curLine = _txt.text;
            ArrayUtil.removeAll(_controls, this);
        }
    }

    /** Our client-side context. */
    protected var _ctx :CrowdContext;

    /** The director to which we are sending chat requests. */
    protected var _chatDtr :ChatDirector;

    /** The place where the user may enter chat. */
    protected var _txt :ChatInput;

    /** The button for sending chat. */
    protected var _but :CommandButton;

    /** An array of the currently shown-controls. */
    protected static var _controls :Array = [];

    /** The preserved current line of text when traversing history or carried between instances of
     * ChatControl. */
    protected static var _curLine :String;
}
}

//
// $Id$

package com.threerings.flex {

import flash.display.DisplayObjectContainer;

import flash.events.Event;
import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.TextEvent;

import flash.ui.Keyboard;

import mx.containers.HBox;

import mx.core.Application;

import mx.controls.TextInput;

import mx.events.FlexEvent;

import com.threerings.util.ArrayUtil;
import com.threerings.util.StringUtil;

import com.threerings.flex.CommandButton;
import com.threerings.flex.CommandMenu;

import com.threerings.crowd.chat.client.ChatDirector;
import com.threerings.crowd.chat.data.ChatCodes;

import com.threerings.crowd.util.CrowdContext;

/**
 * The chat control widget.
 */
public class ChatControl extends HBox
{
    /**
     * Request focus for the oldest ChatControl.
     */
    public static function grabFocus () :void
    {
        if (_controls.length > 0) {
            (_controls[0] as ChatControl).setFocus();
        }
    }

    public function ChatControl (
        ctx :CrowdContext, sendButtonLabel :String = "send",
        height :Number = NaN, controlHeight :Number = NaN)
    {
        _ctx = ctx;
        _chatDtr = _ctx.getChatDirector();

        this.height = height;
        styleName = "chatControl";

        addChild(_txt = new ChatInput());
        _txt.addEventListener(FlexEvent.ENTER, sendChat, false, 0, true);
        _txt.addEventListener(KeyboardEvent.KEY_UP, handleKeyUp);

        _but = new CommandButton(sendButtonLabel, sendChat);
        addChild(_but);

        if (!isNaN(controlHeight)) {
            _txt.height = controlHeight;
            _but.height = controlHeight;
        }

        addEventListener(Event.ADDED_TO_STAGE, handleAddRemove);
        addEventListener(Event.REMOVED_FROM_STAGE, handleAddRemove);
    }

    /**
     * Provides access to the text field we use to accept chat.
     */
    public function get chatInput () :ChatInput
    {
        return _txt;
    }

    /**
     * Provides access to the send button.
     */
    public function get sendButton () :CommandButton
    {
        return _but;
    }

    /**
     * Request focus to this chat control.
     */
    override public function setFocus () :void
    {
        _txt.setFocus();
    }

    /**
     * Enables or disables our chat input.
     */
    public function setEnabled (enabled :Boolean) :void
    {
        _txt.enabled = enabled;
        _but.enabled = enabled;
    }

    /**
     * Configures the chat director to which we should send our chat. Pass null to restore our
     * default chat director.
     */
    public function setChatDirector (chatDtr :ChatDirector) :void
    {
        _chatDtr = (chatDtr == null) ? _ctx.getChatDirector() : chatDtr;
    }

    /**
     * Configures the background color of the text entry area.
     */
    public function setChatColor (color :int) :void
    {
        _txt.setStyle("backgroundColor", color);
    }

    /**
     * Handles FlexEvent.ENTER and the action from the send button.
     */
    protected function sendChat (... ignored) :void
    {
        var message :String = StringUtil.trim(_txt.text);
        if ("" == message) {
            return;
        }

        var result :String = _chatDtr.requestChat(null, message, true);
        if (result != ChatCodes.SUCCESS) {
            _chatDtr.displayFeedback(null, result);
            return;
        }

        // if there was no error, clear the entry area in prep for the next entry event
        _txt.text = "";
        _histidx = -1;
    }

    protected function scrollHistory (next :Boolean) :void
    {
        var size :int = _chatDtr.getCommandHistorySize();
        if ((_histidx == -1) || (_histidx == size)) {
            _curLine = _txt.text;
            _histidx = size;
        }

        _histidx = (next) ? Math.min(_histidx + 1, size)
                          : Math.max(_histidx - 1, 0);
        var text :String = (_histidx == size) ? _curLine : _chatDtr.getCommandHistory(_histidx);
        _txt.text = text;
        _txt.setSelection(text.length, text.length);
    }

    /**
     * Handles Event.ADDED_TO_STAGE and Event.REMOVED_FROM_STAGE.
     */
    protected function handleAddRemove (event :Event) :void
    {
        if (event.type == Event.ADDED_TO_STAGE) {
            // set up any already-configured text
            _txt.text = _curLine;
            _histidx = -1;

            // request focus
            callLater(_txt.setFocus);
            _controls.push(this);

        } else {
            _curLine = _txt.text;
            ArrayUtil.removeAll(_controls, this);
        }
    }

    protected function handleKeyUp (event :KeyboardEvent) :void
    {
        switch (event.keyCode) {
        case Keyboard.UP: scrollHistory(false); break;
        case Keyboard.DOWN: scrollHistory(true); break;
        }
    }

    /** Our client-side context. */
    protected var _ctx :CrowdContext;

    /** The director to which we are sending chat requests. */
    protected var _chatDtr :ChatDirector;

    /** The place where the user may enter chat. */
    protected var _txt :ChatInput;

    /** The current index in the chat command history. */
    protected var _histidx :int = -1;

    /** The button for sending chat. */
    protected var _but :CommandButton;

    /** An array of the currently shown-controls. */
    protected static var _controls :Array = [];

    /** The preserved current line of text when traversing history or carried between instances of
     * ChatControl. */
    protected static var _curLine :String;
}
}

Allow the up and down arrow keys to traverse the command history, like we do in Java.

git-svn-id: b675b909355d5cf946977f44a8ec5a6ceb3782e4@667 ed5b42cb-e716-0410-a449-f6a68f950b19