New Constants added for new messages and error code

SVN-Revision: 8804

--- flexclient/dag/Components/DAGConstants.as
+++ flexclient/dag/Components/DAGConstants.as
@@ -11,8 +11,7 @@
 		public static  var DELETE_FROM_VIEW:String="DeleteFromView";
 		public static  var ADD_LIMIT_VIEW:String="AddLimit";
 		public static  var RESULT_VIEW:String="Result";
-
-
+
 		//Error Codes
 		public static  var SUCCESS:int=0;
 		public static  var EMPTY_DAG:int=1;
@@ -22,7 +21,15 @@
 		public static  var DAO_EXCEPTION:int=5;
 		public static  var DYNAMIC_EXTENSION_EXCEPTION:int=6;
 		public static  var NO_PATHS_PRESENT:int=7;
+		public static  var NO_RESULT_PRESENT:int=8;
+		public static var  CLASS_NOT_FOUND:int=9;

-
+		//messages
+		public static var EMPTY_LIMIT_ERROR_MESSAGE:String = "
Please enter at least one condition to add a limit to limit set.
";
+		public static var GENERIC_MESSAGE:String="
Error occured while executing query.Please report this problem to the Adminstrator.
";
+		public static var MULTIPLE_ROOT_MESSAGE:String="
Expression graph should be a connected graph and without multiple roots.
"
+		public static var NO_RESULT_PRESENT_MESSAGE:String="
Zero records found for this query.
"
+		public static var EDIT_LIMITS_MESSAGE:String = "
Limit succesfully edited.
";
+		public static var DELETE_LIMITS_MESSAGE:String = "
Limit succesfully deleted.
";
 	}
 }


now using all_fields=true in group_list and tag_list commands.

--- WeaveData/src/weave/data/DataSources/CKANDataSource.as
+++ WeaveData/src/weave/data/DataSources/CKANDataSource.as
@@ -292,7 +292,7 @@
 		else
 		{
 			var cmd:String = 'api/' + source.apiVersion.value + '/rest/' + action.split('_')[0];
-			if (params)
+			if (params && params.hasOwnProperty('id'))
 				cmd += '/' + params['id'];
 			url = URLUtil.getFullURL(url, cmd);
 			request = new URLRequest(url);
@@ -394,7 +394,7 @@
 			return lang("Tags");

 		if (action == PACKAGE_SHOW || action == GROUP_SHOW || action == TAG_SHOW)
-			return metadata['name'] || metadata['description'] || metadata['url']
+			return metadata['display_name'] || metadata['name'] || metadata['description'] || metadata['url']
 				|| (result is String ? result as String : (result['title'] || result['display_name'] || result['name']))
 				|| params['id'];

@@ -429,7 +429,14 @@
 		if (action == PACKAGE_SHOW)
 			return getChildren().length > 0;
 		if (action == GROUP_SHOW || action == TAG_SHOW)
+		{
+			var metapkg:Object = metadata['packages'];
+			if (metapkg is Number)
+				return metapkg > 0;
+			if (metapkg is Array)
+				return (metapkg as Array).length > 0;
 			return getChildren().length > 0;
+		}

 		return action != GET_DATASOURCE && action != NO_ACTION;
 	}
@@ -476,29 +483,38 @@
 		{
 			var list:Array = [];
 			if (source.showPackages.value)
-				list.push(PACKAGE_LIST);
+				list.push([PACKAGE_LIST, null]);
 			if (source.showGroups.value)
-				list.push(GROUP_LIST);
+				list.push([GROUP_LIST, {"all_fields": true}]);
 			if (source.showTags.value)
-				list.push(TAG_LIST);
-			return updateChildren(list, function(node:CKANAction, action:String):void {
-				node.action = action;
-				node.metadata = node.params = null;
+				list.push([TAG_LIST, {"all_fields": true}]);
+			return updateChildren(list, function(node:CKANAction, actionAndParams:Array):void {
+				node.action = actionAndParams[0];
+				node.params = actionAndParams[1];
+				node.metadata = null;
 			});
 		}

 		// handle all situations where result is just an array of IDs
-		if (action == PACKAGE_LIST || action == GROUP_LIST || action == TAG_LIST || (action == TAG_SHOW && !apiVersion3))
+		if (StandardLib.getArrayType(result as Array) == String)
 			return updateChildren(result as Array, function(node:CKANAction, id:String):void {
-				if (action == PACKAGE_LIST)
+				if (action == PACKAGE_LIST || action == TAG_SHOW)
 					node.action = PACKAGE_SHOW;
 				if (action == GROUP_LIST)
 					node.action = GROUP_SHOW;
 				if (action == TAG_LIST)
 					node.action = TAG_SHOW;
-				if (action == TAG_SHOW)
-					node.action = PACKAGE_SHOW;
 				node.metadata = node.params = {"id": id};
+			});
+
+		if (action == GROUP_LIST || action == TAG_LIST)
+			return updateChildren(result as Array, function(node:CKANAction, meta:Object):void {
+				if (action == GROUP_LIST)
+					node.action = GROUP_SHOW;
+				if (action == TAG_LIST)
+					node.action = TAG_SHOW;
+				node.metadata = meta;
+				node.params = {"id": meta['id']};
 			});

 		if ((action == GROUP_SHOW || action == TAG_SHOW) && result.hasOwnProperty('packages'))
@@ -507,7 +523,7 @@
 					pkg = {"id": pkg};
 				node.action = PACKAGE_SHOW;
 				node.metadata = pkg;
-				node.params = {"id": pkg.id};
+				node.params = {"id": pkg['id']};
 			});

 		if (action == PACKAGE_SHOW && result.hasOwnProperty('resources'))


Comment tweak.

Comment tweak.

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

--- src/as/com/threerings/util/Enum.as
+++ src/as/com/threerings/util/Enum.as
@@ -54,7 +54,7 @@
  *
  * Important notes:
  *  - make your class final
- *  - create a constructor that merely calls super
+ *  - create a constructor that calls super(name)
  *  - declare your enum constants const, and with the same String as their name.
  *  - call finishedEnumerating() at the end of your constants.
  *  - your enum objects should be immutable


Close #187 - AdvancedForm -  Make fields protected instead of private to ease extension

--- library/src/flexlib/containers/AdvancedForm.as
+++ library/src/flexlib/containers/AdvancedForm.as
@@ -76,29 +76,29 @@
     //--------------------------------------------------------------------------

     /**
-     *  @private
-     */
-    private var noSnapshotFlag:Boolean = false;
-
-    /**
-     *  @private Key for reset snapshot
-     */
-    private var resetSnapshotKey:String = "reset";
-
-    /**
-     *  @private
-     */
-    private var undoCounter:int = 0;
-
-    /**
-     *  @private
-     */
-    private var undoCurrentIndex:int = -1;
-
-    /**
-     *  @private
-     */
-    private var modelStack:Object;
+     *
+     */
+    protected var noSnapshotFlag:Boolean = false;
+
+    /**
+     * Key for reset snapshot
+     */
+    protected var resetSnapshotKey:String = "reset";
+
+    /**
+     *
+     */
+    protected var undoCounter:int = 0;
+
+    /**
+     *
+     */
+    protected var undoCurrentIndex:int = -1;
+
+    /**
+     *
+     */
+    protected var modelStack:Object;

     //--------------------------------------------------------------------------
     //
@@ -111,18 +111,18 @@
     //----------------------------------

     /**
-     *  @private LookupTable of isValid flags
-     */
-    private var validators:Object;
+     * LookupTable of isValid flags
+     */
+    protected var validators:Object;

     //----------------------------------
     //  undoHistorySize
     //----------------------------------

     /**
-     *  @private
-     */
-    private var _undoHistorySize:int = 5;
+     *
+     */
+    protected var _undoHistorySize:int = 5;

     /**
      *  The undoHistorySize defaults the number of undos.
@@ -144,9 +144,9 @@
     //----------------------------------

     /**
-     *  @private
-     */
-    private var _modelType:String = "shared";
+     *
+     */
+    protected var _modelType:String = "shared";

     [Inspectable(category="General", enumeration="shared,memory", defaultValue="shared")]
     /**
@@ -203,9 +203,9 @@
     }

     /**
-     * @private
-     */
-    private function myKeyDownHandler(event:KeyboardEvent):void
+     * @protected
+     */
+    protected function myKeyDownHandler(event:KeyboardEvent):void
     {

       if (event.ctrlKey && event.keyCode == 90 && !(event.target is NumericStepper))
@@ -240,7 +240,7 @@
     /**
      * 	Loop through all Validtors at the same level as the Form and set a Event listener for Valid and Invalid
      */
-    private function setValidatorListenerEvents(event:Event):void
+    protected function setValidatorListenerEvents(event:Event):void
     {
       // Take First Snapshot After All Children have been created
       snapshotValues(this.getChildren(), resetSnapshotKey);
@@ -295,7 +295,7 @@
     /**
      * 	Handles all valid and invalid events on the validators
      */
-    private function setValidFlag(event:ValidationResultEvent):void
+    protected function setValidFlag(event:ValidationResultEvent):void
     {
       var tmpFlag:Boolean = true;
       for (var i:int = 0; i < validators.length; i++)
@@ -313,7 +313,7 @@
     /**
      *
      */
-    private function snapshotValues(obj:Object, snapshotKey:String):void
+    protected function snapshotValues(obj:Object, snapshotKey:String):void
     {
       try
       {
@@ -364,9 +364,9 @@
     }

     /**
-     * 	@private
-     */
-    private function textInputChange(event:FocusEvent):void
+     * 	@protected
+     */
+    protected function textInputChange(event:FocusEvent):void
     {
       var snapshotModel:Object = getLastestSnapshot();
       var tmpKey:String = event.target.parent.toString();
@@ -381,9 +381,9 @@
     }

     /**
-     * 	@private
-     */
-    private function controlChange(event:Event):void
+     * 	@protected
+     */
+    protected function controlChange(event:Event):void
     {
       if (event.target is RadioButton && !event.target.selected)
         takeSnapshot();
@@ -393,9 +393,9 @@
     }

     /**
-     * 	@private
-     */
-    private function doUndo():void
+     * 	@protected
+     */
+    protected function doUndo():void
     {
       //debug += "\ndoUndo: undoCurrentIndex: " + undoCurrentIndex + " undoCounter: " + undoCounter;
       noSnapshotFlag = true;
@@ -411,9 +411,9 @@
     }

     /**
-     * 	@private
-     */
-    private function doRedo():void
+     * 	@protected
+     */
+    protected function doRedo():void
     {
       //debug += "\ndoRedo: undoCurrentIndex: " + undoCurrentIndex + " undoCounter: " + undoCounter;
       noSnapshotFlag = true;
@@ -427,9 +427,9 @@
     }

     /**
-     * 	@private
-     */
-    private function takeSnapshot():void
+     * 	@protected
+     */
+    protected function takeSnapshot():void
     {
       if (!noSnapshotFlag)
       {
@@ -443,9 +443,9 @@
     }

     /**
-     * 	@private
-     */
-    private function getLastestSnapshot():Object
+     * 	@protected
+     */
+    protected function getLastestSnapshot():Object
     {
       if (undoCurrentIndex > -1)
         return modelStack[undoCurrentIndex + ""];
@@ -454,9 +454,9 @@
     }

     /**
-     * 	@private
-     */
-    private function getSnapshotKey(coutner:int):String
+     * 	@protected
+     */
+    protected function getSnapshotKey(coutner:int):String
     {
       if (coutner >= 0)
         return coutner + "";
@@ -467,7 +467,7 @@
     /**
      *
      */
-    private function resetValues(obj:Object, snapshotKey:String):void
+    protected function resetValues(obj:Object, snapshotKey:String):void
     {
       if (modelStack[snapshotKey] == undefined)
         throw new Error("Invalid snapshot");
@@ -539,7 +539,7 @@
     /**
      * 	Gather references and defaults of all the children
      */
-    private function strChildren(obj:Object):String
+    protected function strChildren(obj:Object):String
     {
       var str:String = "";
       for (var a:String in obj)


tooltip now shows immediately when f8 is pressed (identify)

--- WeaveUI/src/weave/utils/Identify.as
+++ WeaveUI/src/weave/utils/Identify.as
@@ -19,6 +19,7 @@
 package weave.utils
 {
 	import flash.display.DisplayObject;
+	import flash.events.Event;
 	import flash.events.MouseEvent;

 	import weave.api.WeaveAPI;
@@ -50,7 +51,8 @@
 			if (propertyNames && _identifyPropertyNames != _identifyDefaults)
 			{
 				_identifyPropertyNames = propertyNames;
-				WeaveAPI.StageUtils.addEventCallback(MouseEvent.MOUSE_OVER, null, _identify);
+				_identifyTarget = null;
+				WeaveAPI.StageUtils.addEventCallback(MouseEvent.MOUSE_OVER, null, _identify, true);
 			}
 			else
 			{
@@ -62,8 +64,13 @@
 		}
 		private static function _identify():void
 		{
-			var event:MouseEvent = WeaveAPI.StageUtils.mouseEvent;
+			var event:Event = WeaveAPI.StageUtils.event;
+			if (!event)
+				return;
+
 			var target:DisplayObject = event.target as DisplayObject;
+			if (!target)
+				return;

 			if (!_identifyPropertyNames || _identifyTarget == target)
 				return;


Fixed small error in VCard and replaced XMPPConnection parameter with IXMPPConnection.

git-svn-id: c197267f952b24206666de142881703007ca05d5@12355 b35dd754-fafc-0310-a699-88a17e54d16e

--- src/org/igniterealtime/xiff/vcard/VCard.as
+++ src/org/igniterealtime/xiff/vcard/VCard.as
@@ -273,7 +273,7 @@
 		 * @param jid
 		 * @return Reference to the vCard which will be filled once the loaded event occurs.
 		 */
-		public static function getVCard( connection:XMPPConnection, jid:UnescapedJID ):VCard
+		public static function getVCard( connection:IXMPPConnection, jid:UnescapedJID ):VCard
 		{
 			if ( !cacheFlushTimer.running )
 			{
@@ -330,7 +330,7 @@
 		 * @param connection
 		 * @param vCard
 		 */
-		private static function pushRequest( connection:XMPPConnection, vCard:VCard ):void
+		private static function pushRequest( connection:IXMPPConnection, vCard:VCard ):void
 		{
 			if ( !requestTimer )
 			{
@@ -1153,7 +1153,7 @@
 					var privateNode:XML = <PRIVATE/>;
 					classNode.appendChild( privateNode );
 				}
-				else ( privacyClass == "confidential" )
+				else if ( privacyClass == "confidential" )
 				{
 					var confidentialNode:XML = <CONFIDENTIAL/>;
 					classNode.appendChild( confidentialNode );


Clean up watermark values and watermark storage for sign respect.


updating winBar

updating winBar

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/jkanchelov/VideoPoker.git/'


Create ErrorManager util to get MediaErrorCode & MediaErrorMessage

error: pathspec 'src/org/mangui/osmf/plugins/utils/ErrorManager.as' did not match any file(s) known to git

--- src/org/mangui/osmf/plugins/utils/ErrorManager.as
+++ src/org/mangui/osmf/plugins/utils/ErrorManager.as
@@ -0,0 +1,37 @@
+package org.mangui.osmf.plugins.utils {
+    import org.mangui.hls.HLSError;
+    import org.mangui.hls.HLSEvent;
+    import org.osmf.events.MediaErrorCodes;
+
+    public class ErrorManager {
+
+        public static function getMediaErrorCode(event : HLSEvent) : int {
+            var errorCode : int = MediaErrorCodes.NETSTREAM_PLAY_FAILED;
+            if (event && event.error) {
+                switch (event.error.code) {
+                    case HLSError.FRAGMENT_LOADING_ERROR:
+                    case HLSError.FRAGMENT_LOADING_CROSSDOMAIN_ERROR:
+                    case HLSError.KEY_LOADING_ERROR:
+                    case HLSError.KEY_LOADING_CROSSDOMAIN_ERROR:
+                    case HLSError.MANIFEST_LOADING_CROSSDOMAIN_ERROR:
+                    case HLSError.MANIFEST_LOADING_IO_ERROR:
+                        errorCode = MediaErrorCodes.IO_ERROR;
+                        break;
+                    case org.mangui.hls.HLSError.FRAGMENT_PARSING_ERROR:
+                    case org.mangui.hls.HLSError.KEY_PARSING_ERROR:
+                    case org.mangui.hls.HLSError.MANIFEST_PARSING_ERROR:
+                        errorCode = MediaErrorCodes.NETSTREAM_FILE_STRUCTURE_INVALID;
+                        break;
+                    case org.mangui.hls.HLSError.TAG_APPENDING_ERROR:
+                        errorCode = MediaErrorCodes.ARGUMENT_ERROR;
+                        break;
+                }
+            }
+            return errorCode;
+        };
+
+        public static function getMediaErrorMessage(event : HLSEvent) : String {
+            return (event && event.error) ? event.error.msg : "Unknown error";
+        };
+    };
+}


Issue 13; Fix a problem introduced in r174. Make sure redraw take places after changing the style field.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/leymannx/svgweb.git/'


Добавлен SystemInfo

Добавлен SystemInfo

error: pathspec 'src/main/org/shypl/common/util/SystemInfo.as' did not match any file(s) known to git

--- src/main/org/shypl/common/util/SystemInfo.as
+++ src/main/org/shypl/common/util/SystemInfo.as
@@ -0,0 +1,83 @@
+package org.shypl.common.util {
+	import flash.external.ExternalInterface;
+	import flash.system.Capabilities;
+
+	public final class SystemInfo {
+		public static function define():SystemInfo {
+			return new SystemInfo(
+				Capabilities.os,
+				defineBrowser(),
+				Capabilities.playerType,
+				Capabilities.version,
+				defineScreenResolution()
+			);
+		}
+
+		private static function defineBrowser():String {
+			if (ExternalInterface.available) {
+				try {
+					return ExternalInterface.call("window.navigator.userAgent.toString");
+				}
+				catch (ignored:Error) {
+				}
+			}
+			return "NA";
+		}
+
+		private static function defineScreenResolution():String {
+			return Capabilities.screenResolutionX + "x" + Capabilities.screenResolutionY;
+		}
+
+		private var _os:String;
+		private var _browser:String;
+		private var _playerType:String;
+		private var _playerVersion:String;
+		private var _screenResolution:String;
+
+		public function SystemInfo(os:String, browser:String, playerType:String, playerVersion:String, screenResolution:String) {
+			_os = os;
+			_browser = browser;
+			_playerType = playerType;
+			_playerVersion = playerVersion;
+			_screenResolution = screenResolution;
+		}
+
+		public function get os():String {
+			return _os;
+		}
+
+		public function get browser():String {
+			return _browser;
+		}
+
+		public function get playerType():String {
+			return _playerType;
+		}
+
+		public function get playerVersion():String {
+			return _playerVersion;
+		}
+
+		public function get screenResolution():String {
+			return _screenResolution;
+		}
+
+		public function toObject():Object {
+			return {
+				os: _os,
+				browser: _browser,
+				player_type: _playerType,
+				player_version: _playerVersion,
+				screen_resolution: _screenResolution
+			}
+		}
+
+		public function toString():String {
+			return "os: " + _os + ", "
+				+ "browser: " + _browser + ", "
+				+ "player_type: " + _playerType + ", "
+				+ "player_version: " + _playerVersion + ", "
+				+ "screen_resolution: " + _screenResolution;
+		}
+	}
+}


Time for real work.

Time for real work.

error: pathspec 'src/sentinel/testing/states/TestGameplay.as' did not match any file(s) known to git

--- src/sentinel/testing/states/TestGameplay.as
+++ src/sentinel/testing/states/TestGameplay.as
@@ -0,0 +1,38 @@
+package sentinel.testing.states
+{
+
+	import sentinel.gameplay.scene.World;
+	import sentinel.gameplay.states.GameplayState;
+	import sentinel.gameplay.ui.UI;
+	import sentinel.framework.client.Keyboard;
+	import sentinel.framework.events.KeyboardEvent;
+
+
+	public class TestGameplay extends GameplayState
+	{
+
+		public function TestGameplay(world:World, ui:UI)
+		{
+			super(world, ui);
+
+			keyboard.addEventListener(KeyboardEvent.KEY_PRESSED, _keyPress);
+		}
+
+
+		private function _keyPress(event:KeyboardEvent):void
+		{
+			if (event.keyCode === Keyboard.ESC)
+			{
+				exit();
+			}
+		}
+
+
+		protected function exit():void
+		{
+			//
+		}
+
+	}
+
+}


StreamBuffer: handle overlapping fragments  (when switching level)

for example let's imagine we have data already  buffered, and new tags are appended, overlapping with existing buffer :
existing ------------------------------------------->
new tags                                       K--K----K----->
here we are trying to filter new tags to convert them into the following
existing ------------------------------------------->
filtered new tags                                      K----->
this is more complex than it seems, as we need to deal with keyframes for video and all that kind of stuff
video filtered new tags should start with a keyframe ...
if we already have overlapping tags, adjust startPosition/minPTS to match the one from first tag
we only trigger this logic if detected overlapping is more than 500 ms

--- src/org/mangui/hls/stream/StreamBuffer.as
+++ src/org/mangui/hls/stream/StreamBuffer.as
@@ -78,6 +78,10 @@
         private var _lastBufLen : Number;
         private var _lastDuration : Number;
         private var _lastMediaTimeUpdate : int;
+        /* overlapping fragment stuff */
+        private var _overlappingTags : Vector.<FLVTag>;
+        private var _overlappingStartPosition : Number;
+        private var _overlappingMinPTS : Number;

         public function StreamBuffer(hls : HLS, audioTrackController : AudioTrackController, levelController : LevelController) {
@@ -193,6 +197,52 @@
                 sliding = _liveSlidingMain;
                 // if a new fragment is being appended
                 if(fragLevel != _fragMainLevel || fragSN != _fragMainSN) {
+                    if(continuity == _fragMainInitialContinuity) {
+                        // this whole part of the code is here to handle playlists with fragments overlapping with each other (when switching level usually)
+                        // for example let's imagine we have data already  buffered, and new tags are appended, overlapping with existing buffer :
+                        // existing ------------------------------------------->
+                        // new tags                                       K--K----K----->
+                        //
+                        // here we are trying to filter new tags to convert them into the following
+                        // existing ------------------------------------------->
+                        // filtered new tags                                      K----->
+                        // this is more complex than it seems, as we need to deal with keyframes for video and all that kind of stuff
+                        // video filtered new tags should start with a keyframe ...
+                        // if we already have overlapping tags, adjust startPosition/minPTS to match the one from first tag
+                        // we only trigger this logic if detected overlapping is more than 500 ms
+
+                        if(_overlappingTags.length) {
+                            startPosition = _overlappingStartPosition;
+                            min_pts = _overlappingMinPTS;
+                            nextRelativeStartPos = startPosition + (max_pts - min_pts) / 1000;
+                        } else {
+                            _overlappingStartPosition = startPosition;
+                            _overlappingMinPTS = min_pts;
+                        }
+                        var end : Number = startPosition+(max_pts-min_pts)/1000;
+                        // check if any overlapping occurs, let 500ms tolerance
+                        if(startPosition+0.5 < max_audio_pos && startPosition+0.5 < max_video_pos) {
+                            CONFIG::LOGGING {
+                                Log.warn("fragment overlapping with buffered one, start/end/max_audio_pos/max_video_pos:"+startPosition+"/"+ end + "/" + max_audio_pos+"/"+max_video_pos);
+                            }
+                            _overlappingTags = _overlappingTags.concat(tags);
+                            // filter out overlapping tags
+                            tags = filterOverlappingTags(_overlappingTags, max_pos - startPosition);
+                            if(tags.length == 0) {
+                                // not enough data, cannot filter overlapping tags, don't push those tags
+                                // fragloader will call us back later with more data
+                                return;
+                            } else {
+                                // reset overlapping tags
+                                _overlappingTags = new Vector.<FLVTag>();
+                                // adjust startPosition and min_pts
+                                startPosition = max_pos;
+                                min_pts = tags[0].pts;
+                                // recompute value
+                                nextRelativeStartPos = startPosition + (max_pts - min_pts) / 1000;
+                            }
+                        }
+                    }
                     _fragMainLevel = fragLevel;
                     _fragMainSN = fragSN;
                     _fragMainIdx++;
@@ -351,6 +401,7 @@
             _videoTags = new Vector.<FLVData>();
             _metaTags = new Vector.<FLVData>();
             _headerTags = new Vector.<FLVData>();
+            _overlappingTags = new Vector.<FLVTag>();
             _fragMainLevel = _fragAltAudioLevel = _fragMainLevelNetStream = -1;
             _fragMainSN = _fragAltAudioSN = _fragMainSNNetStream = 0;
             FLVData.refPTSMain = FLVData.refPTSAltAudio = NaN;
@@ -541,6 +592,8 @@
                             _fragmentLoader.stop();
                             // seek position is out of buffer : load after fragment
                             _fragmentLoader.seekFromLastFrag(lastFrag);
+                            // reset overlapping tags, if any
+                            _overlappingTags = new Vector.<FLVTag>();
                         }
                         return;
                     }
@@ -645,6 +698,127 @@
                 _clipBackBuffer(HLSSettings.maxBackBufferLength);
             }
         }
+
+        /* filter incoming tags overlapping with existing buffer */
+        private function filterOverlappingTags(tags : Vector.<FLVTag>, overlap : Number) : Vector.<FLVTag> {
+            var aacIdx : int,avcIdx : int,disIdx : int,metIdx : int, videoIdx : int,audioIdx : int, lastIdx : int;
+            var first_pts : Number = tags[0].pts + 1000*overlap;
+            var flvData : FLVData = getNextTag(false);
+            if(flvData) {
+                first_pts = Math.max(first_pts,flvData.tag.pts);
+            }
+            var filteredTags : Vector.<FLVTag>=  new Vector.<FLVTag>();
+            var filteredDuration : Number = 0;
+            aacIdx = avcIdx = disIdx = metIdx = videoIdx = audioIdx = lastIdx = -1;
+            for (var i : int = 0; i < tags.length; i++) {
+                var tag : FLVTag = tags[i];
+                switch(tag.type) {
+                    case FLVTag.DISCONTINUITY:
+                        // retrieve last DISCONTINUITY tag before first_pts
+                        if (tag.pts <= first_pts)
+                            disIdx = i;
+                        break;
+                    case FLVTag.METADATA:
+                        // retrieve last METADATA tag before first_pts
+                        if (tag.pts <= first_pts)
+                            metIdx = i;
+                        break;
+                    case FLVTag.AAC_HEADER:
+                        // retrieve last AAC_HEADER tag before first_pts
+                        if (tag.pts <= first_pts)
+                            aacIdx = i;
+                        break;
+                    case FLVTag.AVC_HEADER:
+                        // retrieve last AVC_HEADER tag before first_pts
+                        if (tag.pts <= first_pts)
+                            avcIdx = i;
+                        break;
+                    case FLVTag.AVC_NALU:
+                        // retrieve first keyframe after first_pts
+                        if (videoIdx == -1 && tag.pts > first_pts && tag.keyframe) {
+                            lastIdx = videoIdx = i;
+                            CONFIG::LOGGING {
+                                Log.debug("found AVC_NALU_K after overlap @PTS:" + tag.pts);
+                            }
+                        } else if (videoIdx >=0) {
+                            lastIdx = i;
+                        }
+                         break;
+                    case FLVTag.MP3_RAW:
+                    case FLVTag.AAC_RAW:
+                        // retrieve first frame after first_pts
+                        if (audioIdx == -1 && tag.pts >  first_pts) {
+                            lastIdx = audioIdx = i;
+                        } else if (audioIdx >=0) {
+                            lastIdx = i;
+                        }
+                        break;
+                    default:
+                        break;
+                }
+            }
+
+            if(lastIdx >=0) {
+                filteredDuration = tags[lastIdx].pts - first_pts;
+                CONFIG::LOGGING {
+                    Log.debug("filterOverlappingTags : filtered duration:" + filteredDuration);
+                }
+            }
+
+            if((videoIdx >= 0 || audioIdx >=0) && filteredDuration > 500) {
+                // modify PTS for DISCONTINUITY/METADATA/AAC_HEADER/AVC_HEADER tag
+                // and push as filtered tag
+                if(disIdx >=0) {
+                    tags[disIdx].pts = tags[disIdx].dts = Math.min(tags[audioIdx].dts,tags[videoIdx].dts);
+                    filteredTags.push(tags[disIdx]);
+                }
+                if(metIdx >=0) {
+                    tags[metIdx].pts = tags[metIdx].dts = Math.min(tags[audioIdx].dts,tags[videoIdx].dts);
+                    filteredTags.push(tags[metIdx]);
+                }
+                if(aacIdx >=0) {
+                    tags[aacIdx].pts = tags[aacIdx].dts = tags[audioIdx].dts;
+                    filteredTags.push(tags[aacIdx]);
+                }
+                if(avcIdx >=0) {
+                    tags[avcIdx].pts = tags[avcIdx].dts = tags[videoIdx].dts;
+                    filteredTags.push(tags[avcIdx]);
+                }
+
+                for (i= 0; i < tags.length; i++) {
+                    tag = tags[i];
+                    switch(tag.type) {
+                        case FLVTag.AVC_NALU:
+                            // push all AVC NALU located after videoIdx
+                            if (videoIdx >= 0 && i >=  videoIdx) {
+                                filteredTags.push(tag);
+                            }
+                             break;
+                        case FLVTag.MP3_RAW:
+                        case FLVTag.AAC_RAW:
+                            // push all audio tags located after audioIdx
+                            if (audioIdx >=0 && i >=  audioIdx) {
+                                filteredTags.push(tag);
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                }
+            } else {
+                CONFIG::LOGGING {
+                    Log.debug("filterOverlappingTags: only overlapping tags found");
+                }
+            }
+            CONFIG::LOGGING {
+                Log.debug("filterOverlappingTags: filtered " + filteredTags.length + " out of " + tags.length);
+                // for (i= 0; i < filteredTags.length; i++) {
+                //     Log.debug("filteredOverlappingTags: filtered " + filteredTags[i].typeString + '/' + filteredTags[i].dts + '/' + filteredTags[i].pts);
+                // }
+            }
+            return filteredTags;
+        }
+

         /* filter/tweak tags to seek accurately into the stream */
         private function seekFilterTags(tags : Vector.<FLVData>, absoluteStartPosition : Number) : Vector.<FLVData> {


adds IBundle for intent

adds IBundle for intent

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/eric-stanley/robotlegs-framework.git/'


layout changes

layout changes

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/dseeker/lietro.git/'


add discovery service test

add discovery service test

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/noikiy/amfphp-2.0.git/'


A combo box that when changed, dispatches a command with the current selection as the arg.

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

error: pathspec 'src/as/com/threerings/flex/CommandComboBox.as' did not match any file(s) known to git

--- src/as/com/threerings/flex/CommandComboBox.as
+++ src/as/com/threerings/flex/CommandComboBox.as
@@ -0,0 +1,78 @@
+//
+// $Id$
+//
+// Nenya library - tools for developing networked games
+// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
+// http://www.threerings.net/code/nenya/
+//
+// 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.flex {
+
+import flash.events.Event;
+
+import mx.controls.ComboBox;
+import mx.events.ListEvent;
+
+import com.threerings.util.CommandEvent;
+
+/**
+ * A combo box that dispatches a command (or calls a function) when it is toggled. NOTE: Unlike the
+ * other Command* controls, CommandComboBox does not guarantee that the CommandEvent is dispatched
+ * after notifying all other listeners.
+ */
+public class CommandComboBox extends ComboBox
+{
+    /**
+     * Create a command combobox. The 'data' attribute of the selectedItem object is used as
+     * an argument of the command or function.
+     *
+     * @param cmdOrFn either a String, which will be the CommandEvent command to dispatch,
+     *        or a function, which will be called when changed.
+     */
+    public function CommandComboBox (cmdOrFn :* = null)
+    {
+        CommandButton.validateCmd(cmdOrFn);
+        _cmdOrFn = cmdOrFn;
+
+        addEventListener(ListEvent.CHANGE, handleChange);
+    }
+
+    /**
+     * Set the command and argument to be issued when this button is pressed.
+     */
+    public function setCommand (cmd :String) :void
+    {
+        _cmdOrFn = cmd;
+    }
+
+    /**
+     * Set a callback function to call when the button is pressed.
+     */
+    public function setCallback (fn :Function) :void
+    {
+        _cmdOrFn = fn;
+    }
+
+    protected function handleChange (event :ListEvent) :void
+    {
+        CommandEvent.dispatch(this, _cmdOrFn, this.selectedItem.data);
+    }
+
+    /** The command (String) to submit, or the function (Function) to call
+     * when changed,  */
+    protected var _cmdOrFn :Object;
+}
+}


Added a new AbstractEntity class

Added a new AbstractEntity class

git-svn-id: 27326a786375daad9d33dc990c6f272e4c8f567c@956 fda5f131-174c-0410-8613-e0905860106b

error: pathspec 'org.openwms/trunk/source/org.openwms.common.domain.as/src/main/flex/org/openwms/common/domain/AbstractEntity.as' did not match any file(s) known to git

--- org.openwms/trunk/source/org.openwms.common.domain.as/src/main/flex/org/openwms/common/domain/AbstractEntity.as
+++ org.openwms/trunk/source/org.openwms.common.domain.as/src/main/flex/org/openwms/common/domain/AbstractEntity.as
@@ -0,0 +1,27 @@
+/*
+ * openwms.org, the Open Warehouse Management System.
+ *
+ * This file is part of openwms.org.
+ *
+ * openwms.org 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 3 of the
+ * License, or (at your option) any later version.
+ *
+ * openwms.org 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 software. If not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.openwms.common.domain {
+
+    [Bindable]
+    [RemoteClass(alias="org.openwms.common.domain.AbstractEntity")]
+    public class AbstractEntity extends AbstractEntityBase {
+    }
+}


Inlining more methods.

Inlining more methods.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/pubnub/flash.git/'


Fix 551959  - Need huge test case for Function.apply (r=treilly, r=brbaker)

error: pathspec 'test/acceptance/ecma3/Function/apply_001.as' did not match any file(s) known to git

--- test/acceptance/ecma3/Function/apply_001.as
+++ test/acceptance/ecma3/Function/apply_001.as
@@ -0,0 +1,80 @@
+/* -*- Mode: javascript; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
+/* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is [Open Source Virtual Machine.].
+ *
+ * The Initial Developer of the Original Code is
+ * Adobe System Incorporated.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Adobe AS3 Team
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var SECTION = "apply_001";
+var VERSION = "";
+startTest();
+
+var TITLE = "Function.prototype.apply with very long argument lists";
+
+writeHeaderToLog( SECTION + " "+ TITLE);
+
+var testcases = getTestCases();
+test();
+
+function getTestCases()
+{
+    var array = new Array();
+    var initial = 1000;
+    var limit = 10000000;
+    var multiplier = 10;
+
+    function makeArray(n) {
+        var A = new Array;
+        for ( var i=0 ; i < n ; i++ )
+            A[i] = i+1;
+        return A;
+    }
+
+    function sum(...rest) {
+        var n = 0;
+        for ( var i=0 ; i < rest.length ; i++ )
+            n += rest[i];
+        return n;
+    }
+
+    for ( var i=initial ; i < limit ; i *= multiplier ) {
+        status = 'Test apply(bigarray) #' + i;
+        actual = sum.apply(null, makeArray(i));
+        expect = (i*(i+1))/2;
+        array.push(new TestCase(SECTION, status, expect, actual));
+    }
+
+    return array;
+}


some tweaks for the benchmark

some tweaks for the benchmark

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/malyavkin/badass-tex-renderer.git/'


Issue 471; Fix problem with bounding box calculation on paths with relative lines.


Do not ignore pause requests if not playing If play had been called on the NetStream but playback had not actually begun, calling pause() on the HTTPVideoProvider was silently ignored. Instead, always pause the NetStream which shouldn't be harmful if the video is already paused. The additional mutation performed by this method was left unaltered.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/OnCircle/vpaid-wrapper.git/'


first usage of the new Render behaviors, for more details check the methods left and top

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/rafaelcordoba/cocktail-demo.git/'


Bug 564527: add testcase for sealed subclass of Dictionary (r=edwsmith)

error: pathspec 'test/acceptance/as3/ShellClasses/DictionarySubclass.as' did not match any file(s) known to git

--- test/acceptance/as3/ShellClasses/DictionarySubclass.as
+++ test/acceptance/as3/ShellClasses/DictionarySubclass.as
@@ -0,0 +1,250 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is [Open Source Virtual Machine.].
+ *
+ * The Initial Developer of the Original Code is
+ * Adobe System Incorporated.
+ * Portions created by the Initial Developer are Copyright (C) 2005-2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Adobe AS3 Team
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+    import flash.utils.Dictionary
+
+    var SECTION = "DictionarySubclass";
+    var VERSION = "as3";
+    startTest();
+    var TITLE   = "test non-dynamic subclass of Dictionary class";
+
+    writeHeaderToLog( SECTION + " "+ TITLE );
+
+    // test constructors
+
+    class SealedDictionary extends Dictionary
+    {
+        public function SealedDictionary(weakKeys:Boolean=false)
+        {
+            super(weakKeys);
+        }
+    };
+
+    var dict:SealedDictionary=new SealedDictionary();
+    AddTestCase(
+      "SealedDictionary constructor no args",
+      true,
+      dict!=null
+      );
+
+    var dict_notweak:SealedDictionary=new SealedDictionary(false);
+    AddTestCase(
+      "SealedDictionary constructor weakKeys=false",
+      true,
+      dict_notweak!=null
+      );
+
+    var dict_weak:SealedDictionary=new SealedDictionary(true);
+    AddTestCase(
+      "SealedDictionary constructor weakKeys=true",
+      true,
+      dict_weak!=null
+      );
+
+    // test get/set keys and values
+
+    AddTestCase(
+      "empty SealedDictionary toString",
+      "[object SealedDictionary]",
+      dict.toString()
+      );
+
+    var tmp;
+
+    tmp = void 0;
+    try { tmp = dict_notweak['notfound']; }
+    catch(e) { tmp = grabError(e, e.toString()); }
+
+    AddTestCase(
+      "SealedDictionary key lookup fails",
+      "Error #1069",
+      tmp
+      );
+
+    tmp = void 0;
+    try { tmp = dict_weak['notfound']; }
+    catch(e) { tmp = grabError(e, e.toString()); }
+
+    AddTestCase(
+      "weak SealedDictionary key lookup fails",
+      "Error #1069",
+      tmp
+      );
+
+    tmp = void 0;
+    try { dict_notweak["one"]="one_value"; tmp = dict_notweak["one"]; }
+    catch(e) { tmp = grabError(e, e.toString()); }
+
+    AddTestCase(
+      "SealedDictionary key is literal",
+      "Error #1056",
+      tmp
+      );
+
+    tmp = void 0;
+    try { dict_weak["one"]="one_value"; tmp = dict_weak["one"]; }
+    catch(e) { tmp = grabError(e, e.toString()); }
+
+    AddTestCase(
+      "weak SealedDictionary key is literal",
+      "Error #1056",
+      tmp
+    );
+
+    var obj1:Object=new Object();
+    obj1.toString = function() { return "obj1" }
+
+    // sadly, sealed subclasses of Dictionary should probably
+    // throw the same error for Object keys, but they don't
+    // (ie they are sealed for normal keys but not Object keys)
+    // this is arguably a bug, but one that can't be fixed without
+    // versioning
+    tmp = void 0;
+    try { dict_notweak[obj1]="obj1_value"; tmp = dict_notweak[obj1]; }
+    catch(e) { tmp = grabError(e, e.toString()); }
+
+    AddTestCase(
+      "SealedDictionary key is object",
+      "obj1_value",
+      tmp
+      );
+
+    tmp = void 0;
+    try { dict_weak[obj1]="obj1_value"; tmp = dict_weak[obj1]; }
+    catch(e) { tmp = grabError(e, e.toString()); }
+
+    AddTestCase(
+      "weak SealedDictionary key is object",
+      "obj1_value",
+      tmp
+    );
+
+    // test in (hasAtomProperty)
+
+    AddTestCase(
+      "literal in SealedDictionary key",
+      false,
+      ("one" in dict_notweak)
+    );
+    // see above: Object keys ignore sealed-ness
+    AddTestCase(
+      "object in SealedDictionary key",
+      true,
+      obj1 in dict_notweak
+    );
+    AddTestCase(
+      "literal in weak SealedDictionary key",
+      false,
+      "one" in dict_weak
+    );
+    AddTestCase(
+      "object in weak SealedDictionary key",
+      true,
+      obj1 in dict_weak
+    );
+
+    var a;
+    var out1=new Array();
+    for (a in dict_notweak) {
+        out1.push(a.toString());
+    }
+    out1.sort();
+    AddTestCase(
+     "for in SealedDictionary",
+     "obj1",
+     out1.toString());
+
+    var out2=new Array(0);
+    for (a in dict_weak) {
+        out2.push(a.toString());
+    }
+    out2.sort();
+    AddTestCase(
+     "for in weak SealedDictionary",
+     "obj1",
+     out2.toString());
+
+    var out3=new Array();
+    for each (a in dict_notweak) {
+        out3.push(a.toString());
+    }
+    out3.sort();
+    AddTestCase(
+     "for each in SealedDictionary",
+     "obj1_value",
+     out3.toString());
+
+    var out4=new Array();
+    for each (a in dict_weak) {
+        out4.push(a.toString());
+    }
+    out4.sort();
+    AddTestCase(
+     "for each in weak SealedDictionary",
+     "obj1_value",
+     out4.toString());
+
+// test delete
+
+    // see above: Object keys ignore sealed-ness
+    tmp = delete dict_notweak['one'];
+    AddTestCase(
+     "delete literal key from SealedDictionary",
+     false,
+     tmp);
+
+    tmp = delete dict_notweak[obj1];
+    AddTestCase(
+     "delete object key from SealedDictionary",
+     true,
+     tmp);
+
+    // see above: Object keys ignore sealed-ness
+    tmp = delete dict_weak['one'];
+    AddTestCase(
+     "delete literal key from weak SealedDictionary",
+     false,
+     tmp);
+
+    tmp = delete dict_weak[obj1];
+    AddTestCase(
+     "delete object key from weak SealedDictionary",
+     true,
+     tmp);
+
+    test();
+


Добавлены утилита FilenameUtils

Добавлены утилита FilenameUtils

error: pathspec 'src/main/org/shypl/common/util/FilenameUtils.as' did not match any file(s) known to git

--- src/main/org/shypl/common/util/FilenameUtils.as
+++ src/main/org/shypl/common/util/FilenameUtils.as
@@ -0,0 +1,67 @@
+package org.shypl.common.util {
+	public final class FilenameUtils {
+
+		public static const EXTENSION_SEPARATOR:String = '.';
+
+		private static const UNIX_SEPARATOR:String = "/";
+
+		private static const WINDOWS_SEPARATOR:String = "\\";
+
+		public static function getName(filename:String):String {
+			if (filename == null) {
+				return null;
+			}
+			var index:int = indexOfLastSeparator(filename);
+			return filename.substring(index + 1);
+		}
+
+		public static function indexOfLastSeparator(filename:String):int {
+			if (filename == null) {
+				return -1;
+			}
+			var lastUnixPos:int = filename.lastIndexOf(UNIX_SEPARATOR);
+			var lastWindowsPos:int = filename.lastIndexOf(WINDOWS_SEPARATOR);
+			return Math.max(lastUnixPos, lastWindowsPos);
+		}
+
+		public static function indexOfExtension(filename:String):int {
+			if (filename == null) {
+				return -1;
+			}
+			var extensionPos:int = filename.lastIndexOf(EXTENSION_SEPARATOR);
+			var lastSeparator:int = indexOfLastSeparator(filename);
+			return lastSeparator > extensionPos ? -1 : extensionPos;
+		}
+
+		public static function removeExtension(filename:String):String {
+			if (filename == null) {
+				return null;
+			}
+			var index:int = indexOfExtension(filename);
+			if (index == -1) {
+				return filename;
+			}
+			else {
+				return filename.substring(0, index);
+			}
+		}
+
+		public static function getBaseName(filename:String):String {
+			return removeExtension(getName(filename));
+		}
+
+		public static function getExtension(filename:String):String {
+			if (filename == null) {
+				return null;
+			}
+			var index:int = indexOfExtension(filename);
+			if (index == -1) {
+				return "";
+			}
+			else {
+				return filename.substring(index + 1);
+			}
+		}
+
+	}
+}


SoundSequencer - Cues a sequence of sounds with sample accuracy

error: pathspec 'raw/src/org/yellcorp/lib/sound/SoundSequencer.as' did not match any file(s) known to git

--- raw/src/org/yellcorp/lib/sound/SoundSequencer.as
+++ raw/src/org/yellcorp/lib/sound/SoundSequencer.as
@@ -0,0 +1,199 @@
+package org.yellcorp.lib.sound
+{
+import flash.events.SampleDataEvent;
+import flash.media.Sound;
+import flash.utils.ByteArray;
+
+
+public class SoundSequencer
+{
+    private var _outputBufferSize:uint;
+
+    private var cues:Array;
+    private var sequenceSampleLength:Number;
+
+    // the data from individual sounds are extracted into this ByteArray
+    private var extractBuffer:ByteArray;
+
+    // mixing buffers. during the mixing loop, one stores the accumulated
+    // sum of the playing waves thus far, and the other is set to that sum
+    // plus the next sound wave. A and B are swapped at the end of each
+    // iteration
+    private var mixingBufferA:ByteArray;
+    private var mixingBufferB:ByteArray;
+
+    // acts as a source of zero bytes when the first sound in the mixing
+    // loop does not coincide exactly with the start of the packet
+    private var zeroBuffer:ByteArray;
+
+    public function SoundSequencer(outputBufferSize:uint = 8192)
+    {
+        if (outputBufferSize < 2048 || outputBufferSize > 8192)
+        {
+            throw new ArgumentError("outputBufferSize must be in the range 2048 to 8192");
+        }
+        _outputBufferSize = outputBufferSize;
+        cues = [ ];
+
+        extractBuffer = new ByteArray();
+        mixingBufferA = new ByteArray();
+        mixingBufferB = new ByteArray();
+        zeroBuffer = createZeroBuffer(_outputBufferSize);
+        sequenceSampleLength = 0;
+    }
+
+    public function cue(sound:Sound, sample:int):void
+    {
+        var newCue:Cue = new Cue(sound, sample);
+        cues.push(newCue);
+        if (newCue.endSample > sequenceSampleLength)
+        {
+            sequenceSampleLength = newCue.endSample;
+        }
+    }
+
+    public function getSound():Sound
+    {
+        var userSound:Sound = new Sound();
+        userSound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData, false, 0, false);
+        return userSound;
+    }
+
+    private function onSampleData(event:SampleDataEvent):void
+    {
+        var packetStart:Number = event.position;
+        var packetEnd:Number = packetStart + _outputBufferSize;
+
+        var cueLength:Number;
+        var packetOffset:Number;
+        var cueOffset:Number;
+        var samplesExtracted:Number;
+
+        var srcBuffer:ByteArray;
+        var destBuffer:ByteArray;
+
+        srcBuffer = zeroBuffer;
+        destBuffer = mixingBufferB;
+
+        if (packetStart > sequenceSampleLength)
+        {
+            // sequence complete
+            return;
+        }
+
+        // this will contain data from the last packet, so clear it
+        mixingBufferA.clear();
+
+        for each (var cue:Cue in cues)
+        {
+            // check if it overlaps with the current packet
+            if (cue.startSample > packetEnd ||
+                cue.endSample < packetStart)
+            {
+                continue;
+            }
+
+            srcBuffer.position = 0;
+            destBuffer.clear();
+            extractBuffer.clear();
+
+            if (packetStart >= cue.startSample)
+            {
+                // we are exactly at the start, or in the middle of the
+                // cued sound
+                packetOffset = 0;
+                cueOffset = packetStart - cue.startSample;
+                cueLength = _outputBufferSize;
+            }
+            else
+            {
+                // otherwise the cued sound is starting in the middle of
+                // this packet
+                packetOffset = cue.startSample - packetStart;
+                cueOffset = 0;
+                cueLength = _outputBufferSize - packetOffset;
+            }
+
+            samplesExtracted = cue.sound.extract(extractBuffer, cueLength, cueOffset);
+            if (samplesExtracted == 0)
+            {
+                // reached the end of this cued sound
+                continue;
+            }
+            extractBuffer.position = 0;
+
+            if (packetOffset > 0)
+            {
+                // cued sound starts in the middle of the packet - just
+                // copy the accumulation buffer data up to that point
+                destBuffer.writeBytes(srcBuffer, 0, packetOffset * 8);
+                srcBuffer.position = packetOffset * 8;
+            }
+
+            while (srcBuffer.bytesAvailable > 0 && extractBuffer.bytesAvailable > 0)
+            {
+                // mix the cued sound with the accumulation buffer
+                // left channel
+                destBuffer.writeFloat(srcBuffer.readFloat() + extractBuffer.readFloat());
+                // right channel
+                destBuffer.writeFloat(srcBuffer.readFloat() + extractBuffer.readFloat());
+            }
+
+            if (srcBuffer.bytesAvailable > 0)
+            {
+                // ran out of cued sound during the mix, write the rest of
+                // the accumulation buffer
+                destBuffer.writeBytes(srcBuffer, srcBuffer.position);
+            }
+
+            // we have just mixed one more cued sound into the destination
+            // buffer, so it will act as the source on the next loop,
+            // therefore swap the buffers.  we compare srcBuffer to mixingBufferB
+            // because srcBuffer won't equal mixingBufferA on the first loop,
+            // it will be pointing at zeroBuffer instead
+            if (srcBuffer == mixingBufferB)
+            {
+                srcBuffer = mixingBufferA;
+                destBuffer = mixingBufferB;
+            }
+            else
+            {
+                srcBuffer = mixingBufferB;
+                destBuffer = mixingBufferA;
+            }
+        }
+        event.data.writeBytes(srcBuffer);
+    }
+
+    private static function createZeroBuffer(sampleCount:uint):ByteArray
+    {
+        var zeroBuffer:ByteArray = new ByteArray();
+        for (var i:int = 0; i < sampleCount; i++)
+        {
+            zeroBuffer.writeDouble(0);
+        }
+        zeroBuffer.position = 0;
+        return zeroBuffer;
+    }
+}
+}
+
+
+import flash.media.Sound;
+
+
+class Cue
+{
+    public var sound:Sound;
+    public var startSample:Number;
+    public var length:Number;
+    public var endSample:Number;
+
+    public function Cue(sound:Sound, startSample:Number)
+    {
+        this.sound = sound;
+        this.startSample = startSample;
+        this.length = Math.ceil(sound.length * 44.1);
+        this.endSample = startSample + this.length;
+    }
+}


copied RDataSource from WeaveAnalyst branch

error: pathspec 'WeaveData/src/weave/data/DataSources/RDataSource.as' did not match any file(s) known to git

--- WeaveData/src/weave/data/DataSources/RDataSource.as
+++ WeaveData/src/weave/data/DataSources/RDataSource.as
@@ -0,0 +1,247 @@
+/* ***** BEGIN LICENSE BLOCK *****
+*
+* This file is part of Weave.
+*
+* The Initial Developer of Weave is the Institute for Visualization
+* and Perception Research at the University of Massachusetts Lowell.
+* Portions created by the Initial Developer are Copyright (C) 2008-2015
+* the Initial Developer. All Rights Reserved.
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this file,
+* You can obtain one at http://mozilla.org/MPL/2.0/.
+*
+* ***** END LICENSE BLOCK ***** */
+
+package weave.data.DataSources
+{
+	import flash.events.ErrorEvent;
+
+	import mx.rpc.events.FaultEvent;
+	import mx.rpc.events.ResultEvent;
+
+	import weave.api.core.ILinkableObject;
+	import weave.api.data.ColumnMetadata;
+	import weave.api.data.IAttributeColumn;
+	import weave.api.data.IColumnReference;
+	import weave.api.data.IDataSource;
+	import weave.api.data.IDataSource_Service;
+	import weave.api.data.IWeaveTreeNode;
+	import weave.api.detectLinkableObjectChange;
+	import weave.api.disposeObject;
+	import weave.api.getCallbackCollection;
+	import weave.api.getLinkableDescendants;
+	import weave.api.getSessionState;
+	import weave.api.linkableObjectIsBusy;
+	import weave.api.newLinkableChild;
+	import weave.api.registerLinkableChild;
+	import weave.api.reportError;
+	import weave.core.LinkableHashMap;
+	import weave.core.LinkablePromise;
+	import weave.core.LinkableString;
+	import weave.data.AttributeColumns.ProxyColumn;
+	import weave.data.AttributeColumns.ReferencedColumn;
+	import weave.data.hierarchy.ColumnTreeNode;
+	import weave.services.AMF3Servlet;
+	import weave.services.JsonCache;
+	import weave.services.WeaveRServlet;
+	import weave.services.addAsyncResponder;
+	import weave.utils.ColumnUtils;
+	import weave.utils.VectorUtils;
+
+	public class RDataSource extends AbstractDataSource implements IDataSource_Service
+	{
+		WeaveAPI.ClassRegistry.registerImplementation(IDataSource, RDataSource, "R Data Source");
+
+		public static const SCRIPT_OUTPUT_NAME:String = 'scriptOutputName';
+		private static const RESULT_DATA:String = "resultData";
+		private static const COLUMN_NAMES:String = "columnNames";
+
+		public function RDataSource()
+		{
+			promise.depend(url, scriptName, inputs, hierarchyRefresh);
+		}
+
+		public const url:LinkableString = registerLinkableChild(this, new LinkableString('/WeaveAnalystServices/ComputationalServlet'), handleURLChange);
+		public const scriptName:LinkableString = newLinkableChild(this, LinkableString);
+		public const inputs:LinkableHashMap = newLinkableChild(this, LinkableHashMap);
+
+		private const promise:LinkablePromise = registerLinkableChild(this, new LinkablePromise(runScript, describePromise));
+		private function describePromise():String { return lang("Running script {0}", scriptName.value); }
+		private const outputCSV:CSVDataSource = newLinkableChild(this, CSVDataSource);
+		private var _service:AMF3Servlet;
+
+		override protected function initialize():void
+		{
+			super.initialize();
+			promise.validate();
+		}
+
+		private function handleURLChange():void
+		{
+			if (_service && _service.servletURL == url.value)
+				return;
+			disposeObject(_service);
+			_service = registerLinkableChild(this, new AMF3Servlet(url.value));
+			hierarchyRefresh.triggerCallbacks();
+		}
+
+		private function runScript():void
+		{
+			// if callbacks are delayed, we assume that hierarchyRefresh will be explicitly triggered later.
+			if (getCallbackCollection(this).callbacksAreDelayed)
+				return;
+			// force retrieval of referenced columns
+			for each (var refCol:ReferencedColumn in getLinkableDescendants(inputs, ReferencedColumn))
+				refCol.getInternalColumn();
+			if (linkableObjectIsBusy(inputs))
+				return;
+
+			var keyType:String;
+			var simpleInputs:Object = {};
+			var columnsByKeyType:Object = {}; // Object(keyType -> Array of IAttributeColumn)
+
+			var tableData:Object = {}; // Object(inputName -> { columnName : column })
+			var columnData:Object = {}; // Object(keyType -> {keys: [], columns: Object(name -> Array) })
+
+			var joined:Array = [];
+			var colMap:Object = {};
+
+			for each (var obj:ILinkableObject in inputs.getObjects())
+			{
+				var name:String = inputs.getName(obj);
+
+				// if the input is a column
+				var column:IAttributeColumn = obj as IAttributeColumn;
+				if (column)
+				{
+					keyType = column.getMetadata(ColumnMetadata.KEY_TYPE);
+					var columnArray:Array = columnsByKeyType[keyType] || (columnsByKeyType[keyType] = [])
+					columnArray.push(column);
+					for (keyType in columnsByKeyType)
+					{
+						var cols:Array = columnsByKeyType[keyType];
+						joined = ColumnUtils.joinColumns(cols, null, true);
+						var keys:Array = VectorUtils.pluck(joined.shift() as Array, 'localName');
+						colMap = {};
+						for (var i:int = 0; i <  joined.length; i++)
+							colMap[ inputs.getName(cols[i]) ] = joined[i];
+						columnData[keyType] = {keys: keys, columns: colMap};
+					}
+				}
+				else
+				{
+					var columns:Array = obj as Array;
+					// if the input is an array of columns
+					if(columns)
+					{
+						var flag:Boolean = false;
+						if(!columns.length)
+							return;
+
+						column = columns[0] as IAttributeColumn;
+						keyType = column.getMetadata(ColumnMetadata.KEY_TYPE);
+
+						for each (var col:IAttributeColumn in columns)
+						{
+							flag = col.getMetadata(ColumnMetadata.KEY_TYPE) != keyType;
+							colMap[col.getMetadata(ColumnMetadata.TITLE)] = col;
+						}
+						if(flag) {
+							reportError("Columns in table input must all be of the same keyType");
+							return;
+						} else {
+							tableData[name] = colMap;
+						}
+					} else {
+						// if the input is just a value (number, string or boolean)
+						simpleInputs[name] = getSessionState(inputs.getObject(name));
+					}
+				}
+			}
+
+			outputCSV.setCSVData(null);
+			outputCSV.metadata.setSessionState(null);
+
+			addAsyncResponder(
+				_service.invokeAsyncMethod('runScriptWithInputs', [scriptName.value, simpleInputs, columnData, tableData]),
+				handleScriptResult,
+				handleScriptError,
+				getSessionState(this)
+			);
+		}
+
+		private function handleScriptResult(event:ResultEvent, sessionState:Object):void
+		{
+			// ignore outdated response
+			if (WeaveAPI.SessionManager.computeDiff(sessionState, getSessionState(this)) !== undefined)
+				return;
+
+			var result:Object = event.result;
+			var columnNames:Array = result[COLUMN_NAMES]; // array of strings
+			var resultData:Array = result[RESULT_DATA]; // array of columns
+			if (resultData)
+			{
+				var rows:Array = VectorUtils.transpose(resultData);
+				rows.unshift(columnNames);
+				outputCSV.setCSVData(rows);
+			}
+			else
+				outputCSV.setCSVData(null);
+		}
+
+		private function handleScriptError(event:FaultEvent, sessionState:Object):void
+		{
+			// ignore outdated response
+			if (WeaveAPI.SessionManager.computeDiff(sessionState, getSessionState(this)) !== undefined)
+				return;
+			reportError(event);
+		}
+
+		override public function getHierarchyRoot():IWeaveTreeNode
+		{
+			if (!_rootNode)
+			{
+				var name:String = WeaveAPI.globalHashMap.getName(this);
+				var source:RDataSource = this;
+				_rootNode = new ColumnTreeNode({
+					label: name,
+					dataSource: this,
+					dependency: outputCSV,
+					hasChildBranches: false,
+					children: function():Array {
+						var csvRoot:IWeaveTreeNode = outputCSV.getHierarchyRoot();
+						return csvRoot.getChildren().map(function(csvNode:IColumnReference, ..._):IWeaveTreeNode {
+							var meta:Object = csvNode.getColumnMetadata();
+							meta[SCRIPT_OUTPUT_NAME] = meta[CSVDataSource.METADATA_COLUMN_NAME];
+							return generateHierarchyNode(meta);
+						});
+					}
+				});
+			}
+			return _rootNode;
+		}
+
+		override protected function generateHierarchyNode(metadata:Object):IWeaveTreeNode
+		{
+			if (!metadata)
+				return null;
+
+			return new ColumnTreeNode({
+				dataSource: this,
+				idFields: [SCRIPT_OUTPUT_NAME],
+				data: metadata
+			});
+		}
+
+		override protected function requestColumnFromSource(proxyColumn:ProxyColumn):void
+		{
+			var name:String = proxyColumn.getMetadata(SCRIPT_OUTPUT_NAME);
+			var column:IAttributeColumn = outputCSV.getColumnById(name);
+			if (column)
+				proxyColumn.setInternalColumn(column);
+			else
+				proxyColumn.dataUnavailable();
+		}
+	}
+}


refactored subscribe/unsubscribe logic into a new method


Добавлен IllegalOperationException

Добавлен IllegalOperationException

error: pathspec 'src/main/org/shypl/common/lang/IllegalOperationException.as' did not match any file(s) known to git

--- src/main/org/shypl/common/lang/IllegalOperationException.as
+++ src/main/org/shypl/common/lang/IllegalOperationException.as
@@ -0,0 +1,7 @@
+package org.shypl.common.lang {
+	public class IllegalOperationException extends RuntimeException {
+		public function IllegalOperationException(message:String = null, cause:Error = null) {
+			super(message, cause);
+		}
+	}
+}


Add UintComparator

Add UintComparator

error: pathspec 'src/main/org/shypl/common/util/UintComparator.as' did not match any file(s) known to git

--- src/main/org/shypl/common/util/UintComparator.as
+++ src/main/org/shypl/common/util/UintComparator.as
@@ -0,0 +1,29 @@
+package org.shypl.common.util {
+	public class UintComparator extends SimpleComparator {
+		private static var LOW_TO_HIGH:UintComparator;
+		private static var HIGH_TO_LOW:UintComparator;
+
+		public static function getInstance(reverse:Boolean = false):Comparator {
+			if (reverse) {
+				if (HIGH_TO_LOW === null) {
+					HIGH_TO_LOW = new UintComparator(true);
+				}
+				return HIGH_TO_LOW;
+			}
+
+			if (LOW_TO_HIGH === null) {
+				LOW_TO_HIGH = new UintComparator(false);
+			}
+
+			return LOW_TO_HIGH;
+		}
+
+		public function UintComparator(reverse:Boolean) {
+			super(reverse);
+		}
+
+		override protected function isGreater(a:Object, b:Object):Boolean {
+			return uint(a) > uint(b);
+		}
+	}
+}


SWFADdress追加

SWFADdress追加

git-svn-id: 864080e30cc358c5edb906449bbf014f90258007@12 96db6a20-122f-0410-8d9f-89437bbe4005

error: pathspec 'src/com/asual/SWFAddress.as' did not match any file(s) known to git

--- src/com/asual/SWFAddress.as
+++ src/com/asual/SWFAddress.as
@@ -0,0 +1,137 @@
+/**
+ * SWFAddress v1.1: Deep linking for Flash - http://www.asual.com/swfaddress/
+ *
+ * SWFAddress is (c) 2006 Rostislav Hristov and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ */
+
+package com.asual{
+
+    import flash.external.ExternalInterface;
+    import flash.utils.clearInterval;
+    import flash.utils.setInterval;
+
+    public class SWFAddress {
+
+        private static var _value:String = '';
+        private static var _availability:Boolean = ExternalInterface.available;
+
+        public static var onChange:Function;
+
+        private static function _check():void {
+            if (SWFAddress.onChange != null) {
+                clearInterval(SWFAddress._interval);
+                if (_availability) {
+                    ExternalInterface.addCallback('getSWFAddressValue',
+                        function():String {return _value});
+                    ExternalInterface.addCallback('setSWFAddressValue',
+                        SWFAddress.setValue);
+                }
+                SWFAddress.setValue(SWFAddress.getValue());
+            }
+        }
+        private static var _interval:Number = setInterval(SWFAddress._check, 10);
+
+        public static function getTitle():String {
+            var title:String = (_availability) ?
+                ExternalInterface.call('SWFAddress.getTitle') as String : '';
+            if (title == 'undefined' || title == null) title = '';
+            return title;
+        }
+
+        public static function setTitle(title:String):void {
+            if (_availability) ExternalInterface.call('SWFAddress.setTitle', title);
+        }
+
+        public static function getStatus():String {
+            var status:String = (_availability) ?
+                ExternalInterface.call('SWFAddress.getStatus') as String : '';
+            if (status == 'undefined' || status == null) status = '';
+            return status;
+        }
+
+        public static function setStatus(status:String):void {
+            if (_availability) ExternalInterface.call('SWFAddress.setStatus', status);
+        }
+
+        public static function resetStatus():void {
+            if (_availability) ExternalInterface.call('SWFAddress.resetStatus');
+        }
+
+        public static function getPath():String {
+            var value:String = SWFAddress.getValue();
+            if (value.indexOf('?') != 1) {
+                return value.split('?')[0];
+            } else {
+                return value;
+            }
+        }
+
+        public static function getQueryString():String {
+            var value:String = SWFAddress.getValue();
+            var index:Number = value.indexOf('?');
+            if (index != -1 && index < value.length) {
+                return value.substr(index + 1);
+            }
+            return '';
+        }
+
+        public static function getParameter(param:String):String {
+            var value:String = SWFAddress.getValue();
+            var index:Number = value.indexOf('?');
+            if (index != -1) {
+                value = value.substr(index + 1);
+                var params:Array = value.split('&');
+                var p:Array;
+                var i:Number = params.length;
+                while(i--) {
+                    p = params[i].split('=');
+                    if (p[0] == param) {
+                        return p[1];
+                    }
+                }
+            }
+            return '';
+        }
+
+        public static function getParameterNames():Array {
+            var value:String = SWFAddress.getValue();
+            var index:Number = value.indexOf('?');
+            var names:Array = new Array();
+            if (index != -1) {
+                value = value.substr(index + 1);
+                if (value != '' && value.indexOf('=') != -1) {
+                    var params:Array = value.split('&');
+                    var i:Number = 0;
+                    while(i < params.length) {
+                        names.push(params[i].split('=')[0]);
+                        i++;
+                    }
+                }
+            }
+            return names;
+        }
+
+        public static function getValue():String {
+            var addr:String, id:String = null;
+            if (_availability) {
+                addr = ExternalInterface.call('SWFAddress.getValue') as String;
+                id = ExternalInterface.call('SWFAddress.getId') as String;
+            }
+            if (id == null || !_availability) {
+                addr = SWFAddress._value;
+            } else {
+                if (addr == 'undefined' || addr == null) addr = '';
+            }
+            return addr;
+        }
+
+        public static function setValue(addr:String):void {
+            if (addr == 'undefined' || addr == null) addr = '';
+            SWFAddress._value = addr;
+            if (_availability) ExternalInterface.call('SWFAddress.setValue', addr);
+            if (SWFAddress.onChange != null) SWFAddress.onChange();
+        }
+    }
+}


adding "roll_over" / "roll_out" examples


Introduce maxSkippedFragments setting

Introduce maxSkippedFragments setting

--- src/org/mangui/hls/HLSSettings.as
+++ src/org/mangui/hls/HLSSettings.as
@@ -235,6 +235,17 @@
          * Default is true.
          */
         public static var fragmentLoadSkipAfterMaxRetry : Boolean = true;
+
+        /**
+         * maxSkippedFragments
+         *
+         * Maximum count of skipped fragments in a row before an I/O Error will be raised.
+         *      0 - no skip (same as fragmentLoadSkipAfterMaxRetry = false)
+         *      -1 - no limit for skipping, skip till the end of the playlist
+         *
+         * Default is 5.
+         */
+        public static var maxSkippedFragments : int = 5;

         /**
          * flushLiveURLCache


Refactored CommandFlow test to dry things up

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/eric-stanley/robotlegs-framework.git/'


Added base TestCase for backward compatibility

error: pathspec 'as3/src/asunit4/framework/TestCase.as' did not match any file(s) known to git

--- as3/src/asunit4/framework/TestCase.as
+++ as3/src/asunit4/framework/TestCase.as
@@ -0,0 +1,41 @@
+package asunit4.framework {
+
+    import flash.display.MovieClip
+    import asunit4.async.IAsync;
+
+    class TestCase {
+
+        [Async]
+        public var async:IAsync;
+
+        [Before]
+        public function otherBefore():void {
+        }
+
+        [Before]
+        public function callSetUp():void {
+            setUp();
+        }
+
+        protected function setUp():void {
+        }
+
+        [After]
+        public function callTearDown():void {
+            tearDown();
+        }
+
+        protected function tearDown():void {
+        }
+
+        // TODO: Implement addAsync correctly:
+        protected function addAsync(...):Function {
+            return null;
+        }
+
+        protected function getContext():MovieClip {
+            return null;
+        }
+    }
+}
+


cleaning up

cleaning up


Leave interval check running for log events

--- src/org/openvv/OVVAsset.as
+++ src/org/openvv/OVVAsset.as
@@ -620,7 +620,6 @@
 		private function raiseImpression(ovvData:*):void
 		{
 			dispatchEvent(new OVVEvent(OVVEvent.OVVImpression, ovvData));
-			_intervalTimer.removeEventListener(TimerEvent.TIMER, onIntervalCheck);
 			_impressionEventRaised = true;
 		}


doing some updates, nothing critical. PositionTest is running again


Added support for configurable background color in viewer.

--- tools/viewers/flash/src/AWDViewer.as
+++ tools/viewers/flash/src/AWDViewer.as
@@ -64,6 +64,7 @@
 			_view = new View3D();
 			_view.antiAlias = 4;
 			_view.camera.lens.far = 5000;
+			_view.backgroundColor = loaderInfo.parameters['bgcolor'] || 0;
 			addChild(_view);
 			addEventListener(Event.ENTER_FRAME, onEnterFrame);


Bug 498979: Add Testcase (r=dschaffe)

Bug 498979: Add Testcase (r=dschaffe)

error: pathspec 'test/acceptance/regress/bug_498979.as' did not match any file(s) known to git

--- test/acceptance/regress/bug_498979.as
+++ test/acceptance/regress/bug_498979.as
@@ -0,0 +1,85 @@
+/* ***** BEGIN LICENSE BLOCK *****
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License Version
+* 1.1 (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.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+*
+* The Original Code is [Open Source Virtual Machine.].
+*
+* The Initial Developer of the Original Code is
+* Adobe System Incorporated.
+* Portions created by the Initial Developer are Copyright (C) 2009
+* the Initial Developer. All Rights Reserved.
+*
+* Contributor(s):
+*   Adobe AS3 Team
+*
+* Alternatively, the contents of this file may be used under the terms of
+* either the GNU General Public License Version 2 or later (the "GPL"), or
+* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+* in which case the provisions of the GPL or the LGPL are applicable instead
+* of those above. If you wish to allow use of your version of this file only
+* under the terms of either the GPL or the LGPL, and not to allow others to
+* use your version of this file under the terms of the MPL, indicate your
+* decision by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL or the LGPL. If you do not delete
+* the provisions above, a recipient may use your version of this file under
+* the terms of any one of the MPL, the GPL or the LGPL.
+*
+* ***** END LICENSE BLOCK ***** */
+
+var SECTION = "Regression Tests";
+var VERSION = "";
+var TITLE = " Bug 498979 -  jit mangles value when calling a setter with * type";
+
+startTest();
+
+var _any:*;
+
+function set any(val:*) {
+		_any = val;
+}
+
+function get any():* {
+		return _any;
+}
+
+any = 'hello world';
+
+AddTestCase("Verify value when calling setter with * type", 'hello world', any);
+
+/*
+ The rest of this test file does not work due to this asc bug:
+ https://bugs.adobe.com/jira/browse/ASC-3889
+
+function set obj(val:Object) {
+		_any = val;
+}
+
+function get obj():Object {
+		return _any;
+}
+
+var testValues = ['hello there', 2.0000000005547, 7.314e24, new Object(), -982743278642,
+                  <myXml><testing>hello</testing></myXml>, [4,7,2], false, true, new Date()];
+
+any = testValues[-1];
+AddTestCase("Verify value when calling setter with * type", testValues[-1], any);
+
+
+for (var i=0; i<testValues.length; i++) {
+    any = testValues[i];
+    //AddTestCase("Verify value when calling setter with * type", testValues[i], any);
+    //obj = testValues[i];
+    //AddTestCase("Verify value when calling setter with Object type", testValues[i], obj);
+}
+ */
+
+test();


added TodoListEvent

added TodoListEvent

error: pathspec 'examples/TodoListSampleApp/src/event/TodoListEvent.as' did not match any file(s) known to git

--- examples/TodoListSampleApp/src/event/TodoListEvent.as
+++ examples/TodoListSampleApp/src/event/TodoListEvent.as
@@ -0,0 +1,35 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 event {
+    import org.apache.flex.events.Event;
+
+    public class TodoListEvent extends Event {
+
+        public static const LOG_TODO:String = "logTodoEvent";
+
+        /**
+         * the todo to log
+         */
+        public var todo:String = null;
+
+        public function TodoListEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false) {
+            super(type, bubbles, cancelable);
+        }
+    }
+}


Image Match picture can be uploaded for each location.

error: pathspec 'flexEditor/src/org/arisgames/editor/view/ImageMatchEditorView.as' did not match any file(s) known to git

--- flexEditor/src/org/arisgames/editor/view/ImageMatchEditorView.as
+++ flexEditor/src/org/arisgames/editor/view/ImageMatchEditorView.as
@@ -0,0 +1,198 @@
+package org.arisgames.editor.view
+{
+	import flash.events.MouseEvent;
+
+	import mx.collections.ArrayCollection;
+	import mx.containers.Canvas;
+	import mx.containers.Panel;
+	import mx.controls.Alert;
+	import mx.controls.Button;
+	import mx.controls.DataGrid;
+	import mx.controls.Image;
+	import mx.controls.Label;
+	import mx.controls.LinkButton;
+	import mx.events.DataGridEvent;
+	import mx.events.DynamicEvent;
+	import mx.events.FlexEvent;
+	import mx.managers.PopUpManager;
+	import mx.rpc.Responder;
+
+	import org.arisgames.editor.data.arisserver.Media;
+	import org.arisgames.editor.components.PlaceMarker;
+	import org.arisgames.editor.components.PlaceMarkerEditorMediaPickerMX;
+	import org.arisgames.editor.data.PlaceMark;
+	import org.arisgames.editor.models.GameModel;
+	import org.arisgames.editor.services.AppServices;
+	import org.arisgames.editor.util.AppConstants;
+	import org.arisgames.editor.util.AppDynamicEventManager;
+	import org.arisgames.editor.util.AppUtils;
+
+
+	public class ImageMatchEditorView extends Panel
+	{
+
+		public var placeMark:PlaceMark;
+		public var placeMarker:PlaceMarker;
+
+
+		// GUI
+		[Bindable] public var closeButton:Button;
+
+		[Bindable] public var mediaImageCanvas:Canvas;
+		[Bindable] public var mediaPreviewImage:Image;
+		[Bindable] public var mediaRemoveButton:Button;
+		[Bindable] public var mediaNoMediaLabel:Label;
+		[Bindable] public var mediaPopupMediaPickerButton:Button;
+
+		private var mediaPicker:PlaceMarkerEditorMediaPickerMX;
+
+
+		/**
+		 * Constructor
+		 */
+		public function ImageMatchEditorView()
+		{
+			super();
+			this.addEventListener(FlexEvent.CREATION_COMPLETE, handleInit);
+		}
+
+		private function handleInit(event:FlexEvent):void
+		{
+			mediaRemoveButton.addEventListener(MouseEvent.CLICK, handleMediaRemoveButtonClick);
+			mediaPopupMediaPickerButton.addEventListener(MouseEvent.CLICK, handleMediaPickerButton);
+			closeButton.addEventListener(MouseEvent.CLICK, handleCloseButton);
+		}
+
+		private function handleMediaRemoveButtonClick(evt:MouseEvent):void
+		{
+			trace("handleMediaRemoveButtonClick() called.");
+			this.placeMarker.imageMatchMediaId = 0;
+			this.placeMarker.imageMatchMedia = null;
+			pushDataIntoGUI();
+		}
+
+		private function handleMediaPickerButton(evt:MouseEvent):void
+		{
+			trace("ImageMatchEditorView: handleMediaPickerButton() called...");
+			this.openMediaPicker();
+		}
+
+		private function openMediaPicker():void
+		{
+			mediaPicker = new PlaceMarkerEditorMediaPickerMX();
+			mediaPicker.setPlaceMarker(placeMarker);
+			mediaPicker.delegate = this;
+
+			PopUpManager.addPopUp(mediaPicker, AppUtils.getInstance().getMainView(), true);
+			PopUpManager.centerPopUp(mediaPicker);
+		}
+
+
+		private function pushDataIntoGUI():void
+		{
+			trace("ImageMatchEditorView: pushDataIntoGUI called with imageMatchMedia Id = '" + placeMarker.imageMatchMediaId);
+
+				// Load The Media GUI
+			mediaPopupMediaPickerButton.setVisible(true);
+			mediaPopupMediaPickerButton.includeInLayout = true;
+			if (placeMarker.imageMatchMedia != null && (placeMarker.imageMatchMedia.type == AppConstants.MEDIATYPE_IMAGE || placeMarker.imageMatchMedia.type == AppConstants.MEDIATYPE_ICON))
+			{
+				mediaImageCanvas.setVisible(true);
+				mediaImageCanvas.includeInLayout = true;
+				mediaPreviewImage.setVisible(true);
+				mediaPreviewImage.includeInLayout = true;
+				mediaNoMediaLabel.setVisible(false);
+				mediaNoMediaLabel.includeInLayout = false;
+				mediaRemoveButton.setVisible(true);
+				mediaRemoveButton.includeInLayout = true;
+
+				var mediaurl:String = placeMarker.imageMatchMedia.urlPath + placeMarker.imageMatchMedia.fileName;
+				mediaPreviewImage.source = mediaurl;
+				trace("Just set media image url = '" + mediaurl + "'");
+			}
+			else
+			{
+				mediaImageCanvas.setVisible(true);
+				mediaImageCanvas.includeInLayout = true;
+				mediaPreviewImage.setVisible(false);
+				mediaPreviewImage.includeInLayout = false;
+				mediaNoMediaLabel.setVisible(true);
+				mediaNoMediaLabel.includeInLayout = true;
+				mediaRemoveButton.setVisible(false);
+				mediaRemoveButton.includeInLayout = false;
+			}
+		}
+
+		public function setPlaceMarks(placeMark:PlaceMark, placeMarker:PlaceMarker):void{
+			this.placeMark = placeMark;
+			this.placeMarker = placeMarker;
+
+			if(placeMarker.imageMatchMediaId != 0){
+				if(placeMarker.imageMatchMedia == null){
+					AppServices.getInstance().getMediaByGameIdAndMediaId(GameModel.getInstance().game.gameId, placeMarker.imageMatchMediaId, new Responder(handleLoadImageMatchMedia, handleFault));
+					return;
+				}
+			}
+			pushDataIntoGUI();
+		}
+
+
+		public function didSelectMediaItem(picker:PlaceMarkerEditorMediaPickerMX, m:Media):void
+		{
+			trace("PlaceMarkerEditorMediaDisplayView: didSelectMediaItem()");
+			placeMarker.imageMatchMediaId = m.mediaId;
+			placeMarker.imageMatchMedia = m;
+
+			this.pushDataIntoGUI();
+
+		}
+
+
+
+
+		public function handleLoadImageMatchMedia(obj:Object):void{
+			trace("In handleLoadImageMatchMedia() Result called with obj = " + obj + "; Result = " + obj.result);
+			if (obj.result.returnCode != 0)
+			{
+				trace("Bad loading of media attempt... let's see what happened.  Error = '" + obj.result.returnCodeDescription + "'");
+				var msg:String = obj.result.returnCodeDescription;
+				Alert.show("Error Was: " + msg, "Error While Loading Media");
+				return;
+			}
+
+			placeMarker.imageMatchMedia = new Media();
+			placeMarker.imageMatchMedia.fileName = obj.result.data.file_name;
+			placeMarker.imageMatchMedia.isDefault = obj.result.data.is_default;
+			placeMarker.imageMatchMedia.mediaId = obj.result.data.media_id;
+			placeMarker.imageMatchMedia.name = obj.result.data.name;
+			placeMarker.imageMatchMedia.type = obj.result.data.type;
+			placeMarker.imageMatchMedia.urlPath = obj.result.data.url_path;
+
+			pushDataIntoGUI();
+		}
+
+		public function isPlaceMarkDataLoaded():Boolean
+		{
+			if (this.placeMark != null)
+			{
+				return true;
+			}
+			return false;
+		}
+
+		public function handleCloseButton(evt:MouseEvent):void
+		{
+			trace("Close button clicked...");
+			var de:DynamicEvent = new DynamicEvent(AppConstants.DYNAMICEVENT_CLOSEIMAGEMATCHEDITOR);
+			AppDynamicEventManager.getInstance().dispatchEvent(de);
+		}
+
+
+		public function handleFault(obj:Object):void
+		{
+			trace("Fault called: " + obj.message);
+			Alert.show("Error occurred: " + obj.message, "Problems In ImageMatch Editor");
+		}
+
+	}
+}


FLEX-18746 Added unit test (current fails).

error: pathspec 'frameworks/projects/mx/tests/mx/controls/Tree_FLEX_18746_Tests.as' did not match any file(s) known to git

--- frameworks/projects/mx/tests/mx/controls/Tree_FLEX_18746_Tests.as
+++ frameworks/projects/mx/tests/mx/controls/Tree_FLEX_18746_Tests.as
@@ -0,0 +1,112 @@
+package mx.controls {
+    import flash.events.Event;
+    import flash.events.EventDispatcher;
+
+    import mx.collections.ArrayCollection;
+    import mx.core.mx_internal;
+
+    import org.flexunit.assertThat;
+    import org.flexunit.async.Async;
+    import org.fluint.uiImpersonation.UIImpersonator;
+
+    use namespace mx_internal;
+
+    public class Tree_FLEX_18746_Tests
+    {
+        private static var noEnterFramesToWait:int = NaN;
+        private static const _finishNotifier:EventDispatcher = new EventDispatcher();
+
+        private static var _sut:Tree;
+        private static var child:Object = {label: "Item"};
+        private static var parent0:Object = {label: "Folder 0", children: new ArrayCollection()};
+        private static var parent1:Object = {label: "Folder 1", children: new ArrayCollection([child])};
+
+
+        [Before]
+        public function setUp():void
+        {
+            _sut = new Tree();
+            _sut.width = 200;
+            _sut.height = 200;
+            UIImpersonator.addChild(_sut);
+        }
+
+        [After]
+        public function tearDown():void
+        {
+            UIImpersonator.removeAllChildren();
+            _sut = null;
+        }
+
+
+        //--------------------------------------------------------------------------
+        //
+        //  Test method
+        //
+        //--------------------------------------------------------------------------
+
+        [Test(async, timeout=1000)]
+        public function test_object_removed_from_stage_via_code_is_not_initialized():void
+        {
+            //given
+            const dataProvider:ArrayCollection = new ArrayCollection();
+            dataProvider.addItem(parent0);
+            dataProvider.addItem(parent1);
+
+            //when
+            _sut.dataProvider = dataProvider;
+
+            //then wait a few frames
+            noEnterFramesToWait = 2;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_expand_second_folder, 200);
+        }
+
+
+        private function then_expand_second_folder(event:Event, passThroughData:Object):void
+        {
+            //when
+            _sut.expandItem(parent1, true, true, true);
+
+            //then wait a bit
+            noEnterFramesToWait = 5;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_move_child_to_first_parent_and_expand_it, 500);
+        }
+
+        private function then_move_child_to_first_parent_and_expand_it(event:Event, passThroughData:Object):void
+        {
+            //then
+            assertThat(_sut.isItemOpen(parent1));
+
+            //when
+            ArrayCollection(parent1.children).removeItemAt(0);
+            _sut.expandItem(parent0, true, true, true);
+            ArrayCollection(parent0.children).addItem(child);
+
+            //then wait a bit
+            noEnterFramesToWait = 1;
+            UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+            Async.handleEvent(this, _finishNotifier, Event.COMPLETE, then_contract_second_folder, 200);
+        }
+
+        private static function then_contract_second_folder(event:Event, passThroughData:Object):void
+        {
+            //when
+            _sut.expandItem(parent1, false, true, true);
+
+            //then no error was thrown
+            assertThat(true);
+        }
+
+
+        private static function onEnterFrame(event:Event):void
+        {
+            if(!--noEnterFramesToWait)
+            {
+                UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
+                _finishNotifier.dispatchEvent(new Event(Event.COMPLETE));
+            }
+        }
+    }
+}


cosmetic

cosmetic

fatal: unable to access 'https://github.com/pubnub/flash.git/': The requested URL returned error: 403


Board lines slightly thinner.

Board lines slightly thinner.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/rlowke/lowkemedia.git/'


disable discovery service test

disable discovery service test

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/noikiy/amfphp-2.0.git/'


Добавлен EmptyLoadingFailHandler

Добавлен EmptyLoadingFailHandler

error: pathspec 'src/main/org/shypl/common/loader/EmptyLoadingFailHandler.as' did not match any file(s) known to git

--- src/main/org/shypl/common/loader/EmptyLoadingFailHandler.as
+++ src/main/org/shypl/common/loader/EmptyLoadingFailHandler.as
@@ -0,0 +1,6 @@
+package org.shypl.common.loader {
+	public class EmptyLoadingFailHandler implements LoadingFailHandler {
+		public function handleLoadingFail(url:String):void {
+		}
+	}
+}


Implemented Feature #1308 WireframeDebugController

error: pathspec 'src/aerys/minko/scene/controller/debug/WireframeDebugController.as' did not match any file(s) known to git

--- src/aerys/minko/scene/controller/debug/WireframeDebugController.as
+++ src/aerys/minko/scene/controller/debug/WireframeDebugController.as
@@ -0,0 +1,89 @@
+package aerys.minko.scene.controller.debug
+{
+	import aerys.minko.render.geometry.primitive.LineGeometry;
+	import aerys.minko.render.geometry.stream.iterator.TriangleIterator;
+	import aerys.minko.render.geometry.stream.iterator.TriangleReference;
+	import aerys.minko.render.material.line.LineMaterial;
+	import aerys.minko.scene.controller.AbstractController;
+	import aerys.minko.scene.node.Group;
+	import aerys.minko.scene.node.Mesh;
+
+	import flash.utils.Dictionary;
+
+	public final class WireframeDebugController extends AbstractController
+	{
+		private var _wireframeMaterial	: LineMaterial;
+		private var _targetToWireframe	: Dictionary	= new Dictionary();
+
+		public function get material() : LineMaterial
+		{
+			return _wireframeMaterial
+				|| (_wireframeMaterial = new LineMaterial({diffuseColor : 0xffffffff, lineThickness	: 1.}));
+		}
+
+		public function WireframeDebugController()
+		{
+			super(Mesh);
+
+			initialize();
+		}
+
+		private function initialize() : void
+		{
+			targetAdded.add(targetAddedHandler);
+			targetRemoved.add(targetRemovedHandler);
+		}
+
+		private function targetAddedHandler(ctrl	: WireframeDebugController,
+											target	: Mesh) : void
+		{
+			target.added.add(addedHandler);
+			target.removed.add(removedHandler);
+		}
+
+		private function addedHandler(target 	: Mesh,
+									  ancestor	: Group) : void
+		{
+			if (!target.scene)
+				return ;
+
+			var triangles	: TriangleIterator = new TriangleIterator(
+				target.geometry.getVertexStream(),
+				target.geometry.indexStream
+			);
+			var linesGeom	: LineGeometry		= new LineGeometry();
+			for each (var triangle : TriangleReference in triangles)
+			{
+				linesGeom.moveTo(triangle.v0.x, triangle.v0.y, triangle.v0.z)
+					.lineTo(triangle.v1.x, triangle.v1.y, triangle.v1.z)
+					.lineTo(triangle.v2.x, triangle.v2.y, triangle.v2.z)
+					.lineTo(triangle.v0.x, triangle.v0.y, triangle.v0.z);
+			}
+
+			var lines		: Mesh				= new Mesh(linesGeom, this.material);
+			_targetToWireframe[target] = lines;
+
+			target.parent.addChild(lines);
+		}
+
+		private function removeWireframes(target : Mesh) : void
+		{
+			if (_targetToWireframe[target])
+				_targetToWireframe[target].parent = null;
+			_targetToWireframe[target] = null;
+		}
+
+		private function targetRemovedHandler(ctrl		: WireframeDebugController,
+											  target	: Mesh) : void
+		{
+			target.added.remove(addedHandler);
+			target.removed.remove(removedHandler);
+			removeWireframes(target);
+		}
+
+		private function removedHandler(target : Mesh, ancestor : Group) : void
+		{
+			removeWireframes(target);
+		}
+	}
+}


Remove import statement for file removed in revision r287.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/leymannx/svgweb.git/'


Collections.shuffle().

Collections.shuffle().

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

error: pathspec 'src/as/com/threerings/util/Collections.as' did not match any file(s) known to git

--- src/as/com/threerings/util/Collections.as
+++ src/as/com/threerings/util/Collections.as
@@ -0,0 +1,25 @@
+package com.threerings.util {
+
+import mx.collections.ListCollectionView;
+
+/**
+ * Various collections-related utility methods.
+ */
+public class Collections
+{
+    /**
+     * Randomly shuffle the elements in the specified list.
+     */
+    public static function shuffle (collection :ListCollectionView) :void
+    {
+        // starting from the end of the list, repeatedly swap the element
+        // in question with a random element previous to it up
+        // to and including itself
+        for (var ii :int  = collection.length - 1; ii > 0; ii--) {
+            var idx :int = int(Math.random() * (ii + 1))
+            var item :Object = collection.getItemAt(idx);
+            collection.setItemAt(collection.setItemAt(item, ii), idx);
+        }
+    }
+}
+}