package {
  import flash.display.Sprite;
  import flash.external.ExternalInterface;
  import flash.system.Security;
  import flash.net.NetStream;
  import flash.events.*;

  import org.osmf.containers.MediaContainer;
  import org.osmf.elements.VideoElement;
  import org.osmf.net.NetStreamLoadTrait;

  import org.osmf.media.DefaultMediaFactory;
  import org.osmf.media.MediaElement;
  import org.osmf.media.MediaPlayer;
  import org.osmf.media.URLResource;

  import org.osmf.events.TimeEvent;
  import org.osmf.events.BufferEvent;
  import org.osmf.events.MediaElementEvent;
  import org.osmf.events.LoadEvent;

  import org.osmf.traits.MediaTraitType;

  [SWF(width="640", height="360")]
  public class RTMP extends Sprite {
    private var playbackId:String;
    private var mediaFactory:DefaultMediaFactory;
    private var mediaContainer:MediaContainer;
    private var mediaPlayer:MediaPlayer;
    private var netStream:NetStream;
    private var mediaElement:MediaElement;
    private var netStreamLoadTrait:NetStreamLoadTrait;
    private var playbackState:String = "IDLE";

    public function RTMP() {
      Security.allowDomain('*');
      Security.allowInsecureDomain('*');
      playbackId = this.root.loaderInfo.parameters.playbackId;
      mediaFactory = new DefaultMediaFactory();
      mediaContainer = new MediaContainer();
      setupCallbacks();
      setupGetters();
      ExternalInterface.call('console.log', 'clappr rtmp 0.6-alpha');
      _triggerEvent('flashready');
    }

    private function setupCallbacks():void {
      ExternalInterface.addCallback("playerLoad", playerLoad);
      ExternalInterface.addCallback("playerPlay", playerPlay);
      ExternalInterface.addCallback("playerPause", playerPause);
      ExternalInterface.addCallback("playerStop", playerStop);
      ExternalInterface.addCallback("playerSeek", playerSeek);
      ExternalInterface.addCallback("playerVolume", playerVolume);
    }

    private function setupGetters():void {
      ExternalInterface.addCallback("getState", getState);
      ExternalInterface.addCallback("getPosition", getPosition);
      ExternalInterface.addCallback("getDuration", getDuration);
    }

    private function playerLoad(url:String):void {
      mediaElement = mediaFactory.createMediaElement(new URLResource(url));
      mediaElement.addEventListener(MediaElementEvent.TRAIT_ADD, onTraitAdd);
      mediaPlayer = new MediaPlayer(mediaElement);
      mediaPlayer.autoPlay = false;
      mediaPlayer.addEventListener(TimeEvent.CURRENT_TIME_CHANGE, onTimeUpdated);
      mediaPlayer.addEventListener(TimeEvent.DURATION_CHANGE, onTimeUpdated);
      mediaContainer.addMediaElement(mediaElement);
      addChild(mediaContainer);
    }

    private function onTraitAdd(event:MediaElementEvent):void {
      if (mediaElement.hasTrait(MediaTraitType.LOAD)) {
        netStreamLoadTrait = mediaElement.getTrait(MediaTraitType.LOAD) as NetStreamLoadTrait;
        netStreamLoadTrait.addEventListener(LoadEvent.LOAD_STATE_CHANGE, onLoaded);
      }
    }

    private function onLoaded(event:LoadEvent):void {
      netStream = netStreamLoadTrait.netStream;
      netStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
    }

    private function netStatusHandler(event:NetStatusEvent):void {
      ExternalInterface.call('console.log', 'new event:' + event.info.code);
      if (event.info.code === "NetStream.Buffer.Full") {
        playbackState = "PLAYING";
      } else if (isBuffering(event.info.code)) {
        playbackState = "PLAYING_BUFFERING";
      } else if (event.info.code == "NetStream.Play.Stop") {
        playbackState = "ENDED";
      } else if (event.info.code == "NetStream.Buffer.Empty") {
        playbackState = "BUFFERING";
      }
      _triggerEvent('statechanged');
    }

    private function isBuffering(code:String):Boolean {
      return Boolean(code == "NetStream.Buffer.Empty" && playbackState != "ENDED" ||
              code == "NetStream.SeekStart.Notify" ||
              code == "NetStream.Play.Start");
    }

    private function playerPlay():void {
      mediaPlayer.play();
    }

    private function playerPause():void {
      mediaPlayer.pause();
    }

    private function playerSeek(seconds:Number):void {
      mediaPlayer.seek(seconds);
    }

    private function playerStop():void {
      mediaPlayer.stop();
    }

    private function playerVolume(level:Number):void {
      mediaPlayer.volume = level;
    }

   private function getState():String {
      return playbackState;
    }

    private function getPosition():Number {
      return mediaPlayer.currentTime;
    }

    private function getDuration():Number {
      return mediaPlayer.duration;
    }

    private function onTimeUpdated(event:TimeEvent):void {
      _triggerEvent('progress');
      _triggerEvent('timeupdate');
    }

    private function _triggerEvent(name: String):void {
      ExternalInterface.call('Clappr.Mediator.trigger("' + playbackId + ':' + name +'")');
    }
  }
}

package {
  import flash.display.Sprite;
  import flash.external.ExternalInterface;
  import flash.system.Security;
  import flash.net.NetStream;
  import flash.events.*;

  import org.osmf.containers.MediaContainer;
  import org.osmf.elements.VideoElement;
  import org.osmf.net.NetStreamLoadTrait;

  import org.osmf.media.DefaultMediaFactory;
  import org.osmf.media.MediaElement;
  import org.osmf.media.MediaPlayer;
  import org.osmf.media.URLResource;

  import org.osmf.events.TimeEvent;
  import org.osmf.events.BufferEvent;
  import org.osmf.events.MediaElementEvent;
  import org.osmf.events.LoadEvent;

  import org.osmf.traits.MediaTraitType;

  [SWF(width="640", height="360")]
  public class RTMP extends Sprite {
    private var playbackId:String;
    private var mediaFactory:DefaultMediaFactory;
    private var mediaContainer:MediaContainer;
    private var mediaPlayer:MediaPlayer;
    private var netStream:NetStream;
    private var mediaElement:MediaElement;
    private var netStreamLoadTrait:NetStreamLoadTrait;
    private var playbackState:String = "IDLE";

    public function RTMP() {
      Security.allowDomain('*');
      Security.allowInsecureDomain('*');
      playbackId = this.root.loaderInfo.parameters.playbackId;
      mediaFactory = new DefaultMediaFactory();
      mediaContainer = new MediaContainer();
      setupCallbacks();
      setupGetters();
      ExternalInterface.call('console.log', 'clappr rtmp 0.6-alpha');
      _triggerEvent('flashready');
    }

    private function setupCallbacks():void {
      ExternalInterface.addCallback("playerLoad", playerLoad);
      ExternalInterface.addCallback("playerPlay", playerPlay);
      ExternalInterface.addCallback("playerPause", playerPause);
      ExternalInterface.addCallback("playerStop", playerStop);
      ExternalInterface.addCallback("playerSeek", playerSeek);
      ExternalInterface.addCallback("playerVolume", playerVolume);
    }

    private function setupGetters():void {
      ExternalInterface.addCallback("getState", getState);
      ExternalInterface.addCallback("getPosition", getPosition);
      ExternalInterface.addCallback("getDuration", getDuration);
    }

    private function playerLoad(url:String):void {
      mediaElement = mediaFactory.createMediaElement(new URLResource(url));
      mediaElement.addEventListener(MediaElementEvent.TRAIT_ADD, onTraitAdd);
      mediaPlayer = new MediaPlayer(mediaElement);
      mediaPlayer.autoPlay = false;
      mediaPlayer.addEventListener(TimeEvent.CURRENT_TIME_CHANGE, onTimeUpdated);
      mediaPlayer.addEventListener(TimeEvent.DURATION_CHANGE, onTimeUpdated);
      mediaContainer.addMediaElement(mediaElement);
      addChild(mediaContainer);
    }

    private function onTraitAdd(event:MediaElementEvent):void {
      if (mediaElement.hasTrait(MediaTraitType.LOAD)) {
        netStreamLoadTrait = mediaElement.getTrait(MediaTraitType.LOAD) as NetStreamLoadTrait;
        netStreamLoadTrait.addEventListener(LoadEvent.LOAD_STATE_CHANGE, onLoaded);
      }
    }

    private function onLoaded(event:LoadEvent):void {
      netStream = netStreamLoadTrait.netStream;
      netStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
    }

    private function netStatusHandler(event:NetStatusEvent):void {
      ExternalInterface.call('console.log', 'new event:' + event.info.code);
      if (event.info.code === "NetStream.Buffer.Full") {
        playbackState = "PLAYING";
      } else if (isBuffering(event.info.code)) {
        playbackState = "PLAYING_BUFFERING";
      } else if (event.info.code == "NetStream.Play.Stop") {
        playbackState = "ENDED";
      } else if (event.info.code == "NetStream.Buffer.Empty") {
        playbackState = "BUFFERING";
      }
      _triggerEvent('statechanged');
    }

    private function isBuffering(code:String):Boolean {
      return Boolean(code == "NetStream.Buffer.Empty" && playbackState != "ENDED" ||
              code == "NetStream.SeekStart.Notify" ||
              code == "NetStream.Play.Start");
    }

    private function playerPlay():void {
      mediaPlayer.play();
    }

    private function playerPause():void {
      mediaPlayer.pause();
    }

    private function playerSeek(seconds:Number):void {
      mediaPlayer.seek(seconds);
    }

    private function playerStop():void {
      mediaPlayer.stop();
    }

    private function playerVolume(level:Number):void {
      mediaPlayer.volume = level/100;
    }

   private function getState():String {
      return playbackState;
    }

    private function getPosition():Number {
      return mediaPlayer.currentTime;
    }

    private function getDuration():Number {
      return mediaPlayer.duration;
    }

    private function onTimeUpdated(event:TimeEvent):void {
      _triggerEvent('progress');
      _triggerEvent('timeupdate');
    }

    private function _triggerEvent(name: String):void {
      ExternalInterface.call('Clappr.Mediator.trigger("' + playbackId + ':' + name +'")');
    }
  }
}

fix volume level value (close #4)

RTMP.as: fix volume level value (close #4)


/*
 * Copyright 2011 Ryan Berdeen. All rights reserved.
 * Distributed under the terms of the MIT License.
 * See accompanying file LICENSE.txt
 */

package com.ryanberdeen.echonest.api.v4.track {
  import com.adobe.serialization.json.JSON;
  import com.ryanberdeen.echonest.api.v4.ApiSupport;
  import com.ryanberdeen.echonest.api.v4.EchoNestError;

  import flash.events.DataEvent;
  import flash.events.Event;
  import flash.net.FileReference;
  import flash.net.URLLoader;
  import flash.net.URLRequest;
  import flash.net.URLRequestMethod;
  import flash.utils.ByteArray;

  /**
  * Methods to interact with the Echo Nest track API.
  *
  *
All of the API methods in this class accept basically the same
  * parameters. The parameters parameter contains the parameters
  * to pass to the Echo Nest method. For most methods, this will be
  * id or md5.
  * The api_key parameter will always be
  * set.

  *
  *
The loaderOptions parameter contains the event listeners
  * for the loading process. Most importantly, the
  * onResponse method will be called with the
  * results of the API method. See the ApiSupport.createLoader()
  * method for a description of the loader options.

  *
  *
For a description of the response formats, see the various
  * process...Response() methods.

  *
  *
Be sure to set the apiKey property before calling any API
  * methods.

  */
  public class TrackApi extends ApiSupport {
    /**
    * Adds the standard Echo Nest Flash API event listeners to a file
    * reference.
    *
    * @param options The event listener options. See
    *        createLoader() for the list of available options.
    * @param dispatcher The file reference to add the event listeners to.
    */
    public function addFileReferenceEventListeners(options:Object, fileReference:FileReference, responseProcessor:Function, ...responseProcessorArgs):void {
      // TODO document
      if (options.onOpen) {
        fileReference.addEventListener(Event.OPEN, options.onOpen);
      }

      if (options.onComplete) {
        fileReference.addEventListener(Event.COMPLETE, options.onComplete);
      }

      if (options.onResponse) {
        fileReference.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, function(e:DataEvent):void {
          try {
            var responseObject:* = parseRawResponse(e.data);
            responseProcessorArgs.push(responseObject);
            var response:Object = responseProcessor.apply(responseProcessor, responseProcessorArgs);
            options.onResponse(response);
          }
          catch (e:EchoNestError) {
            if (options.onEchoNestError) {
              options.onEchoNestError(e);
            }
          }
        });
      }

      addEventListeners(options, fileReference);
    }

    public function loadAnalysis(track:Object, loaderOptions:Object):URLLoader {
      var loader:URLLoader = new URLLoader();

      if (loaderOptions.onComplete) {
        loader.addEventListener(Event.COMPLETE, loaderOptions.onComplete);
      }

      if (loaderOptions.onResponse) {
        loader.addEventListener(Event.COMPLETE, function(e:Event):void {
          var analysis:Object = JSON.decode(loader.data);
          loaderOptions.onResponse(analysis);
        });
      }

      addEventListeners(loaderOptions, loader);

      var request:URLRequest = new URLRequest();
      request.url = track.audio_summary.analysis_url;
      loader.load(request);
      return loader;
    }

    /**
    * Processes the response from the upload API method.
    *
    * @param response The response to process.
    *
    * @return The result of processing the response.
    *
    * @see #upload()
    * @see #uploadFileData()
    */
    public function processUploadResponse(response:*):Object {
      return response.track;
    }

    /**
    * Invokes the Echo Nest upload API method with a file
    * reference.
    *
    *
The parameters object must include a track
    * property, which must be a FileReference that may be
    * upload()ed.

    *
    * @param parameters The parameters to include in the API request.
    * @param loaderOptions The event listener options for the loader.
    *
    * @see com.ryanberdeen.echonest.api.v3.ApiSupport#createRequest()
    * @see #processUploadResponse()
    * @see http://developer.echonest.com/docs/v4/track.html#upload
    */
    public function uploadFileReference(parameters:Object, loaderOptions:Object):URLRequest {
      var fileReference:FileReference = parameters.track;
      delete parameters.track;

      addFileReferenceEventListeners(loaderOptions, fileReference, processUploadResponse);
      var request:URLRequest = createRequest('track/upload', parameters);
      fileReference.upload(request, 'track');
      return request;
    }

    /**
    * Invokes the Echo Nest upload API method.
    *
    *
This method is for uploads using the url parameter.
    * To upload a file, use uploadFileReference().
    *
    * @param parameters The parameters to include in the API request.
    * @param loaderOptions The event listener options for the loader.
    *
    * @return The URLLoader being used to perform the API call.
    *
    * @see com.ryanberdeen.echonest.api.v4.ApiSupport#createRequest()
    * @see com.ryanberdeen.echonest.api.v4.ApiSupport#createLoader()
    * @see #processUploadResponse()
    * @see http://developer.echonest.com/docs/v4/track.html#upload
    */
    public function upload(parameters:Object, loaderOptions:Object):URLLoader {
      var request:URLRequest = createRequest('track/upload', parameters);
      request.method = URLRequestMethod.POST;
      var loader:URLLoader = createLoader(loaderOptions, processUploadResponse);
      loader.load(request);
      return loader;
    }
  }
}

fix asdoc html

fix asdoc html


package
{
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.TouchEvent;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.ui.Multitouch;
	import flash.ui.MultitouchInputMode;

	import org.osmf.layout.HorizontalAlign;

	[ SWF(backgrouncColor="0xFFFFFF",
		  frameRate="25",
		  width="320",
		  height="480") ]

	public class MultitouchAndGestures extends Sprite
	{
		private var coordinates:TextField;
		private var multitouch:TextField;
		private var offsetX:Number;
		private var offsetY:Number;

		public function MultitouchAndGestures()
		{
			super();

			// 支持 autoOrient
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;

			multitouch = new TextField();
			multitouch.autoSize = TextFieldAutoSize.LEFT;

			switch(Multitouch.supportsTouchEvents)
			{
				case true:
				{
					Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
					multitouch.text = "Touch Supported, max points: " + Multitouch.maxTouchPoints;

					stage.addEventListener(TouchEvent.TOUCH_BEGIN, onTouch);
					stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouch);
					stage.addEventListener(TouchEvent.TOUCH_END, onTouch);
				}
					break;
				case false:
				{
					multitouch.text = "Not Supported";
				}
					break;
				default:
					break;
			}
			stage.addChild(multitouch);
		}

		private function onTouch(e:TouchEvent):void
		{
			var id:Number = e.touchPointID;
			var x:Number = e.stageX;
			var y:Number = e.stageY;

			switch(e.type) {
				case TouchEvent.TOUCH_BEGIN:
					removeShape(id);
					drawLines(id, x, y);
					drawShape(id, x, y);
					break;
				case TouchEvent.TOUCH_MOVE:
					moveLines(id, x, y);
					drawShape(id, x, y);
					break;
				case TouchEvent.TOUCH_END:
					removeLines(id);
					break;
			}
		}

		private function drawLines(id:Number, x:Number, y:Number):void {
			offsetX = x;
			offsetY = y;

			var vertical:Sprite = new Sprite();
			vertical.name = id+"v";
			vertical.graphics.lineStyle(2, 0x000000);
			vertical.graphics.moveTo(x, 0);
			vertical.graphics.lineTo(x, stage.stageHeight);
			stage.addChild(vertical);

			var horizontal:Sprite = new Sprite();
			horizontal.name = id + "h";
			horizontal.graphics.lineStyle(2, 0x000000);
			horizontal.graphics.moveTo(0, y);
			horizontal.graphics.lineTo(stage.stageWidth, y);
			stage.addChild(horizontal);

			setCoordinates(x, y);
		}

		private function moveLines(id:Number, x:Number, y:Number):void {
			var vertical:Sprite = Sprite(stage.getChildByName(id + "v"));
			var horizontal:Sprite = Sprite(stage.getChildByName(id + "h"));

			vertical.x = x - offsetX;
			horizontal.y = y - offsetY;

			setCoordinates(x, y);
		}

		private function removeLines(id:Number):void {
			stage.removeChild(Sprite(stage.getChildByName(id + "v")));
			stage.removeChild(Sprite(stage.getChildByName(id + "h")));
			stage.removeChild(coordinates);
			coordinates = null;
		}

		private function setCoordinates(x:Number, y:Number):void {
			if (!coordinates) {
				coordinates = new TextField();
				stage.addChild(coordinates);
			}
			coordinates.text =  "("+x+", "+y+")";
			coordinates.x = x-200;
			if (coordinates.x < 0) {
				coordinates.x = x + 100;
			}
			coordinates.y = y-70;
			if (coordinates.y < 0) {
				coordinates.y = y + 100;
			}
		}

		private function drawShape(id:Number, x:Number, y:Number):void {
			var shape:Sprite;
			var shapeId:String = "shape01";
//			var shapeId:String = id.toString();
			if (!stage.getChildByName(shapeId)) {
				shape = new Sprite();
				shape.name = shapeId;
				stage.addChild(shape);
			} else {
				shape = stage.getChildByName(shapeId) as Sprite;
			}

			var width:Number = x - offsetX;
			var height:Number = y - offsetY;

			shape.graphics.lineStyle(2, 0x000000, 1.0);
			shape.graphics.beginFill(0x000000, 0.0);
			shape.graphics.drawRect(offsetX, offsetY, width, height);
			shape.graphics.endFill();
		}

		private function removeShape(id:Number):void {
			var shapeId:String = "shape01";
//			var shapeId:String = id.toString();
			var shape:Sprite = null;
			shape = stage.getChildByName(shapeId) as Sprite;
			if (shape != null) {
				stage.removeChild(shape);
			}
		}
	}
}

package
{
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.GesturePhase;
	import flash.events.TimerEvent;
	import flash.events.TouchEvent;
	import flash.events.TransformGestureEvent;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.ui.Multitouch;
	import flash.ui.MultitouchInputMode;
	import flash.utils.Timer;

	import org.flexunit.internals.matchers.Each;

	[ SWF(backgrouncColor="0xFFFFFF",
		  frameRate="25",
		  width="320",
		  height="480") ]

	public class MultitouchAndGestures extends Sprite
	{
		private var coordinates:TextField;
		private var multitouch:TextField;
		private var currentTarget:String;
		private var idleTimer:Timer;
		private var offsetX:Number;
		private var offsetY:Number;

		public function MultitouchAndGestures()
		{
			super();

			// 支持 autoOrient
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;

			multitouch = new TextField();
			multitouch.autoSize = TextFieldAutoSize.LEFT;

			idleTimer = new Timer(1000);
			idleTimer.addEventListener(TimerEvent.TIMER, onTimer);

			switch(Multitouch.supportsTouchEvents)
			{
				case true:
				{
					Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
					multitouch.text = "Touch Supported, max points: " + Multitouch.maxTouchPoints;

					stage.addEventListener(TouchEvent.TOUCH_BEGIN, onTouch);
					stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouch);
					stage.addEventListener(TouchEvent.TOUCH_END, onTouch);
				}
					break;
				case false:
				{
					multitouch.text = "Not Supported";
				}
					break;
				default:
					break;
			}
			stage.addChild(multitouch);
		}

		private function onTouch(e:TouchEvent):void
		{
			var id:Number = e.touchPointID;
			var x:Number = e.stageX;
			var y:Number = e.stageY;

			switch(e.type) {
				case TouchEvent.TOUCH_BEGIN:
					if (e.target is Stage) {
						removeShape(id);
						drawLines(id, x, y);
						drawShape(id, x, y);
					} else {
						currentTarget = e.target.name;
						initializeGestures();
					}
					break;
				case TouchEvent.TOUCH_MOVE:
					moveLines(id, x, y);
					drawShape(id, x, y);
					break;
				case TouchEvent.TOUCH_END:
					removeLines(id);
					break;
			}
		}

		private function drawLines(id:Number, x:Number, y:Number):void {
			offsetX = x;
			offsetY = y;

			var vertical:Sprite = new Sprite();
			vertical.name = id+"v";
			vertical.graphics.lineStyle(2, 0x000000);
			vertical.graphics.moveTo(x, 0);
			vertical.graphics.lineTo(x, stage.stageHeight);
			stage.addChild(vertical);

			var horizontal:Sprite = new Sprite();
			horizontal.name = id + "h";
			horizontal.graphics.lineStyle(2, 0x000000);
			horizontal.graphics.moveTo(0, y);
			horizontal.graphics.lineTo(stage.stageWidth, y);
			stage.addChild(horizontal);

			setCoordinates(x, y);
		}

		private function moveLines(id:Number, x:Number, y:Number):void {
			var vertical:Sprite = Sprite(stage.getChildByName(id + "v"));
			var horizontal:Sprite = Sprite(stage.getChildByName(id + "h"));

			vertical.x = x - offsetX;
			horizontal.y = y - offsetY;

			setCoordinates(x, y);
		}

		private function removeLines(id:Number):void {
			stage.removeChild(Sprite(stage.getChildByName(id + "v")));
			stage.removeChild(Sprite(stage.getChildByName(id + "h")));
			stage.removeChild(coordinates);
			coordinates = null;
		}

		private function setCoordinates(x:Number, y:Number):void {
			if (!coordinates) {
				coordinates = new TextField();
				stage.addChild(coordinates);
			}
			coordinates.text =  "("+x+", "+y+")";
			coordinates.x = x-200;
			if (coordinates.x < 0) {
				coordinates.x = x + 100;
			}
			coordinates.y = y-70;
			if (coordinates.y < 0) {
				coordinates.y = y + 100;
			}
		}

		private function drawShape(id:Number, x:Number, y:Number):void {
			var shape:Sprite;
			var shapeId:String = "shape01";
//			var shapeId:String = id.toString();
			if (!stage.getChildByName(shapeId)) {
				shape = new Sprite();
				shape.name = shapeId;
				for each(var g:String in Multitouch.supportedGestures) {
					switch(g)
					{
						case TransformGestureEvent.GESTURE_PAN:
							shape.addEventListener(g, onPan);
							break;
						default:
							break;
					}
				}
				stage.addChild(shape);
			} else {
				shape = stage.getChildByName(shapeId) as Sprite;
			}

			var width:Number = x - offsetX;
			var height:Number = y - offsetY;

			shape.graphics.lineStyle(2, 0x000000, 1.0);
			shape.graphics.beginFill(0x000000, 0.0);
			shape.graphics.drawRect(offsetX, offsetY, width, height);
			shape.graphics.endFill();
		}

		private function removeShape(id:Number):void {
			var shapeId:String = "shape01";
//			var shapeId:String = id.toString();
			var shape:Sprite = null;
			shape = stage.getChildByName(shapeId) as Sprite;
			if (shape != null) {
				stage.removeChild(shape);
			}
		}

		//--------------------------
		private function onTimer(e:TimerEvent):void {
			idleTimer.stop();
			initializeTouch();
		}

		private function initializeTimer():void {
			idleTimer.delay = 1000;
			if (!idleTimer.running) {
				idleTimer.start();
			}
		}

		private function initializeGestures():void {
			if (Multitouch.supportsGestureEvents) {
				Multitouch.inputMode = MultitouchInputMode.GESTURE;
				initializeTimer();
			}
		}

		private function initializeTouch():void {
			if (Multitouch.supportsTouchEvents) {
				Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
			}
		}

		private function onPan(e:TransformGestureEvent):void {
			var shape:Sprite = stage.getChildByName(currentTarget) as Sprite;
			switch(e.phase) {
				case GesturePhase.UPDATE:
					shape.x = shape.x + e.offsetX;
					shape.y = shape.y + e.offsetY;
					initializeTimer();
				break;
			}
		}
	}
}

add Gestures # modified: MultitouchAndGestures/src/MultitouchAndGestures.as


##                                                        -*- shell-script -*-
## instrument.as: This file is part of build-aux.
## Copyright (C) Gostai S.A.S., 2006-2008.
##
## This software is provided "as is" without warranty of any kind,
## either expressed or implied, including but not limited to the
## implied warranties of fitness for a particular purpose.
##
## See the LICENSE file for more information.
## For comments, bug reports and feedback: http://www.urbiforge.com
##

m4_defun([_URBI_INSTRUMENT_PREPARE],
[normalize_boolean ()
{
  local var=$[1]
  local val
  eval val=\$$var
  case $val in
      yes|true|1) eval $var=true;;
      *)          eval $var=false;;
  esac
  eval stderr "$var=\$$var"
}

# COMMAND-PREFIX instrument LOG-FILE
# ----------------------------------
# Return what's to be prepended to an executable so that it is instrumented
# to be checked: Valgrind or Darwin's Malloc features.
#
# Use LOG-FILE as output file.
#
# Shared with uconsole-check, please keep sync.
instrument ()
{
  local log=$[1]
  case $INSTRUMENT:$(uname -s) in
      true:Darwin)
	  # Instrument to use Darwin's malloc features.  The man page
	  # says "MallocBadFreeAbort" exists, but setting MallocHelp
	  # reports about "MallocErrorAbort".  The former does not
	  # work, the latter does.
	  echo "env"				\
	      "MallocGuardEdges=1"		\
	      "MallocPreScribble=1"		\
	      "MallocScribble=1"		\
	      "MallocErrorAbort=1"		\
	      "MallocCheckHeapAbort=1"		\
	      "MallocLogFile=$log"
	  ;;
      true:*)
	  # Instrument using Valgrind.
	  : ${VALGRIND=valgrind}
	  if ($VALGRIND --version) >/dev/null 2>&1; then
	    local suppressions
	    if test -f $srcdir/valgrind-suppressions; then
	      suppressions="--suppressions=$srcdir/valgrind-suppressions"
	    fi
	    echo "$VALGRIND"			\
		 "--error-exitcode=242"		\
		 "--log-file-exactly=$log"	\
		 "$suppressions"		\
		 "--"
	  else
	    stderr "cannot find valgrind as $VALGRIND"
	  fi
	  ;;
      *)
	  # Don't instrument.
	  ;;
  esac
}

# FIXME: This should be issued farther in the code, not with the functions.
normalize_boolean INSTRUMENT
])

m4_defun([URBI_INSTRUMENT_PREPARE],
[m4_divert_text([M4SH-INIT], [_URBI_INSTRUMENT_PREPARE])])

##                                                        -*- shell-script -*-
## instrument.as: This file is part of build-aux.
## Copyright (C) Gostai S.A.S., 2006-2008.
##
## This software is provided "as is" without warranty of any kind,
## either expressed or implied, including but not limited to the
## implied warranties of fitness for a particular purpose.
##
## See the LICENSE file for more information.
## For comments, bug reports and feedback: http://www.urbiforge.com
##

m4_defun([_URBI_INSTRUMENT_PREPARE],
[normalize_boolean ()
{
  local var=$[1]
  local val
  eval val=\$$var
  case $val in
      yes|true|1) eval $var=true;;
      *)          eval $var=false;;
  esac
  eval stderr "$var=\$$var"
}

# COMMAND-PREFIX instrument LOG-FILE
# ----------------------------------
# Return what's to be prepended to an executable so that it is instrumented
# to be checked: Valgrind or Darwin's Malloc features.
#
# Use LOG-FILE as output file.
#
# Shared with uconsole-check, please keep sync.
instrument ()
{
  local log=$[1]
  case $INSTRUMENT:$(uname -s) in
      true:Darwin)
	  # Instrument to use Darwin's malloc features.  The man page
	  # says "MallocBadFreeAbort" exists, but setting MallocHelp
	  # reports about "MallocErrorAbort".  The former does not
	  # work, the latter does.
	  echo "env"				\
	      "MallocGuardEdges=1"		\
	      "MallocPreScribble=1"		\
	      "MallocScribble=1"		\
	      "MallocErrorAbort=1"		\
	      "MallocCheckHeapAbort=1"		\
	      "MallocLogFile=$log"
	  ;;
      true:*)
	  # Instrument using Valgrind.
	  : ${VALGRIND=valgrind}
	  if ($VALGRIND --version) >/dev/null 2>&1; then
	    local suppressions
	    if test -f $srcdir/valgrind-suppressions; then
	      suppressions="--suppressions=$srcdir/valgrind-suppressions"
	    fi

	    case $($VALGRIND --help) in
	    *--log-file-exactly*) valgrind_log_option_name=--log-file-exactly ;;
	    *) valgrind_log_option_name=--log-file ;;
	    esac

	    echo "$VALGRIND"				\
	      "--error-exitcode=242"			\
		 "$valgrind_log_option_name=$log"	\
		 "$suppressions"			\
		 "--"
	  else
	    stderr "cannot find valgrind as $VALGRIND"
	  fi
	  ;;
      *)
	  # Don't instrument.
	  ;;
  esac
}

# FIXME: This should be issued farther in the code, not with the functions.
normalize_boolean INSTRUMENT
])

m4_defun([URBI_INSTRUMENT_PREPARE],
[m4_divert_text([M4SH-INIT], [_URBI_INSTRUMENT_PREPARE])])

Handle recent valgrinds without --log-file-exactly option.

	* build-aux/instrument.as(instrument): Check output of valgrind
	  --help to find the name of the loging option.

Signed-off-by: Matthieu Nottale <73d816bf5a7c98ca49eb19b3fa4036e0ae653e5f@gostai.com>


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

package com.threerings.ezgame.client {

import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Loader;

import flash.events.Event;

import flash.utils.Dictionary;

import mx.containers.Canvas;

import mx.core.Container;
import mx.core.IChildList;

import com.threerings.flash.MediaContainer;

import com.threerings.crowd.client.PlaceView;
import com.threerings.crowd.data.PlaceObject;
import com.threerings.crowd.util.CrowdContext;

import com.threerings.ezgame.data.EZGameConfig;
import com.threerings.ezgame.data.EZGameObject;

public class EZGamePanel extends Canvas
    implements PlaceView
{
    /** The game object backend. */
    public var backend :GameControlBackend;

    public function EZGamePanel (ctx :CrowdContext, ctrl :EZGameController)
    {
        _ctx = ctx;
        _ctrl = ctrl;
    }

    // from PlaceView
    public function willEnterPlace (plobj :PlaceObject) :void
    {
        var cfg :EZGameConfig = (_ctrl.getPlaceConfig() as EZGameConfig);

        _ezObj = (plobj as EZGameObject);
        backend = createBackend();

        _gameView = new GameContainer(cfg.getGameDefinition().getMediaPath(cfg.getGameId()));
        _gameView.percentWidth = 100;
        _gameView.percentHeight = 100;
        backend.setSharedEvents(
            Loader(_gameView.getMediaContainer().getMedia()).contentLoaderInfo.sharedEvents);
        backend.setContainer(_gameView);
        addChild(_gameView);
    }

    // from PlaceView
    public function didLeavePlace (plobj :PlaceObject) :void
    {
        _gameView.getMediaContainer().shutdown(true);
        removeChild(_gameView);

        backend.shutdown();
    }

    /**
     * Creates the backend object that will handle requests from user code.
     */
    protected function createBackend () :GameControlBackend
    {
        return new GameControlBackend(_ctx, _ezObj, _ctrl);
    }

    protected var _ctx :CrowdContext;
    protected var _ctrl :EZGameController;

    protected var _gameView :GameContainer;

    protected var _ezObj :EZGameObject;
}
}

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

package com.threerings.ezgame.client {

import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Loader;

import flash.events.Event;

import flash.utils.Dictionary;

import mx.containers.Canvas;

import mx.core.Container;
import mx.core.IChildList;

import com.threerings.flash.MediaContainer;

import com.threerings.crowd.client.PlaceView;
import com.threerings.crowd.data.PlaceObject;
import com.threerings.crowd.util.CrowdContext;

import com.threerings.ezgame.data.EZGameConfig;
import com.threerings.ezgame.data.EZGameObject;

public class EZGamePanel extends Canvas
    implements PlaceView
{
    /** The game object backend. */
    public var backend :GameControlBackend;

    public function EZGamePanel (ctx :CrowdContext, ctrl :EZGameController)
    {
        _ctx = ctx;
        _ctrl = ctrl;
    }

    // from PlaceView
    public function willEnterPlace (plobj :PlaceObject) :void
    {
        var cfg :EZGameConfig = (_ctrl.getPlaceConfig() as EZGameConfig);

        _ezObj = (plobj as EZGameObject);
        backend = createBackend();

        _gameView = new GameContainer(cfg.getGameDefinition().getMediaPath(cfg.getGameId()));
        configureGameView(_gameView);
        backend.setSharedEvents(
            Loader(_gameView.getMediaContainer().getMedia()).contentLoaderInfo.sharedEvents);
        backend.setContainer(_gameView);
        addChild(_gameView);
    }

    // from PlaceView
    public function didLeavePlace (plobj :PlaceObject) :void
    {
        _gameView.getMediaContainer().shutdown(true);
        removeChild(_gameView);

        backend.shutdown();
    }

    /**
     * Creates the backend object that will handle requests from user code.
     */
    protected function createBackend () :GameControlBackend
    {
        return new GameControlBackend(_ctx, _ezObj, _ctrl);
    }

    protected function configureGameView (view :GameContainer) :void
    {
        view.percentWidth = 100;
        view.percentHeight = 100;
    }

    protected var _ctx :CrowdContext;
    protected var _ctrl :EZGameController;
    protected var _gameView :GameContainer;
    protected var _ezObj :EZGameObject;
}
}

Allow our derived class to override our width/height configuration.

git-svn-id: a3e1eb16dde062992de22c830ed8045c8013209a@460 c613c5cb-e716-0410-b11b-feb51c14d237


/**
  * LzInputTextSprite.as
  *
  * @copyright Copyright 2001-2008 Laszlo Systems, Inc.  All Rights Reserved.
  *            Use is subject to license terms.
  *
  * @topic Kernel
  * @subtopic AS2
  */

/**
  * @shortdesc Used for input text.
  *
  */
class LzInputTextSprite extends LzTextSprite {

    #passthrough (toplevel:true) {
        import flash.display.*;
        import flash.events.*;
        import flash.text.*;
    }#

    #passthrough  {

    function LzInputTextSprite (newowner = null, args = null) {
        super(newowner);
    }

    var __handlelostFocusdel;
    var enabled = true;
    var focusable = true;
    var hasFocus = false;
    var scroll = 0;

    override public function __initTextProperties (args:Object) {
        super.__initTextProperties(args);
        // We do not support html in input fields.
        if (this.enabled) {
            textfield.type = TextFieldType.INPUT;
        } else {
            textfield.type = TextFieldType.DYNAMIC;
        }

        /*
          TODO [hqm 2008-01]
          these handlers need to be implemented via Flash native event listenters:

          focusIn , focusOut

          change -- dispatched after text input is modified

          textInput  -- dispatched before the content is modified
                        Do we need to use this for intercepting when we have
                        a pattern restriction on input?

        */

        textfield.addEventListener(Event.CHANGE        , __onChanged);
        //textfield.addEventListener(TextEvent.TEXT_INPUT, __onTextInput);
        textfield.addEventListener(FocusEvent.FOCUS_IN , __gotFocus);
        textfield.addEventListener(FocusEvent.FOCUS_OUT, __lostFocus);

        this.hasFocus = false;

    }

    /**
     * @access private
     */
    public function gotFocus ( ){
        //Debug.write('LzInputTextSprite.__handleOnFocus');
        if ( this.hasFocus ) { return; }
        this.select();
        this.hasFocus = true;
    }

    function select (  ){
        textfield.setSelection(0, textfield.text.length);

    }

    // XXXX selectionBeginIndex    property

    function deselect (  ){
        textfield.setSelection(0,0);
    }

    /**
     * @access private
     */
    function gotBlur (  ){
        //Debug.write('LzInputTextSprite.__handleOnBlur');
        this.hasFocus = false;
        this.deselect();
    }

    /**
     * TODO [hqm 2008-01] I have no idea whether this comment
     * still applies:
     * Register for update on every frame when the text field gets the focus.
     * Set the behavior of the enter key depending on whether the field is
     * multiline or not.
     *
     * @access private
     */
    function __gotFocus ( event:Event ){
        // scroll text fields horizontally back to start
        if (owner) owner.inputtextevent('onfocus');
    }

    /**
     * Register to be called when the text field is modified. Convert this
     * into a LFC ontext event.
     * @access private
     */
    function __onChanged (event:Event ){
        if (owner) owner.inputtextevent('onchange', this.text);
    }

    /**
     * @access private
     * TODO [hqm 2008-01] Does we still need this workaround???
     */
    function __lostFocus (event:Event){
        trace('lost focus', event.target);
        //if (this['__handlelostFocusdel'] == null) this.__handlelostFocusdel = new LzDelegate(this, "__handlelostFocus");
        //lz.Idle.callOnIdle(this.__handlelostFocusdel);
    }

    /**
     * TODO [hqm 2008-01] Does this comment still apply? Do we still need this workaround???
     *
     * must be called after an idle event to prevent the selection from being
     * cleared prematurely, e.g. before a button click.  If the selection is
     * cleared, the button doesn't send mouse events.
     * @access private
     */
    function __handlelostFocus (evt ){
        if (owner == lz.Focus.getFocus()) {
            lz.Focus.clearFocus();
            if (owner) owner.inputtextevent('onblur');
        }
    }

    /**
     * Retrieves the contents of the text field for use by a datapath. See
     * LzDatapath.updateData for more on this.
     * @access protected
     */
    function updateData (){
        return textfield.text;
    }

    /**
     * Sets whether user can modify input text field
     * @param Boolean enabled: true if the text field can be edited
     */
    function setEnabled (enabled){
        this.enabled = enabled;
        if (enabled) {
            textfield.type = 'input';
        } else {
            textfield.type = 'dynamic';
        }
    }

    /**
     * Set the html flag on this text view
     */
    function setHTML (htmlp) {
        // TODO [hqm 2008-10] what do we do here?
    }

    override public function getTextfieldHeight ( ){
        return this.textfield.height;
    }

    /**
    * If a mouse event occurs in an input text field, find the focused view
    * TODO: implement
    */
    static function findSelection(){
        return null;
    }

    }#  // #passthrough

} // End of LzInputTextSprite

/**
  * LzInputTextSprite.as
  *
  * @copyright Copyright 2001-2008 Laszlo Systems, Inc.  All Rights Reserved.
  *            Use is subject to license terms.
  *
  * @topic Kernel
  * @subtopic AS2
  */

/**
  * @shortdesc Used for input text.
  *
  */
class LzInputTextSprite extends LzTextSprite {

    #passthrough (toplevel:true) {
        import flash.display.*;
        import flash.events.*;
        import flash.text.*;
    }#

    #passthrough  {

    function LzInputTextSprite (newowner = null, args = null) {
        super(newowner);
    }

    var __handlelostFocusdel;
    var enabled = true;
    var focusable = true;
    var hasFocus = false;
    var scroll = 0;

    override public function __initTextProperties (args:Object) {
        super.__initTextProperties(args);
        // We do not support html in input fields.
        if (this.enabled) {
            textfield.type = TextFieldType.INPUT;
        } else {
            textfield.type = TextFieldType.DYNAMIC;
        }

        /*
          TODO [hqm 2008-01]
          these handlers need to be implemented via Flash native event listenters:

          focusIn , focusOut

          change -- dispatched after text input is modified

          textInput  -- dispatched before the content is modified
                        Do we need to use this for intercepting when we have
                        a pattern restriction on input?

        */

        textfield.addEventListener(Event.CHANGE        , __onChanged);
        //textfield.addEventListener(TextEvent.TEXT_INPUT, __onTextInput);
        textfield.addEventListener(FocusEvent.FOCUS_IN , __gotFocus);
        textfield.addEventListener(FocusEvent.FOCUS_OUT, __lostFocus);

        this.hasFocus = false;

    }

    /**
     * @access private
     */
    public function gotFocus ( ){
        //Debug.write('LzInputTextSprite.__handleOnFocus');
        if ( this.hasFocus ) { return; }
        this.select();
        this.hasFocus = true;
    }

    function select (  ){
        textfield.setSelection(0, textfield.text.length);

    }

    // XXXX selectionBeginIndex    property

    function deselect (  ){
        textfield.setSelection(0,0);
    }

    /**
     * @access private
     */
    function gotBlur (  ){
        //Debug.write('LzInputTextSprite.__handleOnBlur');
        this.hasFocus = false;
        this.deselect();
    }

    /**
     * TODO [hqm 2008-01] I have no idea whether this comment
     * still applies:
     * Register for update on every frame when the text field gets the focus.
     * Set the behavior of the enter key depending on whether the field is
     * multiline or not.
     *
     * @access private
     */
    function __gotFocus ( event:Event ){
        // scroll text fields horizontally back to start
        if (owner) owner.inputtextevent('onfocus');
    }

    /**
     * Register to be called when the text field is modified. Convert this
     * into a LFC ontext event.
     * @access private
     */
    function __onChanged (event:Event ){
        if (owner) owner.inputtextevent('onchange', this.text);
    }

    /**
     * @access private
     * TODO [hqm 2008-01] Does we still need this workaround???
     */
    function __lostFocus (event:Event){
        trace('lost focus', event.target);
        //if (this['__handlelostFocusdel'] == null) this.__handlelostFocusdel = new LzDelegate(this, "__handlelostFocus");
        //lz.Idle.callOnIdle(this.__handlelostFocusdel);
    }

    /**
     * TODO [hqm 2008-01] Does this comment still apply? Do we still need this workaround???
     *
     * must be called after an idle event to prevent the selection from being
     * cleared prematurely, e.g. before a button click.  If the selection is
     * cleared, the button doesn't send mouse events.
     * @access private
     */
    function __handlelostFocus (evt ){
        if (owner == lz.Focus.getFocus()) {
            lz.Focus.clearFocus();
            if (owner) owner.inputtextevent('onblur');
        }
    }

    /**
     * Get the current text for this inputtext-sprite.
     * @protected
     */
    override public function getText():String {
            return textfield.text;
    }

    /**
     * Retrieves the contents of the text field for use by a datapath. See
     * LzDatapath.updateData for more on this.
     * @access protected
     */
    function updateData (){
        return textfield.text;
    }

    /**
     * Sets whether user can modify input text field
     * @param Boolean enabled: true if the text field can be edited
     */
    function setEnabled (enabled){
        this.enabled = enabled;
        if (enabled) {
            textfield.type = 'input';
        } else {
            textfield.type = 'dynamic';
        }
    }

    /**
     * Set the html flag on this text view
     */
    function setHTML (htmlp) {
        // TODO [hqm 2008-10] what do we do here?
    }

    override public function getTextfieldHeight ( ){
        return this.textfield.height;
    }

    /**
    * If a mouse event occurs in an input text field, find the focused view
    * TODO: implement
    */
    static function findSelection(){
        return null;
    }

    }#  // #passthrough

} // End of LzInputTextSprite

Change 20080601-bargull-EDo by bargull@dell--p4--2-53 on 2008-06-01 02:15:32
    in /home/Admin/src/svn/openlaszlo/trunk
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: return current text for inputtext-sprite

New Features:

Bugs Fixed: LPP-6079

Technical Reviewer: hminsky
QA Reviewer: (pending)
Doc Reviewer: (pending)

Documentation:

Release Notes:

Details:
Just return the flash textfield's text. That way it's consistent across all runtimes.

Tests:

git-svn-id: d62bde4b5aa582fdf07c8d403e53e0399a7ed285@9415 fa20e4f9-1d0a-0410-b5f3-dc9c16b8b17c


package com.axis.http {
  import com.adobe.crypto.MD5;

  import com.axis.Logger;
  import com.axis.rtspclient.GUID;

  import flash.net.Socket;

  import mx.utils.Base64Encoder;

  public class auth {

    public static function basic(user:String, pass:String):String {
      var b64:Base64Encoder = new Base64Encoder();
      b64.insertNewLines = false;
      b64.encode(user + ':' + pass);
      return 'Basic ' + b64.toString();
    }

    public static function digest(
      user:String,
      pass:String,
      httpmethod:String,
      realm:String,
      uri:String,
      qop:String,
      nonce:String,
      nc:uint
    ):String {
      /* NOTE: Unsupported: md5-sess and auth-int */

      if (qop && 'auth' !== qop) {
        Logger.log('unsupported quality of protection: ' + qop);
        return "";
      }

      var ha1:String = MD5.hash(user + ':' + realm + ':' + pass);
      var ha2:String = MD5.hash(httpmethod + ':' + uri);
      var cnonce:String = MD5.hash(GUID.create());

      var hashme:String = qop ?
        (ha1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2) :
        (ha1 + ':' + nonce + ':' + ha2)
      var resp:String = MD5.hash(hashme);

      return 'Digest ' +
        'username="' + user + '", ' +
        'realm="' + realm + '", ' +
        'nonce="' + nonce + '", ' +
        'uri="' + uri + '", ' +
        'nc="' + nc + '", ' +
        (qop ? ('qop="' + qop + '", ') : '') +
        (qop ? ('cnonce="' + cnonce + '", ') : '') +
        'response="' + resp + '"'
        ;
    }

    public static function nextMethod(current:String, authOpts:Object):String {
      switch (current) {
        case 'none':
          /* No authorization attempt yet, try with the best method supported by server */
          if (authOpts.digestRealm)
            return 'digest';
          else if (authOpts.basicRealm)
            return 'basic';
          break;

        case 'digest':
          /* Weird to get unauthorized here unless credentials are invalid.
             On the off-chance of server-bug, try basic aswell */
          if (authOpts.basicRealm)
            return 'basic';

        case 'basic':
          /* If we failed with basic, we're done. Credentials are invalid. */
      }

      /* Getting the same method as passed as current should be considered an error */
      return current;
    }

    public static function authorizationHeader(
      method:String,
      authState:String,
      authOpts:Object,
      urlParsed:Object,
      digestNC:uint):String {

      var content:String = '';
      switch (authState) {
        case "basic":
          content = basic(urlParsed.user, urlParsed.pass);
          break;

        case "digest":
          content = digest(
            urlParsed.user,
            urlParsed.pass,
            method,
            authOpts.digestRealm,
            urlParsed.urlpath,
            authOpts.qop,
            authOpts.nonce,
            digestNC
          );
          break;

        default:
        case "none":
          return "";
      }

      return "Authorization: " + content + "\r\n"
    }
  }
}

package com.axis.http {
  import com.adobe.crypto.MD5;

  import com.axis.Logger;
  import com.axis.rtspclient.GUID;

  import flash.net.Socket;

  import mx.utils.Base64Encoder;

  public class auth {

    public static function basic(user:String, pass:String):String {
      var b64:Base64Encoder = new Base64Encoder();
      b64.insertNewLines = false;
      b64.encode(user + ':' + pass);
      return 'Basic ' + b64.toString();
    }

    public static function digest(
      user:String,
      pass:String,
      httpmethod:String,
      realm:String,
      uri:String,
      qop:String,
      nonce:String,
      nc:uint
    ):String {
      /* NOTE: Unsupported: md5-sess and auth-int */

      if (qop && 'auth' !== qop) {
        Logger.log('unsupported quality of protection: ' + qop);
        return "";
      }

      var ha1:String = MD5.hash(user + ':' + realm + ':' + pass);
      var ha2:String = MD5.hash(httpmethod + ':' + uri);
      var cnonce:String = MD5.hash(GUID.create());

      var hashme:String = qop ?
        (ha1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2) :
        (ha1 + ':' + nonce + ':' + ha2)
      var resp:String = MD5.hash(hashme);

      return 'Digest ' +
        'username="' + user + '", ' +
        'realm="' + realm + '", ' +
        'nonce="' + nonce + '", ' +
        'uri="' + uri + '", ' +
        'nc="' + nc + '", ' +
        (qop ? ('qop="' + qop + '", ') : '') +
        (qop ? ('cnonce="' + cnonce + '", ') : '') +
        'response="' + resp + '"'
        ;
    }

    public static function nextMethod(current:String, authOpts:Object):String {
      switch (current) {
        case 'none':
          /* No authorization attempt yet, try with the best method supported by server */
          if (authOpts.digestRealm)
            return 'digest';
          else if (authOpts.hasOwnProperty('basicRealm'))
            return 'basic';
          break;

        case 'digest':
          /* Weird to get unauthorized here unless credentials are invalid.
             On the off-chance of server-bug, try basic aswell */
          if (authOpts.basicRealm)
            return 'basic';

        case 'basic':
          /* If we failed with basic, we're done. Credentials are invalid. */
      }

      /* Getting the same method as passed as current should be considered an error */
      return current;
    }

    public static function authorizationHeader(
      method:String,
      authState:String,
      authOpts:Object,
      urlParsed:Object,
      digestNC:uint):String {

      var content:String = '';
      switch (authState) {
        case "basic":
          content = basic(urlParsed.user, urlParsed.pass);
          break;

        case "digest":
          content = digest(
            urlParsed.user,
            urlParsed.pass,
            method,
            authOpts.digestRealm,
            urlParsed.urlpath,
            authOpts.qop,
            authOpts.nonce,
            digestNC
          );
          break;

        default:
        case "none":
          return "";
      }

      return "Authorization: " + content + "\r\n"
    }
  }
}

Check that property exist, not value (might be empty string)


package dolly {
import dolly.core.dolly_internal;
import dolly.data.ClassLevelCloneable;
import dolly.data.ClassLevelCopyableCloneable;
import dolly.data.PropertyLevelCloneable;

import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;
import org.flexunit.asserts.assertEquals;
import org.flexunit.asserts.assertNotNull;
import org.flexunit.asserts.assertNull;

use namespace dolly_internal;

public class ClonerTest {

	private var classLevelCloneable:ClassLevelCloneable;
	private var classLevelCloneableType:Type;

	private var classLevelCopyableCloneable:ClassLevelCopyableCloneable;
	private var classLevelCopyableCloneableType:Type;

	private var propertyLevelCloneable:PropertyLevelCloneable;
	private var propertyLevelCloneableType:Type;

	[Before]
	public function before():void {
		classLevelCloneable = new ClassLevelCloneable();
		classLevelCloneable.property1 = "value 1";
		classLevelCloneable.property2 = "value 2";
		classLevelCloneable.property3 = "value 3";
		classLevelCloneable.writableField = "value 4";
		classLevelCloneableType = Type.forInstance(classLevelCloneable);

		classLevelCopyableCloneable = new ClassLevelCopyableCloneable();
		classLevelCopyableCloneable.property1 = "value 1";
		classLevelCopyableCloneable.property2 = "value 2";
		classLevelCopyableCloneable.property3 = "value 3";
		classLevelCopyableCloneable.writableField = "value 4";
		classLevelCopyableCloneableType = Type.forInstance(classLevelCopyableCloneable);

		propertyLevelCloneable = new PropertyLevelCloneable();
		propertyLevelCloneable.property1 = "value 1";
		propertyLevelCloneable.property2 = "value 2";
		propertyLevelCloneable.property3 = "value 3";
		propertyLevelCloneable.writableField = "value 4";

		propertyLevelCloneableType = Type.forInstance(propertyLevelCloneable);
	}

	[After]
	public function after():void {
		classLevelCloneable = null;
		classLevelCloneableType = null;

		classLevelCopyableCloneable = null;
		classLevelCopyableCloneableType = null;

		propertyLevelCloneable = null;
		propertyLevelCloneableType = null;
	}

	[Test]
	public function testGetCloneableFieldsForType():void {
		var cloneableFields:Vector.<Field> = Cloner.getCloneableFieldsForType(classLevelCloneableType);

		assertNotNull(cloneableFields);
		assertEquals(4, cloneableFields.length);

		cloneableFields = Cloner.getCloneableFieldsForType(classLevelCloneableType);
		assertNotNull(cloneableFields);
		assertEquals(4, cloneableFields.length);

		cloneableFields = Cloner.getCloneableFieldsForType(propertyLevelCloneableType);

		assertNotNull(cloneableFields);
		assertEquals(3, cloneableFields.length);
	}

	[Test]
	public function testCloneWithClassLevelMetadata():void {
		const clone:ClassLevelCloneable = Cloner.clone(classLevelCloneable) as ClassLevelCloneable;

		assertNotNull(clone);
		assertNotNull(clone.property1);
		assertEquals(clone.property1, classLevelCloneable.property1);
		assertNotNull(clone.property2);
		assertEquals(clone.property2, classLevelCloneable.property2);
		assertNotNull(clone.property3);
		assertEquals(clone.property3, classLevelCloneable.property3);
		assertNotNull(clone.writableField);
		assertEquals(clone.writableField, classLevelCloneable.writableField);
	}

	[Test]
	public function testCloneWithPropertyLevelMetadata():void {
		const clone:PropertyLevelCloneable = Cloner.clone(
				propertyLevelCloneable
		) as PropertyLevelCloneable;

		assertNotNull(clone);
		assertNull(clone.property1);
		assertNotNull(clone.property2);
		assertEquals(clone.property2, propertyLevelCloneable.property2);
		assertNotNull(clone.property3);
		assertEquals(clone.property3, propertyLevelCloneable.property3);
		assertNotNull(clone.writableField);
		assertEquals(clone.writableField, propertyLevelCloneable.writableField);
	}
}
}

package dolly {
import dolly.core.dolly_internal;
import dolly.data.ClassLevelCloneable;
import dolly.data.ClassLevelCopyableCloneable;
import dolly.data.PropertyLevelCloneable;
import dolly.data.PropertyLevelCopyableCloneable;

import org.as3commons.reflect.Field;
import org.as3commons.reflect.Type;
import org.flexunit.asserts.assertEquals;
import org.flexunit.asserts.assertNotNull;
import org.flexunit.asserts.assertNull;

use namespace dolly_internal;

public class ClonerTest {

	private var classLevelCloneable:ClassLevelCloneable;
	private var classLevelCloneableType:Type;

	private var classLevelCopyableCloneable:ClassLevelCopyableCloneable;
	private var classLevelCopyableCloneableType:Type;

	private var propertyLevelCloneable:PropertyLevelCloneable;
	private var propertyLevelCloneableType:Type;

	private var propertyLevelCopyableCloneable:PropertyLevelCopyableCloneable;
	private var propertyLevelCopyableCloneableType:Type;

	[Before]
	public function before():void {
		classLevelCloneable = new ClassLevelCloneable();
		classLevelCloneable.property1 = "value 1";
		classLevelCloneable.property2 = "value 2";
		classLevelCloneable.property3 = "value 3";
		classLevelCloneable.writableField = "value 4";
		classLevelCloneableType = Type.forInstance(classLevelCloneable);

		classLevelCopyableCloneable = new ClassLevelCopyableCloneable();
		classLevelCopyableCloneable.property1 = "value 1";
		classLevelCopyableCloneable.property2 = "value 2";
		classLevelCopyableCloneable.property3 = "value 3";
		classLevelCopyableCloneable.writableField = "value 4";
		classLevelCopyableCloneableType = Type.forInstance(classLevelCopyableCloneable);

		propertyLevelCloneable = new PropertyLevelCloneable();
		propertyLevelCloneable.property1 = "value 1";
		propertyLevelCloneable.property2 = "value 2";
		propertyLevelCloneable.property3 = "value 3";
		propertyLevelCloneable.writableField = "value 4";
		propertyLevelCloneableType = Type.forInstance(propertyLevelCloneable);

		propertyLevelCopyableCloneable = new PropertyLevelCopyableCloneable();
		propertyLevelCopyableCloneable.property1 = "value 1";
		propertyLevelCopyableCloneable.property2 = "value 2";
		propertyLevelCopyableCloneable.property3 = "value 3";
		propertyLevelCopyableCloneable.writableField = "value 4";
		propertyLevelCopyableCloneableType = Type.forInstance(propertyLevelCopyableCloneable);
	}

	[After]
	public function after():void {
		classLevelCloneable = null;
		classLevelCloneableType = null;

		classLevelCopyableCloneable = null;
		classLevelCopyableCloneableType = null;

		propertyLevelCloneable = null;
		propertyLevelCloneableType = null;

		propertyLevelCopyableCloneable = null;
		propertyLevelCopyableCloneableType = null;
	}

	[Test]
	public function testGetCloneableFieldsForType():void {
		var cloneableFields:Vector.<Field> = Cloner.getCloneableFieldsForType(classLevelCloneableType);
		assertNotNull(cloneableFields);
		assertEquals(4, cloneableFields.length);

		cloneableFields = Cloner.getCloneableFieldsForType(classLevelCloneableType);
		assertNotNull(cloneableFields);
		assertEquals(4, cloneableFields.length);

		cloneableFields = Cloner.getCloneableFieldsForType(propertyLevelCloneableType);
		assertNotNull(cloneableFields);
		assertEquals(3, cloneableFields.length);

		cloneableFields = Cloner.getCloneableFieldsForType(propertyLevelCopyableCloneableType);
		assertNotNull(cloneableFields);
		assertEquals(4, cloneableFields.length);
	}

	[Test]
	public function testCloneWithClassLevelMetadata():void {
		const clone1:ClassLevelCloneable = Cloner.clone(classLevelCloneable);
		assertNotNull(clone1);
		assertNotNull(clone1.property1);
		assertEquals(clone1.property1, classLevelCloneable.property1);
		assertNotNull(clone1.property2);
		assertEquals(clone1.property2, classLevelCloneable.property2);
		assertNotNull(clone1.property3);
		assertEquals(clone1.property3, classLevelCloneable.property3);
		assertNotNull(clone1.writableField);
		assertEquals(clone1.writableField, classLevelCloneable.writableField);

		const clone2:ClassLevelCopyableCloneable = Cloner.clone(classLevelCopyableCloneable);
		assertNotNull(clone2);
		assertNotNull(clone2.property1);
		assertEquals(clone2.property1, classLevelCloneable.property1);
		assertNotNull(clone2.property2);
		assertEquals(clone2.property2, classLevelCloneable.property2);
		assertNotNull(clone2.property3);
		assertEquals(clone2.property3, classLevelCloneable.property3);
		assertNotNull(clone2.writableField);
		assertEquals(clone2.writableField, classLevelCloneable.writableField);
	}

	[Test]
	public function testCloneWithPropertyLevelMetadata():void {
		const clone1:PropertyLevelCloneable = Cloner.clone(propertyLevelCloneable);
		assertNotNull(clone1);
		assertNull(clone1.property1);
		assertNotNull(clone1.property2);
		assertEquals(clone1.property2, propertyLevelCloneable.property2);
		assertNotNull(clone1.property3);
		assertEquals(clone1.property3, propertyLevelCloneable.property3);
		assertNotNull(clone1.writableField);
		assertEquals(clone1.writableField, propertyLevelCloneable.writableField);

		const clone2:PropertyLevelCopyableCloneable = Cloner.clone(propertyLevelCopyableCloneable);
		assertNotNull(clone2);
		assertNotNull(clone2.property1);
		assertEquals(clone2.property1, propertyLevelCloneable.property1);
		assertNotNull(clone2.property2);
		assertEquals(clone2.property2, propertyLevelCloneable.property2);
		assertNotNull(clone2.property3);
		assertEquals(clone2.property3, propertyLevelCloneable.property3);
		assertNotNull(clone2.writableField);
		assertEquals(clone2.writableField, propertyLevelCloneable.writableField);
	}
}
}

Test classes ClassLevelCopyableCloneable and PropertyLevelCopyableCloneable in ClonerTest.


add CubeGeometry.fromBoundingBox()

add CubeGeometry.fromBoundingBox()


package aerys.minko.render.shader
{
	import aerys.minko.render.shader.compiler.graph.nodes.leaf.BindableConstant;
	import aerys.minko.render.shader.compiler.graph.nodes.leaf.BindableSampler;
	import aerys.minko.type.binding.DataBindings;

	/**
	 * The wrapper used to expose scene/mesh data bindings in ActionScript shaders.
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public final class ShaderDataBindings
	{
		private var _dataBindings	: DataBindings	= null;
		private var _signature		: Signature		= null;
		private var _signatureFlags	: uint			= 0;

		public function ShaderDataBindings(bindings			: DataBindings,
										   signature		: Signature,
										   signatureFlags	: uint)
		{
			_dataBindings = bindings;
			_signature = signature;
			_signatureFlags = signatureFlags;
		}

		public function getParameter(name : String, size : uint) : SFloat
		{
			return new SFloat(new BindableConstant(name, size));
		}

		public function getTextureParameter(bindingName	: String,
											filter		: uint = 1,
											mipmap		: uint = 0,
											wrapping	: uint = 1,
											dimension	: uint = 0) : SFloat
		{
			return new SFloat(
				new BindableSampler(bindingName, filter, mipmap, wrapping, dimension)
			);
		}

		public function propertyExists(propertyName : String) : Boolean
		{
			var value 	: Boolean	= _dataBindings.propertyExists(propertyName);

			_signature.update(
				propertyName,
				value,
				Signature.OPERATION_EXISTS | _signatureFlags
			);

			return value;
		}

		public function getConstant(propertyName : String,
									defaultValue : Object	= null) : *
		{
			if (!_dataBindings.propertyExists(propertyName))
			{
				if (defaultValue === null)
				{
					throw new Error(
						"The property '" + propertyName
						+ "' does not exist and no default value was provided."
					);
				}

				_signature.update(
					propertyName,
					false,
					Signature.OPERATION_EXISTS | _signatureFlags
				);

				return defaultValue;
			}

			var value : Object = _dataBindings.getProperty(propertyName);

			_signature.update(
				propertyName,
				value,
				Signature.OPERATION_GET | _signatureFlags
			);

			return value;
		}
	}
}

package aerys.minko.render.shader
{
	import aerys.minko.render.resource.texture.TextureResource;
	import aerys.minko.render.shader.compiler.Serializer;
	import aerys.minko.render.shader.compiler.graph.nodes.leaf.BindableConstant;
	import aerys.minko.render.shader.compiler.graph.nodes.leaf.BindableSampler;
	import aerys.minko.render.shader.compiler.graph.nodes.leaf.Constant;
	import aerys.minko.render.shader.compiler.graph.nodes.leaf.Sampler;
	import aerys.minko.type.binding.DataBindings;

	/**
	 * The wrapper used to expose scene/mesh data bindings in ActionScript shaders.
	 *
	 * @author Jean-Marc Le Roux
	 *
	 */
	public final class ShaderDataBindings
	{
		private var _dataBindings	: DataBindings	= null;
		private var _signature		: Signature		= null;
		private var _signatureFlags	: uint			= 0;

		public function ShaderDataBindings(bindings			: DataBindings,
										   signature		: Signature,
										   signatureFlags	: uint)
		{
			_dataBindings = bindings;
			_signature = signature;
			_signatureFlags = signatureFlags;
		}

		public function getParameter(name			: String,
									 size			: uint,
									 defaultValue	: Object = null) : SFloat
		{
			if (defaultValue != null && !propertyExists(name))
			{
				var constantValue : Vector.<Number> = new Vector.<Number>();
				Serializer.serializeKnownLength(defaultValue, constantValue, 0, size);
				return new SFloat(new Constant(constantValue));
			}

			return new SFloat(new BindableConstant(name, size));
		}

		public function getTextureParameter(bindingName		: String,
											filter			: uint				= 1,
											mipmap			: uint				= 0,
											wrapping		: uint				= 1,
											dimension		: uint				= 0,
											defaultValue	: TextureResource	= null) : SFloat
		{
			if (defaultValue != null && !propertyExists(bindingName))
				return new SFloat(new Sampler(defaultValue, filter, mipmap, wrapping, dimension));

			return new SFloat(
				new BindableSampler(bindingName, filter, mipmap, wrapping, dimension)
			);
		}

		public function propertyExists(propertyName : String) : Boolean
		{
			var value 	: Boolean	= _dataBindings.propertyExists(propertyName);

			_signature.update(
				propertyName,
				value,
				Signature.OPERATION_EXISTS | _signatureFlags
			);

			return value;
		}

		public function getConstant(propertyName : String,
									defaultValue : Object	= null) : *
		{
			if (!_dataBindings.propertyExists(propertyName))
			{
				if (defaultValue === null)
				{
					throw new Error(
						"The property '" + propertyName
						+ "' does not exist and no default value was provided."
					);
				}

				_signature.update(
					propertyName,
					false,
					Signature.OPERATION_EXISTS | _signatureFlags
				);

				return defaultValue;
			}

			var value : Object = _dataBindings.getProperty(propertyName);

			_signature.update(
				propertyName,
				value,
				Signature.OPERATION_GET | _signatureFlags
			);

			return value;
		}
	}
}

Add default values to shader parameters (#380)


////////////////////////////////////////////////////////////////////////////////
//
//  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 mx.styles
{
import mx.utils.ObjectUtil;

/**
 * Represents a dimension with an optional unit, to be used in css media queries.
 *
Valid units are:
 * no unit
 * px : pixel
 * in : inch
 * cm : centimeter
 * pt : point
 * dp :  device independent pixel ( 1 pix at about 160 DPI )
 *
 *  @langversion 3.0
 *  @playerversion AIR 3.0
 *  @productversion Flex 4.13
 */
public class CSSDimension
{
    /* device independent units */
    static public  const NO_UNIT: String = "";
    static public  const UNIT_INCH: String = "in";
    static public  const UNIT_CM: String = "cm";
    static public  const UNIT_PT: String = "pt";
    static public  const UNIT_DP: String = "dp";

    /* pixel units */
    static private  const UNIT_PX: String = "px";

    /* scale factor for device independent units */
    static private  const INCH_PER_INCH: Number = 1.0;
    static private  const CM_PER_INCH: Number = 2.54;
    static private  const PT_PER_INCH: Number = 72;
    static private  const DP_PER_INCH: Number = 160;

    private var _value: Number;
    private var _unit: String;
    private var _pixelValue: int;

    /** Constructor
     *
     * @param value
     * @param refDPI
     * @param unit
     *
     */
    public function CSSDimension(value: Number, refDPI: Number, unit: String = NO_UNIT)
    {
        _value = value;
        _unit = unit;
        _pixelValue = computePixelValue(refDPI);
    }

    /** Dimension unit, as a string, or empty string if no unit
     *
     */
    public function get unit(): String
    {
        return _unit;
    }

    /** Dimension value as a number, without the unit
     */
    public function get value(): Number
    {
        return _value;
    }

    /**
     * Dimension converted to actual pixels, considering the current device DPI
     */
    public function get pixelValue(): Number
    {
        return _pixelValue;
    }

    /**
     *  Compares to another CSSDimension instance.
     *  Actual pixel values are used for comparison, so dimensions can have different units.
     *
     *  @param other another  CSSDimension instance
     *
     *  @return 0 if both dimensions are of equal value. rounding errors may occur due to conversion
     *  -1 if this is lower than other.
     *  1 if this is greater than other.
     *
     *  @langversion 3.0
     *  @playerversion AIR 3.0
     *  @productversion Flex 4.13
     */
    public function compareTo(other: CSSDimension): int
    {
        return ObjectUtil.numericCompare(_pixelValue, other.pixelValue);
    }

    /**
     * Printable string of the dimension
     * @return version as a string
     */
    public function toString(): String
    {
        return  _value.toString() + _unit;
    }

    /** @private converts a value with unit an actual pixel value, according to refDPI screen resolution
     * the formula is the following for physical units
     *   pixelValue = value * refDPI / unit_per_inch ;
     *   eg. 5in at 132 DPI =>  5 * 132 /1 =
     *   eg. 19cm at 132 DPI => 19 * 132 /2.54  =
     * */
    private function computePixelValue(refDPI: Number): int
    {
        switch (_unit) {
            // test device-independent units
            case UNIT_INCH:
                return _value * refDPI;
            case UNIT_DP:
                return _value * refDPI / DP_PER_INCH;
            case UNIT_CM:
                return _value * refDPI / CM_PER_INCH;
            case UNIT_PT:
                return _value * refDPI / PT_PER_INCH;
        }
        // else it's pixel unit
        return _value;
    }

}

}

////////////////////////////////////////////////////////////////////////////////
//
//  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 mx.styles
{
import mx.utils.ObjectUtil;

/**
 * Represents a dimension with an optional unit, to be used in css media queries.
 *
Valid units are:
 * no unit
 * px : pixel
 * in : inch
 * cm : centimeter
 * pt : point
 * dp :  device independent pixel ( 1 pix at about 160 DPI )
 *

 *
 *  @langversion 3.0
 *  @playerversion AIR 3.0
 *  @productversion Flex 4.13
 */
public class CSSDimension
{
    /* device independent units */
    static public  const NO_UNIT: String = "";
    static public  const UNIT_INCH: String = "in";
    static public  const UNIT_CM: String = "cm";
    static public  const UNIT_PT: String = "pt";
    static public  const UNIT_DP: String = "dp";

    /* pixel units */
    static private  const UNIT_PX: String = "px";

    /* scale factor for device independent units */
    static private  const INCH_PER_INCH: Number = 1.0;
    static private  const CM_PER_INCH: Number = 2.54;
    static private  const PT_PER_INCH: Number = 72;
    static private  const DP_PER_INCH: Number = 160;

    private var _value: Number;
    private var _unit: String;
    private var _pixelValue: int;

    /** Constructor
     *
     * @param value
     * @param refDPI
     * @param unit
     *
     */
    public function CSSDimension(value: Number, refDPI: Number, unit: String = NO_UNIT)
    {
        _value = value;
        _unit = unit;
        _pixelValue = computePixelValue(refDPI);
    }

    /** Dimension unit, as a string, or empty string if no unit
     *
     */
    public function get unit(): String
    {
        return _unit;
    }

    /** Dimension value as a number, without the unit
     */
    public function get value(): Number
    {
        return _value;
    }

    /**
     * Dimension converted to actual pixels, considering the current device DPI
     */
    public function get pixelValue(): Number
    {
        return _pixelValue;
    }

    /**
     *  Compares to another CSSDimension instance.
     *  Actual pixel values are used for comparison, so dimensions can have different units.
     *
     *  @param other another  CSSDimension instance
     *
     *  @return 0 if both dimensions are of equal value. rounding errors may occur due to conversion
     *  -1 if this is lower than other.
     *  1 if this is greater than other.
     *
     *  @langversion 3.0
     *  @playerversion AIR 3.0
     *  @productversion Flex 4.13
     */
    public function compareTo(other: CSSDimension): int
    {
        return ObjectUtil.numericCompare(_pixelValue, other.pixelValue);
    }

    /**
     * Printable string of the dimension
     * @return version as a string
     */
    public function toString(): String
    {
        return  _value.toString() + _unit;
    }

    /** @private converts a value with unit an actual pixel value, according to refDPI screen resolution
     * the formula is the following for physical units
     *   pixelValue = value * refDPI / unit_per_inch ;
     *   eg. 5in at 132 DPI =>  5 * 132 /1 =
     *   eg. 19cm at 132 DPI => 19 * 132 /2.54  =
     * */
    private function computePixelValue(refDPI: Number): int
    {
        switch (_unit) {
            // test device-independent units
            case UNIT_INCH:
                return _value * refDPI;
            case UNIT_DP:
                return _value * refDPI / DP_PER_INCH;
            case UNIT_CM:
                return _value * refDPI / CM_PER_INCH;
            case UNIT_PT:
                return _value * refDPI / PT_PER_INCH;
        }
        // else it's pixel unit
        return _value;
    }

}

}

fix asdoc html

fix asdoc html


package htmlelements
{
	import flash.display.Sprite;
	import flash.events.*;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.media.Video;
	import flash.media.SoundTransform;
	import flash.utils.Timer;

	import FlashMediaElement;
	import HtmlMediaEvent;

	public class VideoElement extends Sprite implements IMediaElement
	{
		private var _currentUrl:String = "";
		private var _autoplay:Boolean = true;

		private var _connection:NetConnection;
		private var _stream:NetStream;
		private var _video:Video;
		private var _element:FlashMediaElement;
		private var _soundTransform;
		private var _oldVolume:Number = 1;

		// event values
		private var _duration:Number = 0;
		private var _framerate:Number;
		private var _isPaused:Boolean = true;
		private var _isEnded:Boolean = false;
		private var _volume:Number = 1;
		private var _isMuted:Boolean = false;

		private var _bytesLoaded:Number = 0;
		private var _bytesTotal:Number = 0;
		private var _bufferedTime:Number = 0;

		private var _videoWidth:Number = -1;
		private var _videoHeight:Number = -1;

		private var _timer:Timer;

		private var _isRTMP:Boolean = false;
		private var _isConnected:Boolean = false;
		private var _playWhenConnected:Boolean = false;
		private var _hasStartedPlaying:Boolean = false;

		public function get video():Video {
			return _video;
		}

		public function get videoHeight():Number {
			return _videoHeight;
		}

		public function get videoWidth():Number {
			return _videoWidth;
		}

		public function duration():Number {
			return _duration;
		}

		public function currentTime():Number {
			if (_stream != null) {
				return _stream.time;
			} else {
				return 0;
			}
		}

		// (1) load()
		// calls _connection.connect();
		// waits for NetConnection.Connect.Success
		// _stream gets created

		public function VideoElement(element:FlashMediaElement, autoplay:Boolean, timerRate:Number)
		{
			_element = element;
			_autoplay = autoplay;

			_video = new Video();
			addChild(_video);

			_connection = new NetConnection();
			_connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
			_connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			//_connection.connect(null);

			_timer = new Timer(timerRate);
			_timer.addEventListener("timer", timerHandler);

		}

		private function timerHandler(e:TimerEvent) {

			_bytesLoaded = _stream.bytesLoaded;
			_bytesTotal = _stream.bytesTotal;

			sendEvent(HtmlMediaEvent.TIMEUPDATE);

			trace("bytes", _bytesLoaded, _bytesTotal);

			if (_bytesLoaded < _bytesTotal)
				sendEvent(HtmlMediaEvent.PROGRESS);
		}

		// internal events
		private function netStatusHandler(event:NetStatusEvent):void {
			trace("netStatus", event.info.code);

			switch (event.info.code) {

				case "NetStream.Buffer.Empty":
				case "NetStream.Buffer.Full":
					_bytesLoaded = _stream.bytesLoaded;
					_bytesTotal = _stream.bytesTotal;

					sendEvent(HtmlMediaEvent.PROGRESS);
					break;

				case "NetConnection.Connect.Success":
					connectStream();
					break;
				case "NetStream.Play.StreamNotFound":
					trace("Unable to locate video");
					break;

				// STREAM
				case "NetStream.Play.Start":
					_isPaused = false;
					sendEvent(HtmlMediaEvent.CANPLAY);
					sendEvent(HtmlMediaEvent.PLAY);
					sendEvent(HtmlMediaEvent.PLAYING);
					_timer.start();
					break;

				case "NetStream.Seek.Notify":
					sendEvent(HtmlMediaEvent.SEEKED);
					break;

				case "NetStream.Pause.Notify":
					_isPaused = true;
					sendEvent(HtmlMediaEvent.PAUSE);
					break;

				case "NetStream.Play.Stop":
					_isPaused = false;
					_timer.stop();
					sendEvent(HtmlMediaEvent.ENDED);
					break;

			}
		}

		private function connectStream():void {
			trace("connectStream");
			_stream = new NetStream(_connection);

			// explicitly set the sound since it could have come before the connection was made
			_soundTransform = new SoundTransform(_volume);
			_stream.soundTransform = _soundTransform;

			_stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); // same event as connection
			_stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);

			var customClient:Object = new Object();
			customClient.onMetaData = onMetaDataHandler;
			_stream.client = customClient;

			_video.attachNetStream(_stream);

			_isConnected = true;

			if (_playWhenConnected && !_hasStartedPlaying) {
				play();
				_playWhenConnected = false;
			}

		}

		private function securityErrorHandler(event:SecurityErrorEvent):void {
			trace("securityErrorHandler: " + event);
		}

		private function asyncErrorHandler(event:AsyncErrorEvent):void {
			// ignore AsyncErrorEvent events.
		}

		private function onMetaDataHandler(info:Object):void {
			_duration = info.duration;
			_framerate = info.framerate;
			_videoWidth = info.width;
			_videoHeight = info.height;

			// set size?

			sendEvent(HtmlMediaEvent.LOADEDMETADATA);
		}

		// interface members
		public function setSrc(url:String):void {
			if (_isConnected && _stream) {
				// stop and restart
				_stream.pause();
			}

			_currentUrl = url;
			_isRTMP = !!_currentUrl.match(/^rtmp(s|t|e|te)?\:\/\//);
			_isConnected = false;
			_hasStartedPlaying = false;
		}

		public function load():void {
			// as far as I know there is no way to start downloading a file without playing it (preload="auto" in HTML5)
			// so this "load" just begins a Flash connection
			if (_isConnected && _stream) {
				_stream.pause();
			}
			_isConnected = false;

			if (_isRTMP) {
				_connection.connect(_currentUrl.replace(/\/[^\/]+$/,"/"));
			} else {
				_connection.connect(null);
			}
			// in a few moments the "NetConnection.Connect.Success" event will fire
			// and call createConnection which finishes the "load" sequence

			sendEvent(HtmlMediaEvent.LOADSTART);
		}

		public function play():void {

			if (!_hasStartedPlaying && !_isConnected) {
				_playWhenConnected = true;
				load();
				return;
			}

			if (_hasStartedPlaying) {
				if (_isPaused) {
					_stream.resume();
					_timer.start();
					_isPaused = false;
					sendEvent(HtmlMediaEvent.PLAY);
					sendEvent(HtmlMediaEvent.PLAYING);
				}
			} else {

				if (_isRTMP) {
					_stream.play(_currentUrl.split("/").pop());
				} else {
					_stream.play(_currentUrl);
				}
				_timer.start();
				_isPaused = false;
				sendEvent(HtmlMediaEvent.PLAY);
				sendEvent(HtmlMediaEvent.PLAYING);
				_hasStartedPlaying = true;
			}

		}

		public function pause():void {
			if (_stream == null)
				return;

			_stream.pause();
			_isPaused = true;
			_timer.stop();

			_isPaused = true;
			sendEvent(HtmlMediaEvent.PAUSE);
		}

		public function stop():void {
			if (_stream == null)
				return;

			_stream.close();
			_isPaused = false;
			_timer.stop();
			sendEvent(HtmlMediaEvent.STOP);
		}

		public function setCurrentTime(pos:Number):void {
			if (_stream == null)
				return;

			_stream.seek(pos);
			sendEvent(HtmlMediaEvent.TIMEUPDATE);
			sendEvent(HtmlMediaEvent.SEEKED);
		}

		public function setVolume(volume:Number):void {
			if (_stream != null) {
				_soundTransform = new SoundTransform(volume);
				_stream.soundTransform = _soundTransform;
			}

			_volume = volume;

			_isMuted = (_volume == 0);

			sendEvent(HtmlMediaEvent.VOLUMECHANGE);
		}

		public function setMuted(muted:Boolean):void {

			if (_isMuted == muted)
				return;

			if (muted) {
				_oldVolume = _stream.soundTransform.volume;
				setVolume(0);
			} else {
				setVolume(_oldVolume);
			}

			_isMuted = muted;
		}

		private function sendEvent(eventName:String) {

			// calculate this to mimic HTML5
			_bufferedTime = _bytesLoaded / _bytesTotal + _duration;

			// build JSON
			var values:String =
							"{duration:" + _duration +
							",framerate:" + _framerate +
							",currentTime:" + (_stream != null ? _stream.time : 0) +
							",muted:" + _isMuted +
							",paused:" + _isPaused +
							",ended:" + _isEnded +
							",volume:" + _volume +
							",src:\"" + _currentUrl + "\"" +
							",bytesTotal:" + _bytesTotal +
							",bufferedBytes:" + _bytesLoaded +
							",bufferedTime:" + _bufferedTime +
							",videoWidth:" + _videoWidth +
							",videoHeight:" + _videoHeight +
							"}";

			_element.sendEvent(eventName, values);
		}
	}
}

package htmlelements
{
	import flash.display.Sprite;
	import flash.events.*;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.media.Video;
	import flash.media.SoundTransform;
	import flash.utils.Timer;

	import FlashMediaElement;
	import HtmlMediaEvent;

	public class VideoElement extends Sprite implements IMediaElement
	{
		private var _currentUrl:String = "";
		private var _autoplay:Boolean = true;

		private var _connection:NetConnection;
		private var _stream:NetStream;
		private var _video:Video;
		private var _element:FlashMediaElement;
		private var _soundTransform;
		private var _oldVolume:Number = 1;

		// event values
		private var _duration:Number = 0;
		private var _framerate:Number;
		private var _isPaused:Boolean = true;
		private var _isEnded:Boolean = false;
		private var _volume:Number = 1;
		private var _isMuted:Boolean = false;

		private var _bytesLoaded:Number = 0;
		private var _bytesTotal:Number = 0;
		private var _bufferedTime:Number = 0;

		private var _videoWidth:Number = -1;
		private var _videoHeight:Number = -1;

		private var _timer:Timer;

		private var _isRTMP:Boolean = false;
		private var _isConnected:Boolean = false;
		private var _playWhenConnected:Boolean = false;
		private var _hasStartedPlaying:Boolean = false;

		public function get video():Video {
			return _video;
		}

		public function get videoHeight():Number {
			return _videoHeight;
		}

		public function get videoWidth():Number {
			return _videoWidth;
		}

		public function duration():Number {
			return _duration;
		}

		public function currentTime():Number {
			if (_stream != null) {
				return _stream.time;
			} else {
				return 0;
			}
		}

		// (1) load()
		// calls _connection.connect();
		// waits for NetConnection.Connect.Success
		// _stream gets created

		public function VideoElement(element:FlashMediaElement, autoplay:Boolean, timerRate:Number)
		{
			_element = element;
			_autoplay = autoplay;

			_video = new Video();
			addChild(_video);

			_connection = new NetConnection();
			_connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
			_connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			//_connection.connect(null);

			_timer = new Timer(timerRate);
			_timer.addEventListener("timer", timerHandler);

		}

		private function timerHandler(e:TimerEvent) {

			_bytesLoaded = _stream.bytesLoaded;
			_bytesTotal = _stream.bytesTotal;

			sendEvent(HtmlMediaEvent.TIMEUPDATE);

			trace("bytes", _bytesLoaded, _bytesTotal);

			if (_bytesLoaded < _bytesTotal)
				sendEvent(HtmlMediaEvent.PROGRESS);
		}

		// internal events
		private function netStatusHandler(event:NetStatusEvent):void {
			trace("netStatus", event.info.code);

			switch (event.info.code) {

				case "NetStream.Buffer.Empty":
					_isEnded ? sendEvent(HtmlMediaEvent.ENDED) : null;
					break;

				case "NetStream.Buffer.Full":
					_bytesLoaded = _stream.bytesLoaded;
					_bytesTotal = _stream.bytesTotal;

					sendEvent(HtmlMediaEvent.PROGRESS);
					break;

				case "NetConnection.Connect.Success":
					connectStream();
					break;
				case "NetStream.Play.StreamNotFound":
					trace("Unable to locate video");
					break;

				// STREAM
				case "NetStream.Play.Start":
					_isPaused = false;
					sendEvent(HtmlMediaEvent.CANPLAY);
					sendEvent(HtmlMediaEvent.PLAY);
					sendEvent(HtmlMediaEvent.PLAYING);
					_timer.start();
					break;

				case "NetStream.Seek.Notify":
					sendEvent(HtmlMediaEvent.SEEKED);
					break;

				case "NetStream.Pause.Notify":
					_isPaused = true;
					sendEvent(HtmlMediaEvent.PAUSE);
					break;

				case "NetStream.Play.Stop":
					_isEnded = true;
					_isPaused = false;
					_timer.stop();
					_bufferEmpty ? sendEvent(HtmlMediaEvent.ENDED) : null;
					break;

			}
		}

		private function connectStream():void {
			trace("connectStream");
			_stream = new NetStream(_connection);

			// explicitly set the sound since it could have come before the connection was made
			_soundTransform = new SoundTransform(_volume);
			_stream.soundTransform = _soundTransform;

			_stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); // same event as connection
			_stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);

			var customClient:Object = new Object();
			customClient.onMetaData = onMetaDataHandler;
			_stream.client = customClient;

			_video.attachNetStream(_stream);

			_isConnected = true;

			if (_playWhenConnected && !_hasStartedPlaying) {
				play();
				_playWhenConnected = false;
			}

		}

		private function securityErrorHandler(event:SecurityErrorEvent):void {
			trace("securityErrorHandler: " + event);
		}

		private function asyncErrorHandler(event:AsyncErrorEvent):void {
			// ignore AsyncErrorEvent events.
		}

		private function onMetaDataHandler(info:Object):void {
			_duration = info.duration;
			_framerate = info.framerate;
			_videoWidth = info.width;
			_videoHeight = info.height;

			// set size?

			sendEvent(HtmlMediaEvent.LOADEDMETADATA);
		}

		// interface members
		public function setSrc(url:String):void {
			if (_isConnected && _stream) {
				// stop and restart
				_stream.pause();
			}

			_currentUrl = url;
			_isRTMP = !!_currentUrl.match(/^rtmp(s|t|e|te)?\:\/\//);
			_isConnected = false;
			_hasStartedPlaying = false;
		}

		public function load():void {
			// as far as I know there is no way to start downloading a file without playing it (preload="auto" in HTML5)
			// so this "load" just begins a Flash connection
			if (_isConnected && _stream) {
				_stream.pause();
			}
			_isConnected = false;

			if (_isRTMP) {
				_connection.connect(_currentUrl.replace(/\/[^\/]+$/,"/"));
			} else {
				_connection.connect(null);
			}
			// in a few moments the "NetConnection.Connect.Success" event will fire
			// and call createConnection which finishes the "load" sequence

			sendEvent(HtmlMediaEvent.LOADSTART);
		}

		public function play():void {

			if (!_hasStartedPlaying && !_isConnected) {
				_playWhenConnected = true;
				load();
				return;
			}

			if (_hasStartedPlaying) {
				if (_isPaused) {
					_stream.resume();
					_timer.start();
					_isPaused = false;
					sendEvent(HtmlMediaEvent.PLAY);
					sendEvent(HtmlMediaEvent.PLAYING);
				}
			} else {

				if (_isRTMP) {
					_stream.play(_currentUrl.split("/").pop());
				} else {
					_stream.play(_currentUrl);
				}
				_timer.start();
				_isPaused = false;
				sendEvent(HtmlMediaEvent.PLAY);
				sendEvent(HtmlMediaEvent.PLAYING);
				_hasStartedPlaying = true;
			}

		}

		public function pause():void {
			if (_stream == null)
				return;

			_stream.pause();
			_isPaused = true;
			_timer.stop();

			_isPaused = true;
			sendEvent(HtmlMediaEvent.PAUSE);
		}

		public function stop():void {
			if (_stream == null)
				return;

			_stream.close();
			_isPaused = false;
			_timer.stop();
			sendEvent(HtmlMediaEvent.STOP);
		}

		public function setCurrentTime(pos:Number):void {
			if (_stream == null)
				return;

			_stream.seek(pos);
			sendEvent(HtmlMediaEvent.TIMEUPDATE);
			sendEvent(HtmlMediaEvent.SEEKED);
		}

		public function setVolume(volume:Number):void {
			if (_stream != null) {
				_soundTransform = new SoundTransform(volume);
				_stream.soundTransform = _soundTransform;
			}

			_volume = volume;

			_isMuted = (_volume == 0);

			sendEvent(HtmlMediaEvent.VOLUMECHANGE);
		}

		public function setMuted(muted:Boolean):void {

			if (_isMuted == muted)
				return;

			if (muted) {
				_oldVolume = _stream.soundTransform.volume;
				setVolume(0);
			} else {
				setVolume(_oldVolume);
			}

			_isMuted = muted;
		}

		private function sendEvent(eventName:String) {

			// calculate this to mimic HTML5
			_bufferedTime = _bytesLoaded / _bytesTotal + _duration;

			// build JSON
			var values:String =
							"{duration:" + _duration +
							",framerate:" + _framerate +
							",currentTime:" + (_stream != null ? _stream.time : 0) +
							",muted:" + _isMuted +
							",paused:" + _isPaused +
							",ended:" + _isEnded +
							",volume:" + _volume +
							",src:\"" + _currentUrl + "\"" +
							",bytesTotal:" + _bytesTotal +
							",bufferedBytes:" + _bytesLoaded +
							",bufferedTime:" + _bufferedTime +
							",videoWidth:" + _videoWidth +
							",videoHeight:" + _videoHeight +
							"}";

			_element.sendEvent(eventName, values);
		}
	}
}

fix for issue #49 - "ended" event firing before actual stream end