/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/*
 * Copyright 2013 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package avm1lib {
import flash.display.Loader;
import flash.display.MovieClip;
import flash.events.Event;
import flash.external.ExternalInterface;
import flash.geom.ColorTransform;
import flash.geom.Rectangle;
import flash.media.Sound;
import flash.media.SoundMixer;
import flash.net.SharedObject;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.system.Capabilities;
import flash.system.fscommand;
import flash.text.TextFormat;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;
import flash.utils.clearInterval;
import flash.utils.clearTimeout;
import flash.utils.getTimer;

[native(cls="AS2Globals")]
public dynamic class AS2Globals {
  // TODO: change this when entering a domain.
  public static var instance;
  public var _global;

  public var flash:Object;

  public function AS2Globals() {
    AS2Globals.instance = this;
    this._global = this;
    this.flash = createFlashObject();
  }

  private function createFlashObject():Object {
    return {
      _MovieClip: AS2MovieClip,
      display: {},
      external: {
        ExternalInterface: ExternalInterface
      },
      filters: {},
      geom: {},
      text: {}
    };
  }

  public function $asfunction(link) {
    notImplemented('AS2Globals.$asfunction');
  }

  public native function ASSetPropFlags(obj, children, flags, allowFalse);

  public function call(frame) {
    var nativeTarget = AS2Utils.resolveTarget();
    nativeTarget._callFrame(frame);
  }
  public function chr(number) {
    return String.fromCharCode(number);
  }
  public var clearInterval:Function = clearInterval;
  public var clearTimeout:Function = clearTimeout;

  public function duplicateMovieClip(target, newname, depth) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    nativeTarget.duplicateMovieClip(newname, depth);
  }

  public var fscommand:Function = fscommand;

  public native function escape(str: String): String;
  public native function unescape(str: String): String;

  public function getAS2Property(target, index) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    return nativeTarget[PropertiesIndexMap[index]];
  }

  public var getTimer:Function = getTimer;

  public function getURL(url, target, method) {
    var request = new URLRequest(url);
    if (method) {
      request.method = method;
    }
    if (typeof target === 'string' && target.indexOf('_level') === 0) {
      loadMovieNum(url, +target.substr(6), method);
      return;
    }
    navigateToURL(request, target);
  }

  public function getVersion() {
    return Capabilities.version;
  }

  private native function _addToPendingScripts(subject:Object, fn:Function, args:Array = null);

  public function gotoAndPlay(scene, frame) {
    var nativeTarget = AS2Utils.resolveTarget();
    if (arguments.length < 2) {
      _addToPendingScripts(nativeTarget, nativeTarget.gotoAndPlay, [arguments[0]]);
    } else {
      _addToPendingScripts(nativeTarget, nativeTarget.gotoAndPlay, [arguments[1], arguments[0]]); // scene and frame are swapped for AS3
    }
  }

  public function gotoAndStop(scene, frame) {
    var nativeTarget = AS2Utils.resolveTarget();
    if (arguments.length < 2) {
      _addToPendingScripts(nativeTarget, nativeTarget.gotoAndStop, [arguments[0]]);
    } else {
      _addToPendingScripts(nativeTarget, nativeTarget.gotoAndStop, [arguments[1], arguments[0]]); // scene and frame are swapped for AS3
    }
  }

  public function gotoLabel(label) {
    var nativeTarget = AS2Utils.resolveTarget();
    _addToPendingScripts(nativeTarget, function (subject, label) {
      subject._gotoLabel(label);
    }, [nativeTarget, label]);
  }

  public function ifFrameLoaded(scene, frame) {
    // ignoring scene parameter ?
    var nativeTarget = AS2Utils.resolveTarget();
    var frameNum = arguments.length < 2 ? arguments[0] : arguments[1];
    var framesLoaded = nativeTarget._framesloaded;
    return frameNum < framesLoaded;
  }

  public function int(value: *): * {
    return value | 0;
  }

  public function length(expression: Object): Number {
    return ('' + expression).length; // ASCII Only?
  }

  public function loadMovie(url: String, target: Object, method: String): void {
    // some swfs are using loadMovie to call fscommmand
    if (url && url.toLowerCase().indexOf('fscommand:') === 0) {
      this.fscommand(url.substring('fscommand:'.length), target);
      return;
    }
    var levelStr: String;
    var loadLevel: Boolean = typeof target === 'string' && target.indexOf('_level') === 0 &&
                             int(levelStr = target.charAt(6)) == levelStr;
    var loader:Loader = new Loader();
    if (loadLevel) {
      _setLevel(int(levelStr), loader);
      var request: URLRequest = new URLRequest(url);
      if (method) {
        request.method = method;
      }
      loader.load(request);
    } else {
      var nativeTarget: flash.display.MovieClip = AS2Utils.resolveTarget(target);
      nativeTarget.loadMovie(url, method);
    }
  }

  private native function _setLevel(level:uint, loader:Loader);

  public function loadMovieNum(url, level, method) {
    // some swfs are using loadMovieNum to call fscommmand
    if (url && url.toLowerCase().indexOf('fscommand:') === 0) {
      return this.fscommand(url.substring('fscommand:'.length));
    }

    var loader:Loader = new Loader();
    _setLevel(level, loader);
    var request = new URLRequest(url);
    if (method) {
      request.method = method;
    }
    loader.load(request);
  }
  public function loadVariables(url: String, target: Object, method: String = ''): void {
    var nativeTarget = AS2Utils.resolveTarget(target);
    var request = new URLRequest(url);
    if (method) {
      request.method = method;
    }
    var loader: URLLoader = new URLLoader(request);
    loader.dataFormat = URLLoaderDataFormat.VARIABLES;
    function completeHandler(event: Event): void {
      loader.removeEventListener(Event.COMPLETE, completeHandler);
      for (var key: String in loader.data) {
        nativeTarget[key] = loader.data[key];
      }
    }
    loader.addEventListener(Event.COMPLETE, completeHandler);
  }
  public function mbchr(number) {
    return String.fromCharCode(number);
  }
  public function mblength(expression) {
    return ('' + expression).length;
  }
  public function mbord(character) {
    return ('' + character).charCodeAt(0);
  }
  public function mbsubstring(value, index, count) {
    if (index !== (0 | index) || count !== (0 | count)) {
      // index or count are not integers, the result is the empty string.
      return '';
    }
    return ('' + value).substr(index, count);
  }
  public function nextFrame() {
    var nativeTarget = AS2Utils.resolveTarget();
    _addToPendingScripts(nativeTarget, nativeTarget.nextFrame);
  }
  public function nextScene() {
    var nativeTarget = AS2Utils.resolveTarget();
    _addToPendingScripts(nativeTarget, nativeTarget.nextScene);
  }
  public function ord(character) {
    return ('' + character).charCodeAt(0); // ASCII only?
  }
  public function play() {
    var nativeTarget = AS2Utils.resolveTarget();
    nativeTarget.play();
  }
  public function prevFrame() {
    var nativeTarget = AS2Utils.resolveTarget();
    _addToPendingScripts(nativeTarget, nativeTarget.prevFrame);
  }
  public function prevScene() {
    var nativeTarget = AS2Utils.resolveTarget();
    _addToPendingScripts(nativeTarget, nativeTarget.prevScene);
  }
  public function print(target, boundingBox) {
    // flash.printing.PrintJob
    notImplemented('AS2Globals.print');
  }
  public function printAsBitmap(target, boundingBox) {
    notImplemented('AS2Globals.printAsBitmap');
  }
  public function printAsBitmapNum(level, boundingBox) {
    notImplemented('AS2Globals.printAsBitmapNum');
  }
  public function printNum(level, bondingBox) {
    notImplemented('AS2Globals.printNum');
  }
  public function random(value) {
    return 0 | (Math.random() * (0 | value));
  }
  public function removeMovieClip(target) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    nativeTarget.removeMovieClip();
  }
  public function setInterval(): * {
    // AVM1 setInterval silently swallows everything that vaguely looks like an error.
    if (arguments.length < 2) {
      return undefined;
    }
    var args: Array = [];
    if (typeof arguments[0] === 'function') {
      args = arguments;
    } else {
      if (arguments.length < 3) {
        return undefined;
      }
      var obj: Object = arguments[0];
      var funName: * = arguments[1];
      if (!(obj && typeof obj === 'object' && typeof funName === 'string')) {
        return undefined;
      }
      args[0] = function (): void {
        obj[funName].apply(obj, arguments);
      };
      for (var i: uint = 2; i < arguments.length; i++) {
        args.push(arguments[i]);
      }
    }
    // Unconditionally coerce interval to int, as one would do.
    args[1] |= 0;
    return flash.utils.setInterval.apply(null, args);
  }
  public function setAS2Property(target, index, value) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    nativeTarget[PropertiesIndexMap[index]] = value;
  }
  public function setTimeout() {
    // AVM1 setTimeout silently swallows most things that vaguely look like errors.
    if (arguments.length < 2 || typeof arguments[0] !== 'function')
    {
      return undefined;
    }
    // Unconditionally coerce interval to int, as one would do.
    arguments[1] |= 0;
    return flash.utils.setTimeout.apply(null, arguments);
  }
  public function showRedrawRegions(enable, color) {
    // flash.profiler.showRedrawRegions.apply(null, arguments);
    notImplemented('AS2Globals.showRedrawRegions');
  }
  public function startDrag(target, lock, left, top, right, bottom) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    nativeTarget.startDrag(lock, arguments.length < 3 ? null :
      new flash.geom.Rectangle(left, top, right - left, bottom - top));
  }
  public function stop() {
    var nativeTarget = AS2Utils.resolveTarget();
    nativeTarget.stop();
  }
  public function stopAllSounds() {
    SoundMixer.stopAll();
  }
  public function stopDrag(target) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    nativeTarget.stopDrag();
  }
  public function substring(value, index, count) {
    return mbsubstring(value, index, count); // ASCII Only?
  }
  public function targetPath(target) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    return nativeTarget._target;
  }
  public function toggleHighQuality() {
    // flash.display.Stage.quality
    notImplemented('AS2Globals.toggleHighQuality');
  }
  public native function trace(expression);

  public function unloadMovie(target) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    nativeTarget.unloadMovie();
  }
  public function unloadMovieNum(level) {
    var nativeTarget = AS2Utils.resolveLevel(level);
    nativeTarget.unloadMovie();
  }
  public function updateAfterEvent() {
    // flash.events.TimerEvent.updateAfterEvent
    notImplemented('AS2Globals.updateAfterEvent');
  }

  // built-ins
  public var NaN:Number = NaN;
  public var Infinity:Number = Number.POSITIVE_INFINITY;
  public var isFinite:Function = isFinite;
  public var isNaN:Function = isNaN;
  public var parseFloat:Function = parseFloat;
  public var parseInt:Function = parseInt;
  public var undefined:* = undefined;
  public var MovieClip:Class = AS2MovieClip;
  public var AsBroadcaster:Class = AS2Broadcaster;
  public var System:Class = AS2System;
  public var Stage:Class = AS2Stage;
  public var Button:Class = AS2Button;
  public var TextField:Class = AS2TextField;
  public var Color:Class = AS2Color;
  public var Key:Class = AS2Key;
  public var Mouse:Class = AS2Mouse;
  public var MovieClipLoader:Class = AS2MovieClipLoader;

  public var Sound:Class = AS2Sound;
  public var SharedObject:Class = SharedObject;
  public var ContextMenu:Class = ContextMenu;
  public var ContextMenuItem:Class = ContextMenuItem;
  public var ColorTransform:Class = ColorTransform;
  public var Point:Class = flash.geom.Point;
  public var Rectangle:Class = Rectangle;
  public var TextFormat:Class = TextFormat;

  private static native function _addInternalClasses(proto:Object):void;

  {
    // Initializing all global objects/classes
    var classes = [Object, Function, Array, Number, Math, Boolean, Date, RegExp, String];
    _addInternalClasses(prototype);
  }
}
}

var PropertiesIndexMap:Array = [
  '_x', '_y', '_xscale', '_yscale', '_currentframe', '_totalframes', '_alpha',
  '_visible', '_width', '_height', '_rotation', '_target', '_framesloaded',
  '_name', '_droptarget', '_url', '_highquality', '_focusrect',
  '_soundbuftime', '_quality', '_xmouse', '_ymouse'
];

/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/*
 * Copyright 2013 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package avm1lib {
import flash.display.Loader;
import flash.display.MovieClip;
import flash.events.Event;
import flash.external.ExternalInterface;
import flash.geom.ColorTransform;
import flash.geom.Rectangle;
import flash.media.Sound;
import flash.media.SoundMixer;
import flash.net.SharedObject;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.system.Capabilities;
import flash.system.fscommand;
import flash.text.TextFormat;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;
import flash.utils.clearInterval;
import flash.utils.clearTimeout;
import flash.utils.getTimer;

[native(cls="AS2Globals")]
public dynamic class AS2Globals {
  // TODO: change this when entering a domain.
  public static var instance;
  public var _global;

  public var flash:Object;

  public function AS2Globals() {
    AS2Globals.instance = this;
    this._global = this;
    this.flash = createFlashObject();
  }

  private function createFlashObject():Object {
    return {
      _MovieClip: AS2MovieClip,
      display: {},
      external: {
        ExternalInterface: ExternalInterface
      },
      filters: {},
      geom: {},
      text: {}
    };
  }

  public function $asfunction(link) {
    notImplemented('AS2Globals.$asfunction');
  }

  public native function ASSetPropFlags(obj, children, flags, allowFalse);

  public function call(frame) {
    var nativeTarget = AS2Utils.resolveTarget();
    nativeTarget._callFrame(frame);
  }
  public function chr(number) {
    return String.fromCharCode(number);
  }
  public var clearInterval:Function = flash.utils.clearInterval;
  public var clearTimeout:Function = flash.utils.clearTimeout;

  public function duplicateMovieClip(target, newname, depth) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    nativeTarget.duplicateMovieClip(newname, depth);
  }

  public var fscommand:Function = flash.system.fscommand;

  public native function escape(str: String): String;
  public native function unescape(str: String): String;

  public function getAS2Property(target, index) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    return nativeTarget[PropertiesIndexMap[index]];
  }

  public var getTimer:Function = flash.utils.getTimer;

  public function getURL(url, target, method) {
    var request = new URLRequest(url);
    if (method) {
      request.method = method;
    }
    if (typeof target === 'string' && target.indexOf('_level') === 0) {
      loadMovieNum(url, +target.substr(6), method);
      return;
    }
    navigateToURL(request, target);
  }

  public function getVersion() {
    return Capabilities.version;
  }

  private native function _addToPendingScripts(subject:Object, fn:Function, args:Array = null);

  public function gotoAndPlay(scene, frame) {
    var nativeTarget = AS2Utils.resolveTarget();
    if (arguments.length < 2) {
      _addToPendingScripts(nativeTarget, nativeTarget.gotoAndPlay, [arguments[0]]);
    } else {
      _addToPendingScripts(nativeTarget, nativeTarget.gotoAndPlay, [arguments[1], arguments[0]]); // scene and frame are swapped for AS3
    }
  }

  public function gotoAndStop(scene, frame) {
    var nativeTarget = AS2Utils.resolveTarget();
    if (arguments.length < 2) {
      _addToPendingScripts(nativeTarget, nativeTarget.gotoAndStop, [arguments[0]]);
    } else {
      _addToPendingScripts(nativeTarget, nativeTarget.gotoAndStop, [arguments[1], arguments[0]]); // scene and frame are swapped for AS3
    }
  }

  public function gotoLabel(label) {
    var nativeTarget = AS2Utils.resolveTarget();
    _addToPendingScripts(nativeTarget, function (subject, label) {
      subject._gotoLabel(label);
    }, [nativeTarget, label]);
  }

  public function ifFrameLoaded(scene, frame) {
    // ignoring scene parameter ?
    var nativeTarget = AS2Utils.resolveTarget();
    var frameNum = arguments.length < 2 ? arguments[0] : arguments[1];
    var framesLoaded = nativeTarget._framesloaded;
    return frameNum < framesLoaded;
  }

  public function int(value: *): * {
    return value | 0;
  }

  public function length(expression: Object): Number {
    return ('' + expression).length; // ASCII Only?
  }

  public function loadMovie(url: String, target: Object, method: String): void {
    // some swfs are using loadMovie to call fscommmand
    if (url && url.toLowerCase().indexOf('fscommand:') === 0) {
      this.fscommand(url.substring('fscommand:'.length), target);
      return;
    }
    var levelStr: String;
    var loadLevel: Boolean = typeof target === 'string' && target.indexOf('_level') === 0 &&
                             int(levelStr = target.charAt(6)) == levelStr;
    var loader:Loader = new Loader();
    if (loadLevel) {
      _setLevel(int(levelStr), loader);
      var request: URLRequest = new URLRequest(url);
      if (method) {
        request.method = method;
      }
      loader.load(request);
    } else {
      var nativeTarget: flash.display.MovieClip = AS2Utils.resolveTarget(target);
      nativeTarget.loadMovie(url, method);
    }
  }

  private native function _setLevel(level:uint, loader:Loader);

  public function loadMovieNum(url, level, method) {
    // some swfs are using loadMovieNum to call fscommmand
    if (url && url.toLowerCase().indexOf('fscommand:') === 0) {
      return this.fscommand(url.substring('fscommand:'.length));
    }

    var loader:Loader = new Loader();
    _setLevel(level, loader);
    var request = new URLRequest(url);
    if (method) {
      request.method = method;
    }
    loader.load(request);
  }
  public function loadVariables(url: String, target: Object, method: String = ''): void {
    var nativeTarget = AS2Utils.resolveTarget(target);
    var request = new URLRequest(url);
    if (method) {
      request.method = method;
    }
    var loader: URLLoader = new URLLoader(request);
    loader.dataFormat = URLLoaderDataFormat.VARIABLES;
    function completeHandler(event: Event): void {
      loader.removeEventListener(Event.COMPLETE, completeHandler);
      for (var key: String in loader.data) {
        nativeTarget[key] = loader.data[key];
      }
    }
    loader.addEventListener(Event.COMPLETE, completeHandler);
  }
  public function mbchr(number) {
    return String.fromCharCode(number);
  }
  public function mblength(expression) {
    return ('' + expression).length;
  }
  public function mbord(character) {
    return ('' + character).charCodeAt(0);
  }
  public function mbsubstring(value, index, count) {
    if (index !== (0 | index) || count !== (0 | count)) {
      // index or count are not integers, the result is the empty string.
      return '';
    }
    return ('' + value).substr(index, count);
  }
  public function nextFrame() {
    var nativeTarget = AS2Utils.resolveTarget();
    _addToPendingScripts(nativeTarget, nativeTarget.nextFrame);
  }
  public function nextScene() {
    var nativeTarget = AS2Utils.resolveTarget();
    _addToPendingScripts(nativeTarget, nativeTarget.nextScene);
  }
  public function ord(character) {
    return ('' + character).charCodeAt(0); // ASCII only?
  }
  public function play() {
    var nativeTarget = AS2Utils.resolveTarget();
    nativeTarget.play();
  }
  public function prevFrame() {
    var nativeTarget = AS2Utils.resolveTarget();
    _addToPendingScripts(nativeTarget, nativeTarget.prevFrame);
  }
  public function prevScene() {
    var nativeTarget = AS2Utils.resolveTarget();
    _addToPendingScripts(nativeTarget, nativeTarget.prevScene);
  }
  public function print(target, boundingBox) {
    // flash.printing.PrintJob
    notImplemented('AS2Globals.print');
  }
  public function printAsBitmap(target, boundingBox) {
    notImplemented('AS2Globals.printAsBitmap');
  }
  public function printAsBitmapNum(level, boundingBox) {
    notImplemented('AS2Globals.printAsBitmapNum');
  }
  public function printNum(level, bondingBox) {
    notImplemented('AS2Globals.printNum');
  }
  public function random(value) {
    return 0 | (Math.random() * (0 | value));
  }
  public function removeMovieClip(target) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    nativeTarget.removeMovieClip();
  }
  public function setInterval(): * {
    // AVM1 setInterval silently swallows everything that vaguely looks like an error.
    if (arguments.length < 2) {
      return undefined;
    }
    var args: Array = [];
    if (typeof arguments[0] === 'function') {
      args = arguments;
    } else {
      if (arguments.length < 3) {
        return undefined;
      }
      var obj: Object = arguments[0];
      var funName: * = arguments[1];
      if (!(obj && typeof obj === 'object' && typeof funName === 'string')) {
        return undefined;
      }
      args[0] = function (): void {
        obj[funName].apply(obj, arguments);
      };
      for (var i: uint = 2; i < arguments.length; i++) {
        args.push(arguments[i]);
      }
    }
    // Unconditionally coerce interval to int, as one would do.
    args[1] |= 0;
    return flash.utils.setInterval.apply(null, args);
  }
  public function setAS2Property(target, index, value) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    nativeTarget[PropertiesIndexMap[index]] = value;
  }
  public function setTimeout() {
    // AVM1 setTimeout silently swallows most things that vaguely look like errors.
    if (arguments.length < 2 || typeof arguments[0] !== 'function')
    {
      return undefined;
    }
    // Unconditionally coerce interval to int, as one would do.
    arguments[1] |= 0;
    return flash.utils.setTimeout.apply(null, arguments);
  }
  public function showRedrawRegions(enable, color) {
    // flash.profiler.showRedrawRegions.apply(null, arguments);
    notImplemented('AS2Globals.showRedrawRegions');
  }
  public function startDrag(target, lock, left, top, right, bottom) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    nativeTarget.startDrag(lock, arguments.length < 3 ? null :
      new flash.geom.Rectangle(left, top, right - left, bottom - top));
  }
  public function stop() {
    var nativeTarget = AS2Utils.resolveTarget();
    nativeTarget.stop();
  }
  public function stopAllSounds() {
    SoundMixer.stopAll();
  }
  public function stopDrag(target) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    nativeTarget.stopDrag();
  }
  public function substring(value, index, count) {
    return mbsubstring(value, index, count); // ASCII Only?
  }
  public function targetPath(target) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    return nativeTarget._target;
  }
  public function toggleHighQuality() {
    // flash.display.Stage.quality
    notImplemented('AS2Globals.toggleHighQuality');
  }
  public native function trace(expression);

  public function unloadMovie(target) {
    var nativeTarget = AS2Utils.resolveTarget(target);
    nativeTarget.unloadMovie();
  }
  public function unloadMovieNum(level) {
    var nativeTarget = AS2Utils.resolveLevel(level);
    nativeTarget.unloadMovie();
  }
  public function updateAfterEvent() {
    // flash.events.TimerEvent.updateAfterEvent
    notImplemented('AS2Globals.updateAfterEvent');
  }

  // built-ins
  public var NaN:Number = Number.NaN;
  public var Infinity:Number = Number.POSITIVE_INFINITY;

  [native("isFinite")]
  public native function isFinite(n:Number = void 0):Boolean;

  [native("isNaN")]
  public native function isNaN(n:Number = void 0):Boolean;

  [native("parseFloat")]
  public native function parseFloat(str:String = "NaN"):Number;

  [native("parseInt")]
  public native function parseInt(s:String = "NaN", radix = 0):Number;

  public var undefined:* = undefined;
  public var MovieClip:Class = AS2MovieClip;
  public var AsBroadcaster:Class = AS2Broadcaster;
  public var System:Class = AS2System;
  public var Stage:Class = AS2Stage;
  public var Button:Class = AS2Button;
  public var TextField:Class = AS2TextField;
  public var Color:Class = AS2Color;
  public var Key:Class = AS2Key;
  public var Mouse:Class = AS2Mouse;
  public var MovieClipLoader:Class = AS2MovieClipLoader;

  public var Sound:Class = AS2Sound;
  public var SharedObject:Class = SharedObject;
  public var ContextMenu:Class = ContextMenu;
  public var ContextMenuItem:Class = ContextMenuItem;
  public var ColorTransform:Class = ColorTransform;
  public var Point:Class = flash.geom.Point;
  public var Rectangle:Class = Rectangle;
  public var TextFormat:Class = TextFormat;

  private static native function _addInternalClasses(proto:Object):void;

  {
    // Initializing all global objects/classes
    var classes = [Object, Function, Array, Number, Math, Boolean, Date, RegExp, String];
    _addInternalClasses(prototype);
  }
}
}

var PropertiesIndexMap:Array = [
  '_x', '_y', '_xscale', '_yscale', '_currentframe', '_totalframes', '_alpha',
  '_visible', '_width', '_height', '_rotation', '_target', '_framesloaded',
  '_name', '_droptarget', '_url', '_highquality', '_focusrect',
  '_soundbuftime', '_quality', '_xmouse', '_ymouse'
];

Fix self references to variable definitions in AS3 code.


/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mangui.hls {

    import flash.display.Stage;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.net.NetConnection;
    import flash.net.NetStream;
    import flash.net.URLLoader;
    import flash.net.URLStream;
    import org.mangui.hls.controller.AudioTrackController;
    import org.mangui.hls.controller.LevelController;
    import org.mangui.hls.event.HLSEvent;
    import org.mangui.hls.loader.AltAudioLevelLoader;
    import org.mangui.hls.loader.LevelLoader;
    import org.mangui.hls.model.AudioTrack;
    import org.mangui.hls.model.Level;
    import org.mangui.hls.playlist.AltAudioTrack;
    import org.mangui.hls.stream.HLSNetStream;
    import org.mangui.hls.stream.StreamBuffer;

    CONFIG::LOGGING {
        import org.mangui.hls.utils.Log;
    }
    /** Class that manages the streaming process. **/
    public class HLS extends EventDispatcher {
        private var _levelLoader : LevelLoader;
        private var _altAudioLevelLoader : AltAudioLevelLoader;
        private var _audioTrackController : AudioTrackController;
        private var _levelController : LevelController;
        private var _streamBuffer : StreamBuffer;
        /** HLS NetStream **/
        private var _hlsNetStream : HLSNetStream;
        /** HLS URLStream/URLLoader **/
        private var _hlsURLStream : Class;
        private var _hlsURLLoader : Class;
        private var _client : Object = {};
        private var _stage : Stage;
        /* level handling */
        private var _level : int;
        /* overrided quality_manual_level level */
        private var _manual_level : int = -1;

        /** Create and connect all components. **/
        public function HLS() {
            var connection : NetConnection = new NetConnection();
            connection.connect(null);
            _levelLoader = new LevelLoader(this);
            _altAudioLevelLoader = new AltAudioLevelLoader(this);
            _audioTrackController = new AudioTrackController(this);
            _levelController = new LevelController(this);
            _streamBuffer = new StreamBuffer(this, _audioTrackController, _levelController);
            _hlsURLStream = URLStream as Class;
            _hlsURLLoader = URLLoader as Class;
            // default loader
            _hlsNetStream = new HLSNetStream(connection, this, _streamBuffer);
            this.addEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler);
        };

        /** Forward internal errors. **/
        override public function dispatchEvent(event : Event) : Boolean {
            if (event.type == HLSEvent.ERROR) {
                CONFIG::LOGGING {
                    Log.error((event as HLSEvent).error);
                }
                _hlsNetStream.close();
            }
            return super.dispatchEvent(event);
        };

        private function _levelSwitchHandler(event : HLSEvent) : void {
            _level = event.level;
        };

        public function dispose() : void {
            this.removeEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler);
            _levelLoader.dispose();
            _altAudioLevelLoader.dispose();
            _audioTrackController.dispose();
            _levelController.dispose();
            _hlsNetStream.dispose_();
            _streamBuffer.dispose();
            _levelLoader = null;
            _altAudioLevelLoader = null;
            _audioTrackController = null;
            _levelController = null;
            _hlsNetStream = null;
            _client = null;
            _stage = null;
            _hlsNetStream = null;
        }

        /** Return index of first quality level referenced in Manifest  **/
        public function get firstlevel() : int {
            return _levelController.firstlevel;
        };

        /** Return the quality level used when starting a fresh playback **/
        public function get startlevel() : int {
            return _levelController.startlevel;
        };

        /** Return the quality level used after a seek operation **/
        public function get seeklevel() : int {
            return _levelController.seeklevel;
        };

        /** Return the quality level of the currently played fragment **/
        public function get playbacklevel() : int {
            return _hlsNetStream.playbackLevel;
        };

        /** Return the quality level of last loaded fragment **/
        public function get level() : int {
            return _level;
        };

        /*  set quality level for next loaded fragment (-1 for automatic level selection) */
        public function set level(level : int) : void {
            _manual_level = level;
        };

        /* check if we are in automatic level selection mode */
        public function get autolevel() : Boolean {
            return (_manual_level == -1);
        };

        /* return manual level */
        public function get manuallevel() : int {
            return _manual_level;
        };

        /** Return a Vector of quality level **/
        public function get levels() : Vector.<Level> {
            return _levelLoader.levels;
        };

        /** Return the current playback position. **/
        public function get position() : Number {
            return _streamBuffer.position;
        };

        /** Return the current playback state. **/
        public function get playbackState() : String {
            return _hlsNetStream.playbackState;
        };

        /** Return the current seek state. **/
        public function get seekState() : String {
            return _hlsNetStream.seekState;
        };

        /** Return the type of stream (VOD/LIVE). **/
        public function get type() : String {
            return _levelLoader.type;
        };

        /** Load and parse a new HLS URL **/
        public function load(url : String) : void {
            _level = 0;
            _hlsNetStream.close();
            _levelLoader.load(url);
        };

        /** return HLS NetStream **/
        public function get stream() : NetStream {
            return _hlsNetStream;
        }

        public function get client() : Object {
            return _client;
        }

        public function set client(value : Object) : void {
            _client = value;
        }

        /** get current Buffer Length  **/
        public function get bufferLength() : Number {
            return _hlsNetStream.bufferLength;
        };

        /** get current back buffer Length  **/
        public function get backBufferLength() : Number {
            return _hlsNetStream.backBufferLength;
        };

        /** get audio tracks list**/
        public function get audioTracks() : Vector.<AudioTrack> {
            return _audioTrackController.audioTracks;
        };

        /** get alternate audio tracks list from playlist **/
        public function get altAudioTracks() : Vector.<AltAudioTrack> {
            return _levelLoader.altAudioTracks;
        };

        /** get index of the selected audio track (index in audio track lists) **/
        public function get audioTrack() : int {
            return _audioTrackController.audioTrack;
        };

        /** select an audio track, based on its index in audio track lists**/
        public function set audioTrack(val : int) : void {
            _audioTrackController.audioTrack = val;
        }

        /* set stage */
        public function set stage(stage : Stage) : void {
            _stage = stage;
        }

        /* get stage */
        public function get stage() : Stage {
            return _stage;
        }

        /* set URL stream loader */
        public function set URLstream(urlstream : Class) : void {
            _hlsURLStream = urlstream;
        }

        /* retrieve URL stream loader */
        public function get URLstream() : Class {
            return _hlsURLStream;
        }

        /* set URL stream loader */
        public function set URLloader(urlloader : Class) : void {
            _hlsURLLoader = urlloader;
        }

        /* retrieve URL stream loader */
        public function get URLloader() : Class {
            return _hlsURLLoader;
        }
    }
}

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mangui.hls {

    import flash.display.Stage;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.net.NetConnection;
    import flash.net.NetStream;
    import flash.net.URLLoader;
    import flash.net.URLStream;
    import org.mangui.hls.controller.AudioTrackController;
    import org.mangui.hls.controller.LevelController;
    import org.mangui.hls.event.HLSEvent;
    import org.mangui.hls.loader.AltAudioLevelLoader;
    import org.mangui.hls.loader.LevelLoader;
    import org.mangui.hls.model.AudioTrack;
    import org.mangui.hls.model.Level;
    import org.mangui.hls.playlist.AltAudioTrack;
    import org.mangui.hls.stream.HLSNetStream;
    import org.mangui.hls.stream.StreamBuffer;

    CONFIG::LOGGING {
        import org.mangui.hls.utils.Log;
    }
    /** Class that manages the streaming process. **/
    public class HLS extends EventDispatcher {
        private var _levelLoader : LevelLoader;
        private var _altAudioLevelLoader : AltAudioLevelLoader;
        private var _audioTrackController : AudioTrackController;
        private var _levelController : LevelController;
        private var _streamBuffer : StreamBuffer;
        /** HLS NetStream **/
        private var _hlsNetStream : HLSNetStream;
        /** HLS URLStream/URLLoader **/
        private var _hlsURLStream : Class;
        private var _hlsURLLoader : Class;
        private var _client : Object = {};
        private var _stage : Stage;
        /* level handling */
        private var _level : int;
        /* overrided quality_manual_level level */
        private var _manual_level : int = -1;

        /** Create and connect all components. **/
        public function HLS() {
            _levelLoader = new LevelLoader(this);
            _altAudioLevelLoader = new AltAudioLevelLoader(this);
            _audioTrackController = new AudioTrackController(this);
            _levelController = new LevelController(this);
            _streamBuffer = new StreamBuffer(this, _audioTrackController, _levelController);
            _hlsURLStream = URLStream as Class;
            _hlsURLLoader = URLLoader as Class;
            // default loader
            var connection : NetConnection = new NetConnection();
            connection.connect(null);
            _hlsNetStream = new HLSNetStream(connection, this, _streamBuffer);
            this.addEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler);
        };

        /** Forward internal errors. **/
        override public function dispatchEvent(event : Event) : Boolean {
            if (event.type == HLSEvent.ERROR) {
                CONFIG::LOGGING {
                    Log.error((event as HLSEvent).error);
                }
                _hlsNetStream.close();
            }
            return super.dispatchEvent(event);
        };

        private function _levelSwitchHandler(event : HLSEvent) : void {
            _level = event.level;
        };

        public function dispose() : void {
            this.removeEventListener(HLSEvent.LEVEL_SWITCH, _levelSwitchHandler);
            _levelLoader.dispose();
            _altAudioLevelLoader.dispose();
            _audioTrackController.dispose();
            _levelController.dispose();
            _hlsNetStream.dispose_();
            _streamBuffer.dispose();
            _levelLoader = null;
            _altAudioLevelLoader = null;
            _audioTrackController = null;
            _levelController = null;
            _hlsNetStream = null;
            _client = null;
            _stage = null;
            _hlsNetStream = null;
        }

        /** Return index of first quality level referenced in Manifest  **/
        public function get firstlevel() : int {
            return _levelController.firstlevel;
        };

        /** Return the quality level used when starting a fresh playback **/
        public function get startlevel() : int {
            return _levelController.startlevel;
        };

        /** Return the quality level used after a seek operation **/
        public function get seeklevel() : int {
            return _levelController.seeklevel;
        };

        /** Return the quality level of the currently played fragment **/
        public function get playbacklevel() : int {
            return _hlsNetStream.playbackLevel;
        };

        /** Return the quality level of last loaded fragment **/
        public function get level() : int {
            return _level;
        };

        /*  set quality level for next loaded fragment (-1 for automatic level selection) */
        public function set level(level : int) : void {
            _manual_level = level;
        };

        /* check if we are in automatic level selection mode */
        public function get autolevel() : Boolean {
            return (_manual_level == -1);
        };

        /* return manual level */
        public function get manuallevel() : int {
            return _manual_level;
        };

        /** Return a Vector of quality level **/
        public function get levels() : Vector.<Level> {
            return _levelLoader.levels;
        };

        /** Return the current playback position. **/
        public function get position() : Number {
            return _streamBuffer.position;
        };

        /** Return the current playback state. **/
        public function get playbackState() : String {
            return _hlsNetStream.playbackState;
        };

        /** Return the current seek state. **/
        public function get seekState() : String {
            return _hlsNetStream.seekState;
        };

        /** Return the type of stream (VOD/LIVE). **/
        public function get type() : String {
            return _levelLoader.type;
        };

        /** Load and parse a new HLS URL **/
        public function load(url : String) : void {
            _level = 0;
            _hlsNetStream.close();
            _levelLoader.load(url);
        };

        /** return HLS NetStream **/
        public function get stream() : NetStream {
            return _hlsNetStream;
        }

        public function get client() : Object {
            return _client;
        }

        public function set client(value : Object) : void {
            _client = value;
        }

        /** get current Buffer Length  **/
        public function get bufferLength() : Number {
            return _hlsNetStream.bufferLength;
        };

        /** get current back buffer Length  **/
        public function get backBufferLength() : Number {
            return _hlsNetStream.backBufferLength;
        };

        /** get audio tracks list**/
        public function get audioTracks() : Vector.<AudioTrack> {
            return _audioTrackController.audioTracks;
        };

        /** get alternate audio tracks list from playlist **/
        public function get altAudioTracks() : Vector.<AltAudioTrack> {
            return _levelLoader.altAudioTracks;
        };

        /** get index of the selected audio track (index in audio track lists) **/
        public function get audioTrack() : int {
            return _audioTrackController.audioTrack;
        };

        /** select an audio track, based on its index in audio track lists**/
        public function set audioTrack(val : int) : void {
            _audioTrackController.audioTrack = val;
        }

        /* set stage */
        public function set stage(stage : Stage) : void {
            _stage = stage;
        }

        /* get stage */
        public function get stage() : Stage {
            return _stage;
        }

        /* set URL stream loader */
        public function set URLstream(urlstream : Class) : void {
            _hlsURLStream = urlstream;
        }

        /* retrieve URL stream loader */
        public function get URLstream() : Class {
            return _hlsURLStream;
        }

        /* set URL stream loader */
        public function set URLloader(urlloader : Class) : void {
            _hlsURLLoader = urlloader;
        }

        /* retrieve URL stream loader */
        public function get URLloader() : Class {
            return _hlsURLLoader;
        }
    }
}

reorder code for sake of clarity

reorder code for sake of clarity


package aerys.minko.render.shader.compiler.allocation
{
	import aerys.minko.render.shader.compiler.register.Components;

	/**
	 * @private
	 * @author Romain Gilliotte
	 *
	 */
	public class ContiguousAllocation implements IAllocation
	{
		private var _subAllocations : Vector.<SimpleAllocation>;
		private var _offsets		: Vector.<uint>;

		public function get type() : uint
		{
			return _subAllocations[0].type;
		}

		public function get registerId() : uint
		{
			return _subAllocations[0].registerId;
		}

		public function get registerOffset() : uint
		{
			return offset % 4;
		}

//		public function get writeMask() : uint
//		{
//
//		}

		public function get aligned() : Boolean
		{
			return false;
		}

		public function get offset() : uint
		{
			return _subAllocations[0].offset - _offsets[0];
		}

		public function get maxSize() : uint
		{
			var numArgs : uint = _subAllocations.length;
			var maxSize	: uint = 0;

			for (var argId : uint = 0; argId < numArgs; ++argId)
			{
				var currentSize : uint = _offsets[argId] + _subAllocations[argId].maxSize;
				if (currentSize > maxSize)
					maxSize = currentSize;
			}

			return maxSize;
		}

		public function get subAllocations() : Vector.<SimpleAllocation>
		{
			return _subAllocations;
		}

		public function set offset(v : uint) : void
		{
			var numArgs : uint = _subAllocations.length;

			for (var argId : uint = 0; argId < numArgs; ++argId)
				_subAllocations[argId].offset = v + _offsets[argId];
		}

		public function ContiguousAllocation(subAllocations : Vector.<SimpleAllocation>,
											 offsets		: Vector.<uint>)
		{
			_subAllocations = subAllocations;
			_offsets		= offsets;
		}

		public function getReadSwizzle(readingOpWriteOffset	: uint,
									   readingOpComponents	: uint) : uint
		{
			var components : uint;

			components = readingOpComponents;
			components = Components.applyWriteOffset(components, readingOpWriteOffset);
			components = Components.applyReadOffset(components, registerOffset);

			if (components == Components.stringToComponent('____'))
				throw new Error();

			return Components.generateReadSwizzle(components);
		}

		public function extendLifeTime(operationId : uint) : void
		{
			for each (var sub : SimpleAllocation in _subAllocations)
				sub.extendLifeTime(operationId);
		}

		public function overlapsWith(other : IAllocation, readOnly : Boolean) : Boolean
		{
			if (other is SimpleAllocation)
			{
				return other.overlapsWith(this, readOnly);
			}
			else if (other is ContiguousAllocation)
			{
				var contiOther	: ContiguousAllocation	= ContiguousAllocation(other);

				for each (var sub1 : SimpleAllocation in _subAllocations)
					for each (var sub2 : SimpleAllocation in contiOther.subAllocations)
						if (sub1.overlapsWith(sub2, readOnly))
							return true;

				return false;
			}
			else
				throw new Error('Unknown allocation type.');
		}

		public function toString() : String
		{
			var result : String;
			result = 'Contiguous\n';
			for each (var subAlloc : SimpleAllocation in _subAllocations)
				result += "\t" + subAlloc.toString() + "\n";

			return result;
		}
	}
}

package aerys.minko.render.shader.compiler.allocation
{
	import aerys.minko.render.shader.compiler.register.Components;

	/**
	 * @private
	 * @author Romain Gilliotte
	 *
	 */
	public class ContiguousAllocation implements IAllocation
	{
		private var _subAllocations : Vector.<SimpleAllocation>;
		private var _offsets		: Vector.<uint>;

		public function get type() : uint
		{
			return _subAllocations[0].type;
		}

		public function get registerId() : uint
		{
			return _subAllocations[0].registerId;
		}

		public function get registerOffset() : uint
		{
			return offset % 4;
		}

		public function get aligned() : Boolean
		{
			return false;
		}

		public function get offset() : uint
		{
			return _subAllocations[0].offset - _offsets[0];
		}

		public function get maxSize() : uint
		{
			var numArgs : uint = _subAllocations.length;
			var maxSize	: uint = 0;

			for (var argId : uint = 0; argId < numArgs; ++argId)
			{
				var currentSize : uint = _offsets[argId] + _subAllocations[argId].maxSize;
				if (currentSize > maxSize)
					maxSize = currentSize;
			}

			return maxSize;
		}

		public function get subAllocations() : Vector.<SimpleAllocation>
		{
			return _subAllocations;
		}

		public function set offset(v : uint) : void
		{
			var numArgs : uint = _subAllocations.length;

			for (var argId : uint = 0; argId < numArgs; ++argId)
				_subAllocations[argId].offset = v + _offsets[argId];
		}

		public function ContiguousAllocation(subAllocations : Vector.<SimpleAllocation>,
											 offsets		: Vector.<uint>)
		{
			_subAllocations = subAllocations;
			_offsets		= offsets;
		}

		public function getReadSwizzle(readingOpWriteOffset	: uint,
									   readingOpComponents	: uint) : uint
		{
			var components : uint;

			components = readingOpComponents;
			components = Components.applyWriteOffset(components, readingOpWriteOffset);
			components = Components.applyReadOffset(components, registerOffset);

			if (components == Components.stringToComponent('____'))
				throw new Error();

			return Components.generateReadSwizzle(components);
		}

		public function extendLifeTime(operationId : uint) : void
		{
			for each (var sub : SimpleAllocation in _subAllocations)
				sub.extendLifeTime(operationId);
		}

		public function overlapsWith(other : IAllocation, readOnly : Boolean) : Boolean
		{
			if (other is SimpleAllocation)
			{
				return other.overlapsWith(this, readOnly);
			}
			else if (other is ContiguousAllocation)
			{
				var contiOther	: ContiguousAllocation	= ContiguousAllocation(other);

				for each (var sub1 : SimpleAllocation in _subAllocations)
					for each (var sub2 : SimpleAllocation in contiOther.subAllocations)
						if (sub1.overlapsWith(sub2, readOnly))
							return true;

				return false;
			}
			else
				throw new Error('Unknown allocation type.');
		}

		public function toString() : String
		{
			var result : String;
			result = 'Contiguous\n';
			for each (var subAlloc : SimpleAllocation in _subAllocations)
				result += "\t" + subAlloc.toString() + "\n";

			return result;
		}
	}
}

Remove dead code

Remove dead code


////////////////////////////////////////////////////////////////////////////////
//
//  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 spark.skins.ios7
{

import mx.core.DPIClassification;
import mx.core.mx_internal;

import spark.components.Button;
import spark.components.VScrollBar;
import spark.skins.mobile.supportClasses.MobileSkin;

use namespace mx_internal;

/**
 *  ActionScript-based skin for VScrollBar components in mobile applications.
 *
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
public class VScrollBarSkin extends MobileSkin
{

    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------
    /**
     *  Constructor.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     *
     */
    public function VScrollBarSkin()
    {
        super();

        minHeight = 20;
        thumbSkinClass = VScrollBarThumbSkin;
        var paddingRight:int;
        var paddingVertical:int;

        // Depending on density set our measured width
        switch (applicationDPI)
        {
			case DPIClassification.DPI_640:
			{
				minWidth = 24;
				paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_640DPI;
				paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_640DPI;
				break;
			}
			case DPIClassification.DPI_480:
			{
				minWidth = 18;
				paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_480DPI;
				paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_480DPI;
				break;
			}
            case DPIClassification.DPI_320:
            {
                minWidth = 12;
                paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_320DPI;
                paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_320DPI;
                break;
            }
			case DPIClassification.DPI_240:
			{
				minWidth = 9;
				paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_240DPI;
				paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_240DPI;
				break;
			}
			case DPIClassification.DPI_120:
			{
				minWidth = 9;
				paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_120DPI;
				paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_120DPI;
				break;
			}
            default:
            {
                // default DPI_160
                minWidth = 6;
                paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_DEFAULTDPI;
                paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_DEFAULTDPI;
                break;
            }
        }

        // The minimum height is set such that, at it's smallest size, the thumb appears
        // as high as it is wide.
        minThumbHeight = (minWidth - paddingRight) + (paddingVertical * 2);
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @copy spark.skins.spark.ApplicationSkin#hostComponent
     */
    public var hostComponent:VScrollBar;

    /**
     *  Minimum height for the thumb
     */
    protected var minThumbHeight:Number;

    /**
     *  Skin to use for the thumb Button skin part
     */
    protected var thumbSkinClass:Class;

    //--------------------------------------------------------------------------
    //
    //  Skin parts
    //
    //--------------------------------------------------------------------------
    /**
     *  VScrollbar track skin part
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var track:Button;

    /**
     *  VScrollbar thumb skin part
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var thumb:Button;

    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function createChildren():void
    {
        // Create our skin parts if necessary: track and thumb.
        if (!track)
        {
            // We don't want a visible track so we set the skin to MobileSkin
            track = new Button();
            track.setStyle("skinClass", spark.skins.mobile.supportClasses.MobileSkin);
            track.width = minWidth;
            track.height = minHeight;
            addChild(track);
        }
        if (!thumb)
        {
            thumb = new Button();
            thumb.minHeight = minThumbHeight;
            thumb.setStyle("skinClass", thumbSkinClass);
            thumb.width = minWidth;
            thumb.height = minWidth;
            addChild(thumb);
        }
    }

    /**
     *  @private
     */
    override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
    {
        super.layoutContents(unscaledWidth, unscaledHeight);

        setElementSize(track, unscaledWidth, unscaledHeight);
    }
}
}

////////////////////////////////////////////////////////////////////////////////
//
//  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 spark.skins.ios7
{

import mx.core.DPIClassification;
import mx.core.mx_internal;

import spark.components.Button;
import spark.components.VScrollBar;
import spark.skins.mobile.supportClasses.MobileSkin;

use namespace mx_internal;

/**
 *  ActionScript-based skin for VScrollBar components in mobile applications.
 *
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 2.5
 *  @productversion Flex 4.5
 */
public class VScrollBarSkin extends MobileSkin
{

    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------
    /**
     *  Constructor.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     *
     */
    public function VScrollBarSkin()
    {
        super();

        minHeight = 20;
        thumbSkinClass = VScrollBarThumbSkin;
        var paddingRight:int;
        var paddingVertical:int;

        // Depending on density set our measured width
        switch (applicationDPI)
        {
			case DPIClassification.DPI_640:
			{
				minWidth = 24;
				paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_640DPI;
				paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_640DPI;
				break;
			}
			case DPIClassification.DPI_480:
			{
				minWidth = 16;
				paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_480DPI;
				paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_480DPI;
				break;
			}
            case DPIClassification.DPI_320:
            {
                minWidth = 12;
                paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_320DPI;
                paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_320DPI;
                break;
            }
			case DPIClassification.DPI_240:
			{
				minWidth = 8;
				paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_240DPI;
				paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_240DPI;
				break;
			}
			case DPIClassification.DPI_120:
			{
				minWidth = 4;
				paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_120DPI;
				paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_120DPI;
				break;
			}
            default:
            {
                // default DPI_160
                minWidth = 6;
                paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_DEFAULTDPI;
                paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_DEFAULTDPI;
                break;
            }
        }

        // The minimum height is set such that, at it's smallest size, the thumb appears
        // as high as it is wide.
        minThumbHeight = (minWidth - paddingRight) + (paddingVertical * 2);
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @copy spark.skins.spark.ApplicationSkin#hostComponent
     */
    public var hostComponent:VScrollBar;

    /**
     *  Minimum height for the thumb
     */
    protected var minThumbHeight:Number;

    /**
     *  Skin to use for the thumb Button skin part
     */
    protected var thumbSkinClass:Class;

    //--------------------------------------------------------------------------
    //
    //  Skin parts
    //
    //--------------------------------------------------------------------------
    /**
     *  VScrollbar track skin part
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var track:Button;

    /**
     *  VScrollbar thumb skin part
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */
    public var thumb:Button;

    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------
    /**
     *  @private
     */
    override protected function createChildren():void
    {
        // Create our skin parts if necessary: track and thumb.
        if (!track)
        {
            // We don't want a visible track so we set the skin to MobileSkin
            track = new Button();
            track.setStyle("skinClass", spark.skins.mobile.supportClasses.MobileSkin);
            track.width = minWidth;
            track.height = minHeight;
            addChild(track);
        }
        if (!thumb)
        {
            thumb = new Button();
            thumb.minHeight = minThumbHeight;
            thumb.setStyle("skinClass", thumbSkinClass);
            thumb.width = minWidth;
            thumb.height = minWidth;
            addChild(thumb);
        }
    }

    /**
     *  @private
     */
    override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
    {
        super.layoutContents(unscaledWidth, unscaledHeight);

        setElementSize(track, unscaledWidth, unscaledHeight);
    }
}
}

Tweak VScrollBarkSkin to make sure it looks good in all DPIs


////////////////////////////////////////////////////////////////////////////////
//
//  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 org.apache.flex.core
{
	import org.apache.flex.events.IEventDispatcher;

    /**
     *  The IStyleableObject interface is the interface for
     *  objects that support style properties.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
	public interface IStyleableObject extends IEventDispatcher
	{
        /**
         *  Get the className(s) that will be used to
         *  choose class selectors in most CSS style
         *  implementations.  This property is called
         *  styleName in the Flex SDK.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        function get className():String;

        /**
         *  Get the object containing styles
         *  for this object.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        function get style():Object;
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//  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 org.apache.flex.core
{
	import org.apache.flex.events.IEventDispatcher;

    /**
     *  The IStyleableObject interface is the interface for
     *  objects that support style properties.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
	public interface IStyleableObject extends IEventDispatcher
	{
        /**
         *  Get the className(s) that will be used to
         *  choose class selectors in most CSS style
         *  implementations.  This property is called
         *  styleName in the Flex SDK.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        function get className():String;
        function set className(value:String):void;

        /**
         *  Get the object containing styles
         *  for this object.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        function get style():Object;
	}
}

allow writing of className via the interface


package
{
	/**
	 * This file has been automatically created using
	 * #!/usr/bin/ruby script/generate suite
	 * If you modify it and run this script, your
	 * modifications will be lost!
	 */

	import as3spec.*;
	import com.gigya.WildfireTest;
	import ras3r.controls.TextTest;
	import ras3r.reaction_view.helpers.ImageHelperTest;
	import ras3r.reaction_view.helpers.TextFieldHelperTest;

	public class AllTests extends Suite
	{
		public function AllTests ()
		{
			add(com.gigya.WildfireTest);
			add(ras3r.controls.TextTest);
			add(ras3r.reaction_view.helpers.ImageHelperTest);
			add(ras3r.reaction_view.helpers.TextFieldHelperTest);
		}
	}
}

package
{
	/**
	 * This file has been automatically created using
	 * #!/usr/bin/ruby script/generate suite
	 * If you modify it and run this script, your
	 * modifications will be lost!
	 */

	import as3spec.*;
	import com.gigya.WildfireTest;
	import ras3r.HashTest;
	import ras3r.reaction_view.helpers.BoxHelperTest;
	import ras3r.reaction_view.helpers.ComboBoxHelperTest;
	import ras3r.reaction_view.helpers.ImageHelperTest;
	import ras3r.reaction_view.helpers.TextFieldHelperTest;
	import ras3r.reaction_view.helpers.TextInputHelperTest;
	import ras3r.ReactionControllerTest;
	import ras3r.ReactionViewTest;
	import ras3r.reactive_resource.ResponseTest;

	public class AllTests extends Suite
	{
		public function AllTests ()
		{
			add(com.gigya.WildfireTest);
			add(ras3r.HashTest);
			add(ras3r.reaction_view.helpers.BoxHelperTest);
			add(ras3r.reaction_view.helpers.ComboBoxHelperTest);
			add(ras3r.reaction_view.helpers.ImageHelperTest);
			add(ras3r.reaction_view.helpers.TextFieldHelperTest);
			add(ras3r.reaction_view.helpers.TextInputHelperTest);
			add(ras3r.ReactionControllerTest);
			add(ras3r.ReactionViewTest);
			add(ras3r.reactive_resource.ResponseTest);
		}
	}
}

reset test suite

reset test suite


package org.denivip.osmf.utils
{
	import org.osmf.utils.URL;

	public class Utils
	{
		public static function createFullUrl(rootUrl:String, url:String):String{

			if(url.search(/(ftp|file|https?):\/\/\/?/) == 0)
				return url;

			// other manipulations :)
			if(url.charAt(0) == '/'){
				return URL.getRootUrl(rootUrl) + url;
			}

			if(rootUrl.lastIndexOf('/') != rootUrl.length)
				rootUrl += '/';

			return rootUrl + url;
		}
	}
}

package org.denivip.osmf.utils
{
	import org.osmf.utils.URL;

	public class Utils
	{
		public static function createFullUrl(rootUrl:String, url:String):String {
			if(url.search(/(ftp|file|https?):\/\/\/?/) == 0)
				return url;

			// other manipulations :)
			if(url.charAt(0) == '/'){
				return URL.getRootUrl(rootUrl) + url;
			}

			if(rootUrl.lastIndexOf('/') != rootUrl.length - 1)
				rootUrl += '/';

			return rootUrl + url;
		}
	}
}

Fix issue where check for final slash was comparing zero-based index with length


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

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

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

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

		private var _file:File;
		private var _process:NativeProcess;
		private var _tm:int;
		private var _init:Boolean = false;
		private var _error:Boolean = false;
		private var _crashHandlerArgs:Array = null;

		public var isReady:Boolean = false;

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

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

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

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

			_process.start(startupInfo);
		}

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

			try {
				startProcess();
			} catch(e:Error) {
				return false;
			}

			// try to start the process a second time, but this time ignoring any
			// potential errors since we will definitely get one about the process
			// already running. this seems to give the runtime enough time to check
			// for any stderr output of the initial call to startProcess(), so that we
			// now can check if it actually started: in case it couldn't one of the
			// libraries it depends on, it prints something like "error while loading
			// shared libraries" to stderr, which we're trying to detect here.
			// process.running is unreliable, in that it's always set to true,
			// even if the process didn't start at all
			try {
				startProcess();
			} catch(e:Error) {
				// no-op
			}
			if(!_process.running) return false;
			if(_process.standardError.bytesAvailable > 0) return false;

			// initialization seems to be successful
			_init = true;

			// UseCrashHandler has to be called before Steam_Init
			// but we still have to make sure the process is actually running
			// so FRESteamWorks#useCrashHandler just sets _crashHandlerArgs
			// and the actual call is handled here
			if(_crashHandlerArgs) {
				if(!callWrapper(AIRSteam_UseCrashHandler, _crashHandlerArgs))
					return false;
			}

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

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

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

				_process.exit();
			}
		}

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

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

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

			return !_error;
		}

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

			return output.bytesAvailable;
		}

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

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

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

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

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

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

		private function readStringResponse():String {
			if(!_process.running) return "";

			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var data:String = stdout.readUTFBytes(avail)
			var newline:uint = data.indexOf("\n");
			var buf:String = data.substring(newline);
			var length:uint = parseInt(data.substring(0, newline), 10);
			trace("Waiting for " + length + " bytes");

			while(buf.length < length) {
				avail = waitForData(stdout);
				buf += stdout.readUTFBytes(avail);
			}

			return buf;
		}

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

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

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

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

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

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

		public function useCrashHandler(appID:uint, version:String, date:String, time:String):Boolean {
			// only allow calls before SteamAPI_Init was called
			if(_init) return false;
			_crashHandlerArgs = [appID, version, date, time];
			return true;
		}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

			return success;
		}

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

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

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

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

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

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

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

		private var _file:File;
		private var _process:NativeProcess;
		private var _tm:int;
		private var _init:Boolean = false;
		private var _error:Boolean = false;
		private var _crashHandlerArgs:Array = null;

		public var isReady:Boolean = false;

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

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

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

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

			_process.start(startupInfo);
		}

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

			try {
				startProcess();
			} catch(e:Error) {
				return false;
			}

			// try to start the process a second time, but this time ignoring any
			// potential errors since we will definitely get one about the process
			// already running. this seems to give the runtime enough time to check
			// for any stderr output of the initial call to startProcess(), so that we
			// now can check if it actually started: in case it couldn't one of the
			// libraries it depends on, it prints something like "error while loading
			// shared libraries" to stderr, which we're trying to detect here.
			// process.running is unreliable, in that it's always set to true,
			// even if the process didn't start at all
			try {
				startProcess();
			} catch(e:Error) {
				// no-op
			}
			if(!_process.running) return false;
			if(_process.standardError.bytesAvailable > 0) return false;

			// initialization seems to be successful
			_init = true;

			// UseCrashHandler has to be called before Steam_Init
			// but we still have to make sure the process is actually running
			// so FRESteamWorks#useCrashHandler just sets _crashHandlerArgs
			// and the actual call is handled here
			if(_crashHandlerArgs) {
				if(!callWrapper(AIRSteam_UseCrashHandler, _crashHandlerArgs))
					return false;
			}

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

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

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

				_process.exit();
			}
		}

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

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

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

			return !_error;
		}

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

			return output.bytesAvailable;
		}

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

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

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

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

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

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

		private function readStringResponse():String {
			if(!_process.running) return "";

			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var data:String = stdout.readUTFBytes(avail)
			var newline:uint = data.indexOf("\n");
			var buf:String = data.substring(newline);
			var length:uint = parseInt(data.substring(0, newline), 10);

			while(buf.length < length) {
				avail = waitForData(stdout);
				buf += stdout.readUTFBytes(avail);
			}

			return buf;
		}

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

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

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

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

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

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

		public function useCrashHandler(appID:uint, version:String, date:String, time:String):Boolean {
			// only allow calls before SteamAPI_Init was called
			if(_init) return false;
			_crashHandlerArgs = [appID, version, date, time];
			return true;
		}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

			return success;
		}

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

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

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

Remove debug trace

[swc] Remove debug trace