package {

import com.marstonstudio.crossusermedia.encoder.Encoder;

import flash.display.DisplayObjectContainer;

import flash.events.Event;
import flash.utils.ByteArray;

import mx.core.ByteArrayAsset;
import mx.core.UIComponent;

import org.flexunit.asserts.assertNotNull;

import org.flexunit.asserts.assertTrue;
import org.flexunit.async.Async;
import org.fluint.uiImpersonation.UIImpersonator;

public class TestApp {

        public function TestApp() {}

        [Embed(source="../resources/audio.pcm",mimeType="application/octet-stream")]
        public var AudioPcm:Class;

        public var container:DisplayObjectContainer;

        [Before(async,ui)]
        public function initialize():void {
            trace("+++++++++++++++++++++++++++++++++++++++++++++++++++++++");
            trace("test::start " + new Date().toLocaleString());
            trace("");
            container = new UIComponent();
            Async.proceedOnEvent(this, container, Event.ADDED_TO_STAGE, 100);
            UIImpersonator.addChild(container);
        }

        [Test(description="Load audio asset")]
        public function testAudioLoad():void {

            var audioPcmAsset:ByteArrayAsset = new AudioPcm();
            assertTrue("embedded bytesAvailable", audioPcmAsset.bytesAvailable > 0);

            assertNotNull(container.stage);

            const sampleRate:int = 16000;
            const format:String = 'f32be';
            const bitRate:int = 32000;

            var encoder:Encoder = new Encoder(container);
            encoder.init(format, sampleRate, format, sampleRate, bitRate);
            encoder.load(audioPcmAsset);
            var output:ByteArray = encoder.flush();

            assertTrue("outputSampleRate set to " + sampleRate, encoder.getOutputSampleRate() == sampleRate);
            assertTrue("outputFormat set to " + format, encoder.getOutputFormat() == format);
            assertTrue("outputLength = audioPcmAsset.length = " + audioPcmAsset.length, encoder.getOutputLength() == audioPcmAsset.length);
            assertTrue("output.length = audioPcmAsset.length = " + audioPcmAsset.length, output.length == audioPcmAsset.length);

            encoder.dispose(0);
        }

        [After]
        public function finalize():void {
            UIImpersonator.removeAllChildren();
            container = null;

            trace("");
            trace("test::complete " + new Date().toLocaleString());
            trace("=======================================================");
        }

    }
}

package {

import com.marstonstudio.crossusermedia.encoder.Encoder;

import flash.display.DisplayObjectContainer;

import flash.events.Event;
import flash.utils.ByteArray;
import flash.utils.getTimer;

import mx.core.ByteArrayAsset;
import mx.core.UIComponent;

import org.flexunit.asserts.assertNotNull;

import org.flexunit.asserts.assertTrue;
import org.flexunit.async.Async;
import org.fluint.uiImpersonation.UIImpersonator;

public class TestApp {

        public function TestApp() {}

        [Embed(source="../resources/audio.pcm",mimeType="application/octet-stream")]
        public var AudioPcm:Class;

        public var container:DisplayObjectContainer;

        [Before(async,ui)]
        public function initialize():void {
            trace("+++++++++++++++++++++++++++++++++++++++++++++++++++++++");
            trace("test::start " + new Date().toLocaleString());
            trace("");
            container = new UIComponent();
            Async.proceedOnEvent(this, container, Event.ADDED_TO_STAGE, 100);
            UIImpersonator.addChild(container);
        }

        [Test(description="Load audio asset")]
        public function testAudioLoad():void {

            var audioPcmAsset:ByteArrayAsset = new AudioPcm();
            assertTrue("embedded bytesAvailable", audioPcmAsset.bytesAvailable > 0);

            assertNotNull(container.stage);

            const sampleRate:int = 16000;
            const format:String = 'f32be';
            const bitRate:int = 32000;

            var encoder:Encoder = new Encoder(container);
            encoder.init(format, sampleRate, format, sampleRate, bitRate);
            encoder.load(audioPcmAsset);
            var output:ByteArray = encoder.flush();

            assertTrue("outputSampleRate set to " + sampleRate, encoder.getOutputSampleRate() == sampleRate);
            assertTrue("outputFormat set to " + format, encoder.getOutputFormat() == format);
            assertTrue("outputLength = audioPcmAsset.length = " + audioPcmAsset.length, encoder.getOutputLength() == audioPcmAsset.length);
            assertTrue("output.length = audioPcmAsset.length = " + audioPcmAsset.length, output.length == audioPcmAsset.length);

            //give stdout buffer a chance to catch up before terminating
            sleep(1000);

            encoder.dispose(0);
        }

        [After]
        public function finalize():void {
            UIImpersonator.removeAllChildren();
            container = null;

            trace("");
            trace("test::complete " + new Date().toLocaleString());
            trace("=======================================================");
        }

        private function sleep(ms:int):void {
            var init:int = getTimer();
            while(true) {
                if(getTimer() - init >= ms) {
                    break;
                }
            }
        }

    }
}

add sleep to test for console output

add sleep to test for console output


////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2008-2013 Esri. All Rights Reserved.
//
// 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 com.esri.builder.controllers
{

import com.esri.ags.components.IdentityManager;
import com.esri.ags.components.supportClasses.Credential;
import com.esri.ags.events.IdentityManagerEvent;
import com.esri.ags.events.PortalEvent;
import com.esri.ags.portal.Portal;
import com.esri.builder.eventbus.AppEvent;
import com.esri.builder.model.Model;
import com.esri.builder.model.PortalModel;
import com.esri.builder.supportClasses.LogUtil;
import com.esri.builder.supportClasses.URLUtil;

import mx.logging.ILogger;
import mx.logging.Log;
import mx.resources.ResourceManager;
import mx.rpc.Fault;
import mx.rpc.events.FaultEvent;

public class PortalController
{
    private static const LOG:ILogger = LogUtil.createLogger(PortalController);

    private var lastUsedCultureCode:String;

    private var portal:Portal = PortalModel.getInstance().portal;

    public function PortalController()
    {
        AppEvent.addListener(AppEvent.SETTINGS_SAVED, settingsChangeHandler);
    }

    private function settingsChangeHandler(event:AppEvent):void
    {
        //optimization: AGO uses OAuth, so we register the OAuth info upfront
        var portalModel:PortalModel = PortalModel.getInstance();
        var portalURL:String = portalModel.portalURL;
        if (portalModel.isAGO(portalURL))
        {
            portalModel.registerOAuthPortal(portalURL, Model.instance.cultureCode);
        }

        loadPortal(portalURL, Model.instance.cultureCode);
    }

    private function loadPortal(url:String, cultureCode:String):void
    {
        if (Log.isInfo())
        {
            LOG.info("Loading Portal");
        }

        if (url)
        {
            var hasPortalURLChanged:Boolean = (portal.url != url);
            var hasCultureCodeChanged:Boolean = (lastUsedCultureCode != cultureCode);
            if (hasPortalURLChanged || hasCultureCodeChanged)
            {
                if (Log.isDebug())
                {
                    LOG.debug("Reloading Portal - URL: {0}, culture code: {1}", url, cultureCode);
                }

                if (hasPortalURLChanged)
                {
                    portal.unload();
                }

                lastUsedCultureCode = cultureCode;
                portal.culture = cultureCode;
                portal.url = URLUtil.removeToken(url);

                IdentityManager.instance.removeEventListener(IdentityManagerEvent.SIGN_IN, identityManager_signInHandler);
                portal.addEventListener(PortalEvent.LOAD, portal_loadHandler);
                portal.addEventListener(FaultEvent.FAULT, portal_faultHandler);
                portal.load();
            }
        }
        else
        {
            unloadPortal();
            dispatchPortalStatusUpdate();
        }
    }

    private function identityManager_signInHandler(event:IdentityManagerEvent):void
    {
        if (PortalModel.getInstance().hasSameOrigin(event.credential.server)
            && !PortalModel.getInstance().portal.signedIn)
        {
            signIntoPortalInternally();
        }
    }

    private function signIntoPortalInternally():void
    {
        AppEvent.removeListener(AppEvent.PORTAL_SIGN_IN, portalSignInHandler);
        IdentityManager.instance.removeEventListener(IdentityManagerEvent.SIGN_IN, identityManager_signInHandler);
        portal.addEventListener(PortalEvent.LOAD, portal_loadHandler);
        portal.addEventListener(FaultEvent.FAULT, portal_faultHandler);
        portal.signIn();
    }

    private function portal_loadHandler(event:PortalEvent):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Portal load success");
        }

        //do nothing, load successful
        portal.removeEventListener(PortalEvent.LOAD, portal_loadHandler);
        portal.removeEventListener(FaultEvent.FAULT, portal_faultHandler);

        dispatchPortalStatusUpdate();
    }

    private function portal_faultHandler(event:FaultEvent):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Portal load fault");
        }

        portal.removeEventListener(PortalEvent.LOAD, portal_loadHandler);
        portal.removeEventListener(FaultEvent.FAULT, portal_faultHandler);

        var fault:Fault = event.fault;
        if (fault.faultCode == "403" && fault.faultString == "User not part of this account")
        {
            var credential:Credential = IdentityManager.instance.findCredential(portal.url);
            if (credential)
            {
                credential.destroy();
            }

            AppEvent.dispatch(
                AppEvent.SHOW_ERROR,
                ResourceManager.getInstance().getString("BuilderStrings", "notOrgMember"));
        }
        else
        {
            dispatchPortalStatusUpdate();
        }
    }

    private function unloadPortal():void
    {
        if (Log.isDebug())
        {
            LOG.debug("Unloading Portal");
        }

        portal.url = null;
        portal.unload();
    }

    private function dispatchPortalStatusUpdate():void
    {
        updatePortalHandlersBasedOnStatus();
        AppEvent.dispatch(AppEvent.PORTAL_STATUS_UPDATED);
    }

    private function updatePortalHandlersBasedOnStatus():void
    {
        if (portal.signedIn)
        {
            AppEvent.addListener(AppEvent.PORTAL_SIGN_OUT, portalSignOutHandler);
            AppEvent.removeListener(AppEvent.PORTAL_SIGN_IN, portalSignInHandler);
            IdentityManager.instance.removeEventListener(IdentityManagerEvent.SIGN_IN, identityManager_signInHandler);
        }
        else
        {
            AppEvent.addListener(AppEvent.PORTAL_SIGN_IN, portalSignInHandler);
            IdentityManager.instance.addEventListener(IdentityManagerEvent.SIGN_IN, identityManager_signInHandler);
            AppEvent.removeListener(AppEvent.PORTAL_SIGN_OUT, portalSignOutHandler);
        }
    }

    private function portalSignOutHandler(event:AppEvent):void
    {
        if (Log.isInfo())
        {
            LOG.info("Portal sign out requested");
        }

        AppEvent.removeListener(AppEvent.PORTAL_SIGN_OUT, portalSignOutHandler);
        IdentityManager.instance.removeEventListener(IdentityManagerEvent.SIGN_IN, identityManager_signInHandler);
        portal.addEventListener(PortalEvent.LOAD, portal_loadHandler);
        portal.addEventListener(FaultEvent.FAULT, portal_faultHandler);
        portal.signOut();
    }

    private function portalSignInHandler(event:AppEvent):void
    {
        if (Log.isInfo())
        {
            LOG.info("Portal sign in requested");
        }

        signIntoPortalInternally();
    }
}
}

////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2008-2013 Esri. All Rights Reserved.
//
// 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 com.esri.builder.controllers
{

import com.esri.ags.components.IdentityManager;
import com.esri.ags.components.supportClasses.Credential;
import com.esri.ags.events.IdentityManagerEvent;
import com.esri.ags.events.PortalEvent;
import com.esri.ags.portal.Portal;
import com.esri.builder.eventbus.AppEvent;
import com.esri.builder.model.Model;
import com.esri.builder.model.PortalModel;
import com.esri.builder.supportClasses.LogUtil;
import com.esri.builder.supportClasses.URLUtil;

import mx.logging.ILogger;
import mx.logging.Log;
import mx.resources.ResourceManager;
import mx.rpc.Fault;
import mx.rpc.events.FaultEvent;

public class PortalController
{
    private static const LOG:ILogger = LogUtil.createLogger(PortalController);

    private var lastUsedCultureCode:String;

    private var portal:Portal = PortalModel.getInstance().portal;

    public function PortalController()
    {
        AppEvent.addListener(AppEvent.SETTINGS_SAVED, settingsChangeHandler);
    }

    private function settingsChangeHandler(event:AppEvent):void
    {
        //optimization: AGO uses OAuth, so we register the OAuth info upfront
        var portalModel:PortalModel = PortalModel.getInstance();
        var portalURL:String = portalModel.portalURL;
        var cultureCode:String = Model.instance.cultureCode;
        if (portalModel.isAGO(portalURL))
        {
            portalModel.registerOAuthPortal(portalURL, cultureCode);
        }

        loadPortal(portalURL, cultureCode);
    }

    private function loadPortal(url:String, cultureCode:String):void
    {
        if (Log.isInfo())
        {
            LOG.info("Loading Portal");
        }

        if (url)
        {
            var hasPortalURLChanged:Boolean = (portal.url != url);
            var hasCultureCodeChanged:Boolean = (lastUsedCultureCode != cultureCode);
            if (hasPortalURLChanged || hasCultureCodeChanged)
            {
                if (Log.isDebug())
                {
                    LOG.debug("Reloading Portal - URL: {0}, culture code: {1}", url, cultureCode);
                }

                if (hasPortalURLChanged)
                {
                    portal.unload();
                }

                lastUsedCultureCode = cultureCode;
                portal.culture = cultureCode;
                portal.url = URLUtil.removeToken(url);

                IdentityManager.instance.removeEventListener(IdentityManagerEvent.SIGN_IN, identityManager_signInHandler);
                portal.addEventListener(PortalEvent.LOAD, portal_loadHandler);
                portal.addEventListener(FaultEvent.FAULT, portal_faultHandler);
                portal.load();
            }
        }
        else
        {
            unloadPortal();
            dispatchPortalStatusUpdate();
        }
    }

    private function identityManager_signInHandler(event:IdentityManagerEvent):void
    {
        if (PortalModel.getInstance().hasSameOrigin(event.credential.server)
            && !PortalModel.getInstance().portal.signedIn)
        {
            signIntoPortalInternally();
        }
    }

    private function signIntoPortalInternally():void
    {
        AppEvent.removeListener(AppEvent.PORTAL_SIGN_IN, portalSignInHandler);
        IdentityManager.instance.removeEventListener(IdentityManagerEvent.SIGN_IN, identityManager_signInHandler);
        portal.addEventListener(PortalEvent.LOAD, portal_loadHandler);
        portal.addEventListener(FaultEvent.FAULT, portal_faultHandler);
        portal.signIn();
    }

    private function portal_loadHandler(event:PortalEvent):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Portal load success");
        }

        //do nothing, load successful
        portal.removeEventListener(PortalEvent.LOAD, portal_loadHandler);
        portal.removeEventListener(FaultEvent.FAULT, portal_faultHandler);

        dispatchPortalStatusUpdate();
    }

    private function portal_faultHandler(event:FaultEvent):void
    {
        if (Log.isDebug())
        {
            LOG.debug("Portal load fault");
        }

        portal.removeEventListener(PortalEvent.LOAD, portal_loadHandler);
        portal.removeEventListener(FaultEvent.FAULT, portal_faultHandler);

        var fault:Fault = event.fault;
        if (fault.faultCode == "403" && fault.faultString == "User not part of this account")
        {
            var credential:Credential = IdentityManager.instance.findCredential(portal.url);
            if (credential)
            {
                credential.destroy();
            }

            AppEvent.dispatch(
                AppEvent.SHOW_ERROR,
                ResourceManager.getInstance().getString("BuilderStrings", "notOrgMember"));
        }
        else
        {
            dispatchPortalStatusUpdate();
        }
    }

    private function unloadPortal():void
    {
        if (Log.isDebug())
        {
            LOG.debug("Unloading Portal");
        }

        portal.url = null;
        portal.unload();
    }

    private function dispatchPortalStatusUpdate():void
    {
        updatePortalHandlersBasedOnStatus();
        AppEvent.dispatch(AppEvent.PORTAL_STATUS_UPDATED);
    }

    private function updatePortalHandlersBasedOnStatus():void
    {
        if (portal.signedIn)
        {
            AppEvent.addListener(AppEvent.PORTAL_SIGN_OUT, portalSignOutHandler);
            AppEvent.removeListener(AppEvent.PORTAL_SIGN_IN, portalSignInHandler);
            IdentityManager.instance.removeEventListener(IdentityManagerEvent.SIGN_IN, identityManager_signInHandler);
        }
        else
        {
            AppEvent.addListener(AppEvent.PORTAL_SIGN_IN, portalSignInHandler);
            IdentityManager.instance.addEventListener(IdentityManagerEvent.SIGN_IN, identityManager_signInHandler);
            AppEvent.removeListener(AppEvent.PORTAL_SIGN_OUT, portalSignOutHandler);
        }
    }

    private function portalSignOutHandler(event:AppEvent):void
    {
        if (Log.isInfo())
        {
            LOG.info("Portal sign out requested");
        }

        AppEvent.removeListener(AppEvent.PORTAL_SIGN_OUT, portalSignOutHandler);
        IdentityManager.instance.removeEventListener(IdentityManagerEvent.SIGN_IN, identityManager_signInHandler);
        portal.addEventListener(PortalEvent.LOAD, portal_loadHandler);
        portal.addEventListener(FaultEvent.FAULT, portal_faultHandler);
        portal.signOut();
    }

    private function portalSignInHandler(event:AppEvent):void
    {
        if (Log.isInfo())
        {
            LOG.info("Portal sign in requested");
        }

        signIntoPortalInternally();
    }
}
}

Clean up.

Clean up.


package org.mangui.hls
{
    import flash.external.ExternalInterface;
    import org.hola.ZExternalInterface;
    import org.hola.JSAPI;
    import org.hola.HSettings;
    import org.mangui.hls.event.HLSEvent;
    import org.mangui.hls.constant.HLSPlayStates;
    import org.mangui.hls.model.Level;
    import org.mangui.hls.model.Fragment;
    import flash.utils.setTimeout;
    import flash.net.NetStreamAppendBytesAction;

    public class HLSJS
    {
        private static var _inited: Boolean = false;
        private static var _duration: Number;
        private static var _bandwidth: Number = -1;
        private static var _url: String;
        private static var _currentFrag: String;
        private static var _state: String;
        private static var _hls: HLS;
        private static var _silence: Boolean = false;

        public static function init():void{
            if (_inited || !ZExternalInterface.avail())
                return;
            _inited = true;
            JSAPI.init();
            ExternalInterface.addCallback("hola_version", hola_version);
            ExternalInterface.addCallback("hola_hls_version", hola_version);
            ExternalInterface.addCallback("hola_hls_get_video_url",
                hola_hls_get_video_url);
            ExternalInterface.addCallback("hola_hls_get_position",
                hola_hls_get_position);
            ExternalInterface.addCallback("hola_hls_get_duration",
                hola_hls_get_duration);
            ExternalInterface.addCallback("hola_hls_get_buffer_sec",
                hola_hls_get_buffer_sec);
            ExternalInterface.addCallback("hola_hls_get_state",
                hola_hls_get_state);
            ExternalInterface.addCallback("hola_hls_get_current_fragment",
                hola_hls_get_current_fragment);
            ExternalInterface.addCallback("hola_hls_get_levels",
                hola_hls_get_levels);
            ExternalInterface.addCallback("hola_hls_get_levels_async",
                hola_hls_get_levels_async);
            ExternalInterface.addCallback("hola_hls_get_segment_info",
                hola_hls_get_segment_info);
            ExternalInterface.addCallback("hola_hls_get_level",
                hola_hls_get_level);
            ExternalInterface.addCallback("hola_hls_get_bitrate",
                hola_hls_get_bitrate);
            ExternalInterface.addCallback("hola_hls_get_decoded_frames",
                hola_hls_get_decoded_frames);
            ExternalInterface.addCallback("hola_setBandwidth",
                hola_setBandwidth);
            ExternalInterface.addCallback("hola_hls_setBandwidth",
                hola_setBandwidth);
            ExternalInterface.addCallback("hola_hls_get_type",
                hola_hls_get_type);
            ExternalInterface.addCallback("hola_hls_load_fragment", hola_hls_load_fragment);
            ExternalInterface.addCallback("hola_hls_abort_fragment", hola_hls_abort_fragment);
            ExternalInterface.addCallback("hola_hls_load_level", hola_hls_load_level);
            ExternalInterface.addCallback('hola_hls_flush_stream', hola_hls_flush_stream);
        }

        public static function HLSnew(hls:HLS):void{
            _hls = hls;
            _state = HLSPlayStates.IDLE;
            // track duration events
            hls.addEventListener(HLSEvent.PLAYLIST_DURATION_UPDATED,
                on_playlist_duration_updated);
            // track playlist-url/state
            hls.addEventListener(HLSEvent.PLAYBACK_STATE, on_playback_state);
            hls.addEventListener(HLSEvent.SEEK_STATE, on_seek_state);
            hls.addEventListener(HLSEvent.MANIFEST_LOADED, on_manifest_loaded);
            hls.addEventListener(HLSEvent.MANIFEST_LOADING, on_manifest_loading);
            hls.addEventListener(HLSEvent.FRAGMENT_LOADING, on_fragment_loading);
            // notify js events
            hls.addEventListener(HLSEvent.MANIFEST_LOADING, on_event);
            hls.addEventListener(HLSEvent.MANIFEST_PARSED, on_event);
            hls.addEventListener(HLSEvent.MANIFEST_LOADED, on_event);
            hls.addEventListener(HLSEvent.LEVEL_LOADING, on_event);
            hls.addEventListener(HLSEvent.LEVEL_LOADING_ABORTED, on_event);
            hls.addEventListener(HLSEvent.LEVEL_LOADED, on_level_loaded);
            hls.addEventListener(HLSEvent.LEVEL_SWITCH, on_event);
            hls.addEventListener(HLSEvent.LEVEL_ENDLIST, on_event);
            hls.addEventListener(HLSEvent.FRAGMENT_LOADING, on_event);
            hls.addEventListener(HLSEvent.FRAGMENT_LOADED, on_event);
            hls.addEventListener(HLSEvent.FRAGMENT_LOAD_EMERGENCY_ABORTED,
                on_event);
            hls.addEventListener(HLSEvent.FRAGMENT_PLAYING, on_event);
            hls.addEventListener(HLSEvent.FRAGMENT_SKIPPED, on_event);
            hls.addEventListener(HLSEvent.AUDIO_TRACKS_LIST_CHANGE, on_event);
            hls.addEventListener(HLSEvent.AUDIO_TRACK_SWITCH, on_event);
            hls.addEventListener(HLSEvent.AUDIO_LEVEL_LOADING, on_event);
            hls.addEventListener(HLSEvent.AUDIO_LEVEL_LOADED, on_event);
            hls.addEventListener(HLSEvent.TAGS_LOADED, on_event);
            hls.addEventListener(HLSEvent.LAST_VOD_FRAGMENT_LOADED, on_event);
            hls.addEventListener(HLSEvent.WARNING, on_event);
            hls.addEventListener(HLSEvent.ERROR, on_event);
            hls.addEventListener(HLSEvent.MEDIA_TIME, on_event);
            hls.addEventListener(HLSEvent.PLAYBACK_STATE, on_event);
            hls.addEventListener(HLSEvent.STREAM_TYPE_DID_CHANGE, on_event);
            hls.addEventListener(HLSEvent.PLAYBACK_COMPLETE, on_event);
            hls.addEventListener(HLSEvent.PLAYLIST_DURATION_UPDATED,
                on_event);
            hls.addEventListener(HLSEvent.ID3_UPDATED, on_event);
            hls.addEventListener(HLSEvent.FPS_DROP, on_event);
            hls.addEventListener(HLSEvent.FPS_DROP_LEVEL_CAPPING, on_event);
            hls.addEventListener(HLSEvent.FPS_DROP_SMOOTH_LEVEL_SWITCH,
                on_event);
            hls.addEventListener(HLSEvent.LIVE_LOADING_STALLED, on_event);
            JSAPI.postMessage('flashls.hlsNew');
        }

        public static function HLSdispose(hls:HLS):void{
            JSAPI.postMessage('flashls.hlsDispose');
            _duration = 0;
            _bandwidth = -1;
            _url = null;
            _state = HLSPlayStates.IDLE;
            _hls = null;
        }

        public static function get bandwidth():Number{
            return HSettings.gets('mode')=='adaptive' ? _bandwidth : -1;
        }

        private static function on_manifest_loaded(e:HLSEvent):void{
            _duration = e.levels[_hls.startLevel].duration;
        }

        private static function on_playlist_duration_updated(e:HLSEvent):void{
            _duration = e.duration;
        }

        private static function on_fragment_loading(e: HLSEvent): void
        {
            _currentFrag = e.url;
        }

        private static function on_manifest_loading(e:HLSEvent):void{
            _url = e.url;
            _state = "LOADING";
            on_event(new HLSEvent(HLSEvent.PLAYBACK_STATE, _state));
        }

        private static function on_playback_state(e:HLSEvent):void{
            _state = e.state;
        }

        private static function on_level_loaded(e: HLSEvent): void
        {
            JSAPI.postMessage('flashls.'+e.type, {level: level_to_object(_hls.levels[e.loadMetrics.level])});
        }

        private static function on_seek_state(e: HLSEvent): void
        {
            JSAPI.postMessage('flashls.'+e.type, {state: e.state, seek_pos: _hls.position, buffer: _hls.stream.bufferLength});
        }

        private static function on_event(e: HLSEvent): void
        {
            if (_silence)
                return;
            JSAPI.postMessage('flashls.'+e.type, {url: e.url, level: e.level,
                duration: e.duration, levels: e.levels, error: e.error,
                loadMetrics: e.loadMetrics, playMetrics: e.playMetrics,
                mediatime: e.mediatime, state: e.state,
                audioTrack: e.audioTrack, streamType: e.streamType});
        }

        private static function hola_version(): Object
        {
            return {
                flashls_version: '0.4.4.20',
                patch_version: '2.0.14'
            };
        }

        private static function hola_hls_get_video_url(): String
        {
            return _url;
        }

        private static function hola_hls_get_position(): Number
        {
            return _hls.position;
        }

        private static function hola_hls_get_duration(): Number
        {
            return _duration;
        }

        private static function hola_hls_get_decoded_frames(): Number
        {
            return _hls.stream.decodedFrames;
        }

        private static function hola_hls_get_buffer_sec(): Number
        {
            return _hls.stream.bufferLength;
        }

        private static function hola_hls_get_state(): String
        {
            return _state;
        }

        private static function hola_hls_get_type(): String
        {
            return _hls.type;
        }

        private static function hola_hls_load_fragment(level: Number, frag: Number, url: String): Object
        {
            if (HSettings.gets('mode')!='hola_adaptive')
                return 0;
            return _hls.loadFragment(level, frag, url);
        }

        private static function hola_hls_flush_stream(): void
        {
            if (_hls.stream.decodedFrames === 0)
                return;
            _silence = true;
            _hls.stream.close();
            _hls.stream.play();
            _hls.stream.pause();
            _silence = false;
        }

        private static function hola_hls_abort_fragment(ldr_id: String): void
        {
            if (HSettings.gets('mode')!='hola_adaptive')
                return;
            _hls.abortFragment(ldr_id);
        }

        private static function hola_hls_load_level(level: Number): void
        {
            if (HSettings.gets('mode')!='hola_adaptive')
                return;
            if (!_hls.isStartLevelSet())
                _hls.startLevel = level;
            _hls.dispatchEvent(new HLSEvent(HLSEvent.LEVEL_SWITCH, level));
        }

        private static function level_to_object(l: Level): Object
        {
            var fragments: Array = [];
            for (var i: int = 0; i<l.fragments.length; i++)
            {
                var fragment: Fragment = l.fragments[i];
                fragments.push({url: fragment.url,
                    duration: fragment.duration, seqnum: fragment.seqnum});
            }
            return {url: l.url, bitrate: l.bitrate, fragments: fragments,
                index: l.index, width: l.width, height: l.height, audio: l.audio};
        }

        private static function hola_hls_get_levels(): Object
        {
            var levels: Vector.<Object> = new Vector.<Object>(_hls.levels.length);
            for (var i: int = 0; i<_hls.levels.length; i++)
            {
                var l: Level = _hls.levels[i];
                // no fragments returned, use get_segment_info for fragm.info
                levels[i] = Object({url: l.url, bitrate: l.bitrate,
                    index: l.index, fragments: []});
            }
            return levels;
        }

        private static function hola_hls_get_current_fragment(): String
        {
            return _currentFrag;
        }

        private static function hola_hls_get_levels_async(): void
        {
            setTimeout(function(): void
            {
                var levels: Array = [];
                for (var i: int = 0; i<_hls.levels.length; i++)
                    levels.push(level_to_object(_hls.levels[i]));
                JSAPI.postMessage('flashls.hlsAsyncMessage', {type: 'get_levels', msg: levels});
            }, 0);
        }

        private static function hola_hls_get_segment_info(url: String): Object
        {
            for (var i: int = 0; i<_hls.levels.length; i++)
            {
                var l: Level = _hls.levels[i];
                for (var j:int = 0; j<l.fragments.length; j++)
                {
                    if (url==l.fragments[j].url)
                    {
                        return Object({fragment: l.fragments[j],
                            level: Object({url: l.url, bitrate: l.bitrate,
                            index: l.index})});
                    }
                }
            }
            return undefined;
        }

        private static function hola_hls_get_bitrate(): Number
        {
            return _hls.loadLevel<_hls.levels.length ? _hls.levels[_hls.loadLevel].bitrate : 0;
        }

        private static function hola_hls_get_level(): String
        {
            return _hls.loadLevel<_hls.levels.length ? _hls.levels[_hls.loadLevel].url : undefined;
        }

        private static function hola_setBandwidth(bandwidth: Number): void
        {
            _bandwidth = bandwidth;
        }
    }
}

package org.mangui.hls
{
    import flash.external.ExternalInterface;
    import org.hola.ZExternalInterface;
    import org.hola.JSAPI;
    import org.hola.HSettings;
    import org.mangui.hls.event.HLSEvent;
    import org.mangui.hls.constant.HLSPlayStates;
    import org.mangui.hls.model.Level;
    import org.mangui.hls.model.Fragment;
    import flash.utils.setTimeout;
    import flash.net.NetStreamAppendBytesAction;

    public class HLSJS
    {
        private static var _inited: Boolean = false;
        private static var _duration: Number;
        private static var _bandwidth: Number = -1;
        private static var _url: String;
        private static var _currentFrag: String;
        private static var _state: String;
        private static var _hls: HLS;
        private static var _silence: Boolean = false;

        public static function init():void{
            if (_inited || !ZExternalInterface.avail())
                return;
            _inited = true;
            JSAPI.init();
            ExternalInterface.addCallback("hola_version", hola_version);
            ExternalInterface.addCallback("hola_hls_version", hola_version);
            ExternalInterface.addCallback("hola_hls_get_video_url",
                hola_hls_get_video_url);
            ExternalInterface.addCallback("hola_hls_get_position",
                hola_hls_get_position);
            ExternalInterface.addCallback("hola_hls_get_duration",
                hola_hls_get_duration);
            ExternalInterface.addCallback("hola_hls_get_buffer_sec",
                hola_hls_get_buffer_sec);
            ExternalInterface.addCallback("hola_hls_get_state",
                hola_hls_get_state);
            ExternalInterface.addCallback("hola_hls_get_current_fragment",
                hola_hls_get_current_fragment);
            ExternalInterface.addCallback("hola_hls_get_levels",
                hola_hls_get_levels);
            ExternalInterface.addCallback("hola_hls_get_levels_async",
                hola_hls_get_levels_async);
            ExternalInterface.addCallback("hola_hls_get_segment_info",
                hola_hls_get_segment_info);
            ExternalInterface.addCallback("hola_hls_get_level",
                hola_hls_get_level);
            ExternalInterface.addCallback("hola_hls_get_bitrate",
                hola_hls_get_bitrate);
            ExternalInterface.addCallback("hola_hls_get_decoded_frames",
                hola_hls_get_decoded_frames);
            ExternalInterface.addCallback("hola_setBandwidth",
                hola_setBandwidth);
            ExternalInterface.addCallback("hola_hls_setBandwidth",
                hola_setBandwidth);
            ExternalInterface.addCallback("hola_hls_get_type",
                hola_hls_get_type);
            ExternalInterface.addCallback("hola_hls_load_fragment", hola_hls_load_fragment);
            ExternalInterface.addCallback("hola_hls_abort_fragment", hola_hls_abort_fragment);
            ExternalInterface.addCallback("hola_hls_load_level", hola_hls_load_level);
            ExternalInterface.addCallback('hola_hls_flush_stream', hola_hls_flush_stream);
        }

        public static function HLSnew(hls:HLS):void{
            _hls = hls;
            _state = HLSPlayStates.IDLE;
            // track duration events
            hls.addEventListener(HLSEvent.PLAYLIST_DURATION_UPDATED,
                on_playlist_duration_updated);
            // track playlist-url/state
            hls.addEventListener(HLSEvent.PLAYBACK_STATE, on_playback_state);
            hls.addEventListener(HLSEvent.SEEK_STATE, on_seek_state);
            hls.addEventListener(HLSEvent.MANIFEST_LOADED, on_manifest_loaded);
            hls.addEventListener(HLSEvent.MANIFEST_LOADING, on_manifest_loading);
            hls.addEventListener(HLSEvent.FRAGMENT_LOADING, on_fragment_loading);
            // notify js events
            hls.addEventListener(HLSEvent.MANIFEST_LOADING, on_event);
            hls.addEventListener(HLSEvent.MANIFEST_PARSED, on_event);
            hls.addEventListener(HLSEvent.MANIFEST_LOADED, on_event);
            hls.addEventListener(HLSEvent.LEVEL_LOADING, on_event);
            hls.addEventListener(HLSEvent.LEVEL_LOADING_ABORTED, on_event);
            hls.addEventListener(HLSEvent.LEVEL_LOADED, on_level_loaded);
            hls.addEventListener(HLSEvent.LEVEL_SWITCH, on_event);
            hls.addEventListener(HLSEvent.LEVEL_ENDLIST, on_event);
            hls.addEventListener(HLSEvent.FRAGMENT_LOADING, on_event);
            hls.addEventListener(HLSEvent.FRAGMENT_LOADED, on_event);
            hls.addEventListener(HLSEvent.FRAGMENT_LOAD_EMERGENCY_ABORTED,
                on_event);
            hls.addEventListener(HLSEvent.FRAGMENT_PLAYING, on_event);
            hls.addEventListener(HLSEvent.FRAGMENT_SKIPPED, on_event);
            hls.addEventListener(HLSEvent.AUDIO_TRACKS_LIST_CHANGE, on_event);
            hls.addEventListener(HLSEvent.AUDIO_TRACK_SWITCH, on_event);
            hls.addEventListener(HLSEvent.AUDIO_LEVEL_LOADING, on_event);
            hls.addEventListener(HLSEvent.AUDIO_LEVEL_LOADED, on_event);
            hls.addEventListener(HLSEvent.TAGS_LOADED, on_event);
            hls.addEventListener(HLSEvent.LAST_VOD_FRAGMENT_LOADED, on_event);
            hls.addEventListener(HLSEvent.WARNING, on_event);
            hls.addEventListener(HLSEvent.ERROR, on_event);
            hls.addEventListener(HLSEvent.MEDIA_TIME, on_event);
            hls.addEventListener(HLSEvent.PLAYBACK_STATE, on_event);
            hls.addEventListener(HLSEvent.STREAM_TYPE_DID_CHANGE, on_event);
            hls.addEventListener(HLSEvent.PLAYBACK_COMPLETE, on_event);
            hls.addEventListener(HLSEvent.PLAYLIST_DURATION_UPDATED,
                on_event);
            hls.addEventListener(HLSEvent.ID3_UPDATED, on_event);
            hls.addEventListener(HLSEvent.FPS_DROP, on_event);
            hls.addEventListener(HLSEvent.FPS_DROP_LEVEL_CAPPING, on_event);
            hls.addEventListener(HLSEvent.FPS_DROP_SMOOTH_LEVEL_SWITCH,
                on_event);
            hls.addEventListener(HLSEvent.LIVE_LOADING_STALLED, on_event);
            JSAPI.postMessage('flashls.hlsNew');
        }

        public static function HLSdispose(hls:HLS):void{
            JSAPI.postMessage('flashls.hlsDispose');
            _duration = 0;
            _bandwidth = -1;
            _url = null;
            _state = HLSPlayStates.IDLE;
            _hls = null;
        }

        public static function get bandwidth():Number{
            return HSettings.gets('mode')=='adaptive' ? _bandwidth : -1;
        }

        private static function on_manifest_loaded(e:HLSEvent):void{
            _duration = e.levels[_hls.startLevel].duration;
        }

        private static function on_playlist_duration_updated(e:HLSEvent):void{
            _duration = e.duration;
        }

        private static function on_fragment_loading(e: HLSEvent): void
        {
            _currentFrag = e.url;
        }

        private static function on_manifest_loading(e:HLSEvent):void{
            _url = e.url;
            _state = "LOADING";
            on_event(new HLSEvent(HLSEvent.PLAYBACK_STATE, _state));
        }

        private static function on_playback_state(e:HLSEvent):void{
            _state = e.state;
        }

        private static function on_level_loaded(e: HLSEvent): void
        {
            JSAPI.postMessage('flashls.'+e.type, {level: level_to_object(_hls.levels[e.loadMetrics.level])});
        }

        private static function on_seek_state(e: HLSEvent): void
        {
            JSAPI.postMessage('flashls.'+e.type, {state: e.state, seek_pos: _hls.position, buffer: _hls.stream.bufferLength});
        }

        private static function on_event(e: HLSEvent): void
        {
            if (_silence)
                return;
            JSAPI.postMessage('flashls.'+e.type, {url: e.url, level: e.level,
                duration: e.duration, levels: e.levels, error: e.error,
                loadMetrics: e.loadMetrics, playMetrics: e.playMetrics,
                mediatime: e.mediatime, state: e.state,
                audioTrack: e.audioTrack, streamType: e.streamType});
        }

        private static function hola_version(): Object
        {
            return {
                flashls_version: '0.4.4.20',
                patch_version: '2.0.14'
            };
        }

        private static function hola_hls_get_video_url(): String
        {
            return _url;
        }

        private static function hola_hls_get_position(): Number
        {
            return _hls.position;
        }

        private static function hola_hls_get_duration(): Number
        {
            return _duration;
        }

        private static function hola_hls_get_decoded_frames(): Number
        {
            return _hls.stream.decodedFrames;
        }

        private static function hola_hls_get_buffer_sec(): Number
        {
            return _hls.stream.bufferLength;
        }

        private static function hola_hls_get_state(): String
        {
            return _state;
        }

        private static function hola_hls_get_type(): String
        {
            return _hls.type;
        }

        private static function hola_hls_load_fragment(level: Number, frag: Number, url: String): Object
        {
            if (HSettings.gets('mode')!='hola_adaptive')
                return 0;
            return _hls.loadFragment(level, frag, url);
        }

        private static function hola_hls_flush_stream(): void
        {
            if (_hls.stream.decodedFrames === 0)
                return;
            _silence = true;
            _hls.stream.close();
            _hls.stream.play();
            _hls.stream.pause();
            _silence = false;
        }

        private static function hola_hls_abort_fragment(ldr_id: String): void
        {
            if (HSettings.gets('mode')!='hola_adaptive')
                return;
            _hls.abortFragment(ldr_id);
        }

        private static function hola_hls_load_level(level: Number): void
        {
            if (HSettings.gets('mode')!='hola_adaptive')
                return;
            if (!_hls.isStartLevelSet())
                _hls.startLevel = level;
            _hls.dispatchEvent(new HLSEvent(HLSEvent.LEVEL_SWITCH, level));
        }

        private static function level_to_object(l: Level): Object
        {
            var fragments: Array = [];
            for (var i: int = 0; i<l.fragments.length; i++)
            {
                var fragment: Fragment = l.fragments[i];
                fragments.push({url: fragment.url,
                    duration: fragment.duration, seqnum: fragment.seqnum});
            }
            return {url: l.url, bitrate: l.bitrate, fragments: fragments,
                index: l.index, width: l.width, height: l.height, audio: l.audio};
        }

        private static function hola_hls_get_levels(): Object
        {
            var levels: Vector.<Object> = new Vector.<Object>(_hls.levels.length);
            for (var i: int = 0; i<_hls.levels.length; i++)
            {
                var l: Level = _hls.levels[i];
                // no fragments returned, use get_segment_info for fragm.info
                levels[i] = Object({url: l.url, bitrate: l.bitrate,
                    index: l.index, fragments: [], width: l.width,
                    height: l.height});
            }
            return levels;
        }

        private static function hola_hls_get_current_fragment(): String
        {
            return _currentFrag;
        }

        private static function hola_hls_get_levels_async(): void
        {
            setTimeout(function(): void
            {
                var levels: Array = [];
                for (var i: int = 0; i<_hls.levels.length; i++)
                    levels.push(level_to_object(_hls.levels[i]));
                JSAPI.postMessage('flashls.hlsAsyncMessage', {type: 'get_levels', msg: levels});
            }, 0);
        }

        private static function hola_hls_get_segment_info(url: String): Object
        {
            for (var i: int = 0; i<_hls.levels.length; i++)
            {
                var l: Level = _hls.levels[i];
                for (var j:int = 0; j<l.fragments.length; j++)
                {
                    if (url==l.fragments[j].url)
                    {
                        return Object({fragment: l.fragments[j],
                            level: Object({url: l.url, bitrate: l.bitrate,
                            index: l.index})});
                    }
                }
            }
            return undefined;
        }

        private static function hola_hls_get_bitrate(): Number
        {
            return _hls.loadLevel<_hls.levels.length ? _hls.levels[_hls.loadLevel].bitrate : 0;
        }

        private static function hola_hls_get_level(): String
        {
            return _hls.loadLevel<_hls.levels.length ? _hls.levels[_hls.loadLevel].url : undefined;
        }

        private static function hola_setBandwidth(bandwidth: Number): void
        {
            _bandwidth = bandwidth;
        }
    }
}

add width and height to level object

add width and height to level object


class Spawn: ScriptObject
{
	String SpawnItem;
	String SpawnName;

	Spawn()
	{
		SpawnItem = "";
		SpawnName = "";
	}

	void DelayedStart()
	{
		log.Debug(node.name + " spawning...");
		Node@ parent = node.parent;

		if (SpawnItem != "")
		{
			Node@ newNode = parent.CreateChild(SpawnName);
			log.Debug("Create new node");
			newNode.position = node.position;
			newNode.scale = node.scale;
			newNode.rotation = node.rotation;
			log.Debug("loc=" + newNode.position.ToString() + ", rot=" + newNode.rotation.ToString() + ", scale=" + newNode.scale.ToString());
			log.Debug("loc=" + node.position.ToString() + ", rot=" + node.rotation.ToString() + ", scale=" + node.scale.ToString());
			XMLFile@ xmlFile = cache.GetResource("XMLFile", SpawnItem);
			newNode.LoadXML(xmlFile.root);

			node.Remove();
			log.Debug("Remove self");
		}
	}

	void Save(Serializer& serializer)
	{
		serializer.WriteString(SpawnItem);
		serializer.WriteString(SpawnName);
	}

	void Load(Deserializer& deserializer)
	{
		log.Debug("Deserializing");
		SpawnItem = deserializer.ReadString();
		log.Debug("SpawnItem: " + SpawnItem);
		SpawnName = deserializer.ReadString();
		log.Debug("SpawnName: " + SpawnName);
	}

	void Stop()
	{
	}
}

class Spawn: ScriptObject
{
	String SpawnItem;
	String SpawnName;

	Spawn()
	{
		SpawnItem = "";
		SpawnName = "";
	}

	void DelayedStart()
	{
		log.Debug(node.name + " spawning...");
		Node@ parent = node.parent;

		if (SpawnItem != "")
		{
			Node@ newNode = parent.CreateChild(SpawnName);
			log.Debug("Create new node");
			XMLFile@ xmlFile = cache.GetResource("XMLFile", SpawnItem);
			newNode.LoadXML(xmlFile.root);

			newNode.position = node.position;
			newNode.scale = node.scale;
			newNode.rotation = node.rotation;
			log.Debug("loc=" + newNode.position.ToString() + ", rot=" + newNode.rotation.ToString() + ", scale=" + newNode.scale.ToString());
			log.Debug("loc=" + node.position.ToString() + ", rot=" + node.rotation.ToString() + ", scale=" + node.scale.ToString());

			node.Remove();
			log.Debug("Remove self");
		}
	}

	void Save(Serializer& serializer)
	{
		serializer.WriteString(SpawnItem);
		serializer.WriteString(SpawnName);
	}

	void Load(Deserializer& deserializer)
	{
		log.Debug("Deserializing");
		SpawnItem = deserializer.ReadString();
		log.Debug("SpawnItem: " + SpawnItem);
		SpawnName = deserializer.ReadString();
		log.Debug("SpawnName: " + SpawnName);
	}

	void Stop()
	{
	}
}

Correct minor bug with spawning system

Correct minor bug with spawning system


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

package com.threerings.ezgame.client {

import mx.core.UIComponent;
import mx.controls.CheckBox;
import mx.controls.ComboBox;
import mx.controls.HSlider;
import mx.controls.Label;

import com.threerings.util.StringUtil;

import com.threerings.flex.LabeledSlider;

import com.threerings.parlor.game.client.FlexGameConfigurator;

import com.threerings.ezgame.data.EZGameConfig;

/**
 * Adds custom configuration of options specified in XML.
 */
public class EZGameConfigurator extends FlexGameConfigurator
{
    /**
     * Set a String of configData, which is hopefully XML formatted with
     * some game configuration options.
     */
    public function setXMLConfig (config :XML) :void
    {
        var log :Log = Log.getLog(this);

        for each (var param :XML in config..params.children()) {
            if (StringUtil.isBlank(param.@ident)) {
                log.warning("Bad configuration option: no 'ident' in " +
                    param + ", ignoring.");
                continue;
            }
            switch (param.localName().toLowerCase()) {
            case "range":
                addRangeOption(param, log);
                break;

            case "choice":
                addChoiceOption(param, log);
                break;

            case "toggle":
                addToggleOption(param, log);
                break;

            default:
                log.warning("Unknown XML configuration option: " + param +
                    ", ignoring.");
                break;
            }
        }
    }

    /**
     * Add a control that came from parsing our custom option XML.
     */
    protected function addXMLControl (spec :XML, control :UIComponent) :void
    {
        var ident :String = String(spec.@ident);
        var name :String = String(spec.@name);
        var tip :String = String(spec.@tip);
        if (StringUtil.isBlank(name)) {
            name = ident;
        }

        var lbl :Label = new Label();
        lbl.text = name + ":";
        lbl.toolTip = tip;
        control.toolTip = tip;

        addControl(lbl, control);
        _customConfigs.push(ident, control);
    }

    /**
     * Adds a 'range' option specified in XML
     */
    protected function addRangeOption (spec :XML, log :Log) :void
    {
        var min :Number = Number(spec.@minimum);
        var max :Number = Number(spec.@maximum);
        var start :Number = Number(spec.@start);
        if (isNaN(min) || isNaN(max) || isNaN(start)) {
            log.warning("Unable to parse range specification. " +
                "Required numeric values: minimum, maximum, start " +
                "[xml=" + spec + "].");
            return;
        }

        var slider :HSlider = new HSlider();
        slider.minimum = min;
        slider.maximum = max;
        slider.value = start;
        slider.liveDragging = true;
        slider.snapInterval = 1;

        addXMLControl(spec, new LabeledSlider(slider));
    }

    /**
     * Adds a 'choice' option specified in XML
     */
    protected function addChoiceOption (spec :XML, log :Log) :void
    {
        if (spec.@choices.length == 0 || spec.@start.length == 0) {
            log.warning("Unable to parse choice specification. " +
                "Required 'choices' or 'start' is missing. " +
                "[xml=" + spec + "].");
            return;
        }

        var choiceString :String = String(spec.@choices);
        var start :String = String(spec.@start);

        var choices :Array = choiceString.split(",");
        var startDex :int = choices.indexOf(start);
        if (startDex == -1) {
            log.warning("Choice start value does not appear in list of choices "+
                "[xml=" + spec + "].");
            return;
        }

        var box :ComboBox = new ComboBox();
        box.dataProvider = choices;
        box.selectedIndex = startDex;

        addXMLControl(spec, box);
    }

    /**
     * Adds a 'toggle' option specified in XML
     */
    protected function addToggleOption (spec :XML, log :Log) :void
    {
        if (spec.@start.length == 0) {
            log.warning("Unable to parse toggle specification. " +
                "Required 'start' is missing. " +
                "[xml=" + spec + "].");
            return;
        }

        var startStr :String = String(spec.@start).toLowerCase();

        var box :CheckBox = new CheckBox();
        box.selected = ("true" == startStr);

        addXMLControl(spec, box);
    }

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

        // if there were any custom XML configs, flush those as well.
        if (_customConfigs.length > 0) {
            var options :Object = {};

            for (var ii :int = 0; ii < _customConfigs.length; ii += 2) {
                var ident :String = String(_customConfigs[ii]);
                var control :UIComponent = (_customConfigs[ii + 1] as UIComponent);
                if (control is LabeledSlider) {
                    options[ident] = (control as LabeledSlider).slider.value;

                } else if (control is CheckBox) {
                    options[ident] = (control as CheckBox).selected;

                } else if (control is ComboBox) {
                    options[ident] = (control as ComboBox).value;

                } else {
                    Log.getLog(this).warning("Unknow custom config type " + control);
                }
            }

            (_config as EZGameConfig).customConfig = options;
        }
    }

    /** Contains pairs of identString, control, identString, control.. */
    protected var _customConfigs :Array = [];
}
}

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

package com.threerings.ezgame.client {

import mx.core.UIComponent;
import mx.controls.CheckBox;
import mx.controls.ComboBox;
import mx.controls.HSlider;
import mx.controls.Label;

import com.threerings.util.StringUtil;

import com.threerings.flex.LabeledSlider;

import com.threerings.parlor.game.client.FlexGameConfigurator;

import com.threerings.ezgame.data.EZGameConfig;

/**
 * Adds custom configuration of options specified in XML.
 */
public class EZGameConfigurator extends FlexGameConfigurator
{
    /**
     * Set XML game configuration options.
     */
    public function setXMLConfig (config :XML) :void
    {
        var log :Log = Log.getLog(this);

        for each (var param :XML in config..params.children()) {
            if (StringUtil.isBlank(param.@ident)) {
                log.warning("Bad configuration option: no 'ident' in " +
                    param + ", ignoring.");
                continue;
            }
            switch (param.localName().toLowerCase()) {
            case "range":
                addRangeOption(param, log);
                break;

            case "choice":
                addChoiceOption(param, log);
                break;

            case "toggle":
                addToggleOption(param, log);
                break;

            default:
                log.warning("Unknown XML configuration option: " + param +
                    ", ignoring.");
                break;
            }
        }
    }

    /**
     * Add a control that came from parsing our custom option XML.
     */
    protected function addXMLControl (spec :XML, control :UIComponent) :void
    {
        var ident :String = String(spec.@ident);
        var name :String = String(spec.@name);
        var tip :String = String(spec.@tip);
        if (StringUtil.isBlank(name)) {
            name = ident;
        }

        var lbl :Label = new Label();
        lbl.text = name + ":";
        lbl.toolTip = tip;
        control.toolTip = tip;

        addControl(lbl, control);
        _customConfigs.push(ident, control);
    }

    /**
     * Adds a 'range' option specified in XML
     */
    protected function addRangeOption (spec :XML, log :Log) :void
    {
        var min :Number = Number(spec.@minimum);
        var max :Number = Number(spec.@maximum);
        var start :Number = Number(spec.@start);
        if (isNaN(min) || isNaN(max) || isNaN(start)) {
            log.warning("Unable to parse range specification. " +
                "Required numeric values: minimum, maximum, start " +
                "[xml=" + spec + "].");
            return;
        }

        var slider :HSlider = new HSlider();
        slider.minimum = min;
        slider.maximum = max;
        slider.value = start;
        slider.liveDragging = true;
        slider.snapInterval = 1;

        addXMLControl(spec, new LabeledSlider(slider));
    }

    /**
     * Adds a 'choice' option specified in XML
     */
    protected function addChoiceOption (spec :XML, log :Log) :void
    {
        if (spec.@choices.length == 0 || spec.@start.length == 0) {
            log.warning("Unable to parse choice specification. " +
                "Required 'choices' or 'start' is missing. " +
                "[xml=" + spec + "].");
            return;
        }

        var choiceString :String = String(spec.@choices);
        var start :String = String(spec.@start);

        var choices :Array = choiceString.split(",");
        var startDex :int = choices.indexOf(start);
        if (startDex == -1) {
            log.warning("Choice start value does not appear in list of choices "+
                "[xml=" + spec + "].");
            return;
        }

        var box :ComboBox = new ComboBox();
        box.dataProvider = choices;
        box.selectedIndex = startDex;

        addXMLControl(spec, box);
    }

    /**
     * Adds a 'toggle' option specified in XML
     */
    protected function addToggleOption (spec :XML, log :Log) :void
    {
        if (spec.@start.length == 0) {
            log.warning("Unable to parse toggle specification. " +
                "Required 'start' is missing. " +
                "[xml=" + spec + "].");
            return;
        }

        var startStr :String = String(spec.@start).toLowerCase();

        var box :CheckBox = new CheckBox();
        box.selected = ("true" == startStr);

        addXMLControl(spec, box);
    }

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

        // if there were any custom XML configs, flush those as well.
        if (_customConfigs.length > 0) {
            var options :Object = {};

            for (var ii :int = 0; ii < _customConfigs.length; ii += 2) {
                var ident :String = String(_customConfigs[ii]);
                var control :UIComponent = (_customConfigs[ii + 1] as UIComponent);
                if (control is LabeledSlider) {
                    options[ident] = (control as LabeledSlider).slider.value;

                } else if (control is CheckBox) {
                    options[ident] = (control as CheckBox).selected;

                } else if (control is ComboBox) {
                    options[ident] = (control as ComboBox).value;

                } else {
                    Log.getLog(this).warning("Unknow custom config type " + control);
                }
            }

            (_config as EZGameConfig).customConfig = options;
        }
    }

    /** Contains pairs of identString, control, identString, control.. */
    protected var _customConfigs :Array = [];
}
}

update comment

update comment

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


# Makefile to rebuild SM64 split image

################ Target Executable and Sources ###############

# TARGET is used to specify prefix in all build artifacts including
# output ROM is $(TARGET).z64
TARGET = sm64

# BUILD_DIR is location where all build artifacts are placed
BUILD_DIR = build

##################### Compiler Options #######################
CROSS = mips64-elf-
AS = $(CROSS)as
LD = $(CROSS)ld
OBJDUMP = $(CROSS)objdump
OBJCOPY = $(CROSS)objcopy

ASFLAGS = -mtune=vr4300 -march=vr4300
LDFLAGS = -T $(LD_SCRIPT) -Map $(BUILD_DIR)/sm64.map

####################### Other Tools #########################

# N64 tools
TOOLS_DIR = .
MIO0TOOL = $(TOOLS_DIR)/mio0
N64CKSUM = $(TOOLS_DIR)/n64cksum
N64GRAPHICS = $(TOOLS_DIR)/n64graphics
EMULATOR = mupen64plus
EMU_FLAGS = --noosd
LOADER = loader64
LOADER_FLAGS = -vwf

######################## Targets #############################

default: all

# file dependencies generated by splitter
MAKEFILE_GEN = gen/Makefile.gen
include $(MAKEFILE_GEN)

all: $(TARGET).gen.z64

clean:
	rm -f $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).o $(BUILD_DIR)/$(TARGET).bin $(TARGET).v64

$(MIO0_DIR)/%.mio0: $(MIO0_DIR)/%.bin
	$(MIO0TOOL) $< $@

$(BUILD_DIR):
	mkdir -p $(BUILD_DIR)

$(BUILD_DIR)/$(TARGET).o: gen/$(TARGET).s Makefile.as $(MAKEFILE_GEN) $(MIO0_FILES) $(LEVEL_FILES) | $(BUILD_DIR)
	$(AS) $(ASFLAGS) -o $@ $<

$(BUILD_DIR)/$(TARGET).elf: $(BUILD_DIR)/$(TARGET).o $(LD_SCRIPT)
	$(LD) $(LDFLAGS) -o $@ $< $(LIBS)

$(BUILD_DIR)/$(TARGET).bin: $(BUILD_DIR)/$(TARGET).elf
	$(OBJCOPY) $< $@ -O binary

# final z64 updates checksum
$(TARGET).gen.z64: $(BUILD_DIR)/$(TARGET).bin
	$(N64CKSUM) $< $@

$(BUILD_DIR)/$(TARGET).gen.hex: $(TARGET).gen.z64
	xxd $< > $@

$(BUILD_DIR)/$(TARGET).objdump: $(BUILD_DIR)/$(TARGET).elf
	$(OBJDUMP) -D $< > $@

diff: $(BUILD_DIR)/$(TARGET).gen.hex
	diff sm64.hex $< | wc -l

test: $(TARGET).gen.z64
	$(EMULATOR) $(EMU_FLAGS) $<

load: $(TARGET).gen.z64
	$(LOADER) $(LOADER_FLAGS) $<

.PHONY: all clean default diff test

# Makefile to rebuild SM64 split image

################ Target Executable and Sources ###############

# TARGET is used to specify prefix in all build artifacts including
# output ROM is $(TARGET).z64
TARGET = sm64

# BUILD_DIR is location where all build artifacts are placed
BUILD_DIR = build

##################### Compiler Options #######################
CROSS = mips64-elf-
AS = $(CROSS)as
CC = $(CROSS)gcc
LD = $(CROSS)ld
OBJDUMP = $(CROSS)objdump
OBJCOPY = $(CROSS)objcopy

ASFLAGS = -mtune=vr4300 -march=vr4300
CFLAGS  = -Wall -O2 -mtune=vr4300 -march=vr4300 -G 0 -c
LDFLAGS = -T $(LD_SCRIPT) -Map $(BUILD_DIR)/sm64.map

####################### Other Tools #########################

# N64 tools
TOOLS_DIR = .
MIO0TOOL = $(TOOLS_DIR)/mio0
N64CKSUM = $(TOOLS_DIR)/n64cksum
N64GRAPHICS = $(TOOLS_DIR)/n64graphics
EMULATOR = mupen64plus
EMU_FLAGS = --noosd
LOADER = loader64
LOADER_FLAGS = -vwf

######################## Targets #############################

default: all

# file dependencies generated by splitter
MAKEFILE_GEN = gen/Makefile.gen
include $(MAKEFILE_GEN)

all: $(TARGET).gen.z64

clean:
	rm -f $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).o $(BUILD_DIR)/$(TARGET).bin $(TARGET).v64

$(MIO0_DIR)/%.mio0: $(MIO0_DIR)/%.bin
	$(MIO0TOOL) $< $@

$(BUILD_DIR):
	mkdir -p $(BUILD_DIR)

$(BUILD_DIR)/$(TARGET).o: gen/$(TARGET).s Makefile.as $(MAKEFILE_GEN) $(MIO0_FILES) $(LEVEL_FILES) | $(BUILD_DIR)
	$(AS) $(ASFLAGS) -o $@ $<

$(BUILD_DIR)/%.o: gen/%.c Makefile.as | $(BUILD_DIR)
	$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/$(TARGET).elf: $(BUILD_DIR)/$(TARGET).o $(LD_SCRIPT)
	$(LD) $(LDFLAGS) -o $@ $< $(LIBS)

$(BUILD_DIR)/$(TARGET).bin: $(BUILD_DIR)/$(TARGET).elf
	$(OBJCOPY) $< $@ -O binary

# final z64 updates checksum
$(TARGET).gen.z64: $(BUILD_DIR)/$(TARGET).bin
	$(N64CKSUM) $< $@

$(BUILD_DIR)/$(TARGET).gen.hex: $(TARGET).gen.z64
	xxd $< > $@

$(BUILD_DIR)/$(TARGET).objdump: $(BUILD_DIR)/$(TARGET).elf
	$(OBJDUMP) -D $< > $@

diff: $(BUILD_DIR)/$(TARGET).gen.hex
	diff sm64.hex $< | wc -l

test: $(TARGET).gen.z64
	$(EMULATOR) $(EMU_FLAGS) $<

load: $(TARGET).gen.z64
	$(LOADER) $(LOADER_FLAGS) $<

.PHONY: all clean default diff test

Add MIPS C compiler flags and target to Makefile


////////////////////////////////////////////////////////////////////////////////
//
//  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 products
{
	public class Product
	{
		public function Product(id:String,title:String,detail:Number,sales2013:Number, sales2014 ,image:String)
		{
			this.id = id;
			this.title = title;
			this.detail = detail;
			this.sales2013 = sales2013;
			this.sales2014 = sales2014;
			this.image = image;
		}

		public var id:String;
		public var title:String;
		public var detail:Number;
		public var image:String;
		public var sales2013:Number;
		public var sales2014:Number;

		public function toString():String
		{
			return title;
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//  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 products
{
	public class Product
	{
		public function Product(id:String, title:String, detail:Number,sales2013:Number, sales2014:Number ,image:String)
		{
			this.id = id;
			this.title = title;
			this.detail = detail;
			this.sales2013 = sales2013;
			this.sales2014 = sales2014;
			this.image = image;
		}

		public var id:String;
		public var title:String;
		public var detail:Number;
		public var image:String;
		public var sales2013:Number;
		public var sales2014:Number;

		public function toString():String
		{
			return title;
		}
	}
}

Add missing type in Product.as

Add missing type in Product.as


package aerys.minko.render.shader.part
{
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.type.enum.SamplerFiltering;
	import aerys.minko.type.enum.SamplerMipMapping;
	import aerys.minko.type.enum.SamplerWrapping;
	import aerys.minko.type.stream.format.VertexComponent;

	public class DiffuseShaderPart extends ShaderPart
	{
		/**
		 * The shader part to use a diffuse map or fallback and use a solid color.
		 *
		 * @param main
		 *
		 */
		public function DiffuseShaderPart(main : Shader)
		{
			super(main);
		}

		public function getDiffuse() : SFloat
		{
			var diffuseColor : SFloat	= null;

			if (meshBindings.propertyExists('diffuseMap'))
			{
				var diffuseMap	: SFloat	= meshBindings.getTextureParameter(
					'diffuseMap',
					meshBindings.getConstant('diffuseFiltering', SamplerFiltering.LINEAR),
					meshBindings.getConstant('diffuseMipMapping', SamplerMipMapping.LINEAR),
					meshBindings.getConstant('diffuseWrapping', SamplerWrapping.REPEAT)
				);

				diffuseColor = sampleTexture(diffuseMap,interpolate(vertexUV.xy));
			}
			else if (meshBindings.propertyExists('diffuseColor'))
			{
				diffuseColor = meshBindings.getParameter('diffuseColor', 4);
			}
			else
			{
				diffuseColor = float4(0., 0., 0., 1.);
			}

			// Apply HLSA modifiers
			if (meshBindings.propertyExists('diffuseColorMatrix'))
			{
				diffuseColor = multiply4x4(
					diffuseColor,
					meshBindings.getParameter('diffuseColorMatrix', 16)
				);
			}

			return diffuseColor;
		}
	}
}

package aerys.minko.render.shader.part
{
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.type.enum.SamplerFiltering;
	import aerys.minko.type.enum.SamplerMipMapping;
	import aerys.minko.type.enum.SamplerWrapping;

	public class DiffuseShaderPart extends ShaderPart
	{
		/**
		 * The shader part to use a diffuse map or fallback and use a solid color.
		 *
		 * @param main
		 *
		 */
		public function DiffuseShaderPart(main : Shader)
		{
			super(main);
		}

		public function getDiffuse() : SFloat
		{
			var diffuseColor : SFloat	= null;

			if (meshBindings.propertyExists('diffuseMap'))
			{
				var uv			: SFloat	= vertexUV.xy;
				var diffuseMap	: SFloat	= meshBindings.getTextureParameter(
					'diffuseMap',
					meshBindings.getConstant('diffuseFiltering', SamplerFiltering.LINEAR),
					meshBindings.getConstant('diffuseMipMapping', SamplerMipMapping.LINEAR),
					meshBindings.getConstant('diffuseWrapping', SamplerWrapping.REPEAT)
				);

				if (meshBindings.propertyExists('diffuseUVScale'))
					uv.scaleBy(meshBindings.getParameter('diffuseUVScale', 2));

				if (meshBindings.propertyExists('diffuseUVOffset'))
					uv.incrementBy(meshBindings.getParameter('diffuseUVOffset', 2));

				diffuseColor = sampleTexture(diffuseMap,interpolate(uv));
			}
			else if (meshBindings.propertyExists('diffuseColor'))
			{
				diffuseColor = meshBindings.getParameter('diffuseColor', 4);
			}
			else
			{
				diffuseColor = float4(0., 0., 0., 1.);
			}

			// Apply HLSA modifiers
			if (meshBindings.propertyExists('diffuseColorMatrix'))
			{
				diffuseColor = multiply4x4(
					diffuseColor,
					meshBindings.getParameter('diffuseColorMatrix', 16)
				);
			}

			return diffuseColor;
		}
	}
}

Add support for properties 'diffuseUVOffset' and 'diffuseUVScale'.


/*
 *  FRESteamWorks.h
 *  This file is part of FRESteamWorks.
 *
 *  Created by David ´Oldes´ Oliva on 3/29/12.
 *  Contributors: Ventero <http://github.com/Ventero>
 *  Copyright (c) 2012 Amanita Design. All rights reserved.
 *  Copyright (c) 2012-2013 Level Up Labs, LLC. All rights reserved.
 */

package
{
	import com.amanitadesign.steam.FRESteamWorks;
	import com.amanitadesign.steam.SteamConstants;
	import com.amanitadesign.steam.SteamEvent;
	import com.amanitadesign.steam.WorkshopConstants;

	import flash.desktop.NativeApplication;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.display.StageDisplayState;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.utils.ByteArray;

	public class FRESteamWorksTest extends Sprite
	{
		public var Steamworks:FRESteamWorks = new FRESteamWorks();
		public var tf:TextField;

		private var _buttonPos:int = 5;
		private var _appId:uint;

		public function FRESteamWorksTest()
		{
			tf = new TextField();
			tf.x = 160;
			tf.width = stage.stageWidth - tf.x;
			tf.height = stage.stageHeight;
			addChild(tf);

			addButton("Check stats/achievements", checkAchievements);
			addButton("Toggle achievement", toggleAchievement);
			addButton("Toggle cloud enabled", toggleCloudEnabled);
			addButton("Toggle file", toggleFile);
			addButton("Publish file", publishFile);
			addButton("Toggle fullscreen", toggleFullscreen);
			addButton("Show Friends overlay", activateOverlay);
			addButton("List subscribed files", enumerateSubscribedFiles);

			Steamworks.addEventListener(SteamEvent.STEAM_RESPONSE, onSteamResponse);
			Steamworks.addOverlayWorkaround(stage, true);
			NativeApplication.nativeApplication.addEventListener(Event.EXITING, onExit);
			try {
				//Steamworks.useCrashHandler(480, "1.0", "Feb 20 2013", "21:42:20");
				if(!Steamworks.init()){
					log("STEAMWORKS API is NOT available");
					return;
				}

				log("STEAMWORKS API is available\n");
				log("User ID: " + Steamworks.getUserID());
				_appId = Steamworks.getAppID();
				log("App ID: " + _appId);
				log("Persona name: " + Steamworks.getPersonaName());
				log("isCloudEnabledForApp() == "+Steamworks.isCloudEnabledForApp());
				log("getFileCount() == "+Steamworks.getFileCount());
				log("fileExists('test.txt') == "+Steamworks.fileExists('test.txt'));
				log("getDLCCount() == " + Steamworks.getDLCCount());

				Steamworks.resetAllStats(true);
			} catch(e:Error) {
				log("*** ERROR ***");
				log(e.message);
				log(e.getStackTrace());
			}

		}
		private function log(value:String):void{
			tf.appendText(value+"\n");
			tf.scrollV = tf.maxScrollV;
		}

		public function writeFileToCloud(fileName:String, data:String):Boolean {
			var dataOut:ByteArray = new ByteArray();
			dataOut.writeUTFBytes(data);
			return Steamworks.fileWrite(fileName, dataOut);
		}

		public function readFileFromCloud(fileName:String):String {
			var dataIn:ByteArray = new ByteArray();
			var result:String;
			dataIn.position = 0;
			dataIn.length = Steamworks.getFileSize(fileName);

			if(dataIn.length>0 && Steamworks.fileRead(fileName,dataIn)){
				result = dataIn.readUTFBytes(dataIn.length);
			}
			return result;
		}

		private function checkAchievements(e:Event = null):void {
			if(!Steamworks.isReady) return;

			// current stats and achievement ids are from steam example app
			log("isAchievement('ACH_WIN_ONE_GAME') == "+Steamworks.isAchievement("ACH_WIN_ONE_GAME"));
			log("isAchievement('ACH_TRAVEL_FAR_SINGLE') == "+Steamworks.isAchievement("ACH_TRAVEL_FAR_SINGLE"));
			log("setStatFloat('FeetTraveled') == "+Steamworks.setStatFloat('FeetTraveled', 21.3));
			log("setStatInt('NumGames', 2) == "+Steamworks.setStatInt('NumGames', 2));
			Steamworks.storeStats();
			log("getStatInt('NumGames') == "+Steamworks.getStatInt('NumGames'));
			log("getStatFloat('FeetTraveled') == "+Steamworks.getStatFloat('FeetTraveled'));
		}

		private function toggleAchievement(e:Event = null):void{
			if(!Steamworks.isReady) return;

			var result:Boolean = Steamworks.isAchievement("ACH_WIN_ONE_GAME");
			log("isAchievement('ACH_WIN_ONE_GAME') == " + result);
			if(!result) {
				log("setAchievement('ACH_WIN_ONE_GAME') == "+Steamworks.setAchievement("ACH_WIN_ONE_GAME"));
			} else {
				log("clearAchievement('ACH_WIN_ONE_GAME') == "+Steamworks.clearAchievement("ACH_WIN_ONE_GAME"));
			}
		}

		private function toggleCloudEnabled(e:Event = null):void {
			if(!Steamworks.isReady) return;

			var enabled:Boolean = Steamworks.isCloudEnabledForApp();
			log("isCloudEnabledForApp() == " + enabled);
			log("setCloudEnabledForApp(" + !enabled + ") == " + Steamworks.setCloudEnabledForApp(!enabled));
			log("isCloudEnabledForApp() == " + Steamworks.isCloudEnabledForApp());
		}

		private function toggleFile(e:Event = null):void {
			if(!Steamworks.isReady) return;

			var result:Boolean = Steamworks.fileExists('test.txt');
			log("fileExists('test.txt') == " + result);
			if(result){
				log("readFileFromCloud('test.txt') == "+readFileFromCloud('test.txt') );
				log("fileDelete('test.txt') == "+Steamworks.fileDelete('test.txt'));
			} else {
				log("writeFileToCloud('test.txt','click') == "+writeFileToCloud('test.txt','click'));
			}
		}

		private function publishFile(e:Event = null):void {
			if(!Steamworks.isReady) return;

			var res:Boolean = Steamworks.publishWorkshopFile("test.txt", "", _appId,
				"Test.txt", "Test.txt", WorkshopConstants.VISIBILITY_Private,
				["TestTag"], WorkshopConstants.FILETYPE_Community);
			log("publishWorkshopFile('test.txt' ...) == " + res);
		}

		private function toggleFullscreen(e:Event = null):void {
			if(stage.displayState == StageDisplayState.NORMAL)
				stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
			else
				stage.displayState = StageDisplayState.NORMAL;
		}

		private function activateOverlay(e:Event = null):void {
			if(!Steamworks.isReady) return;

			log("isOverlayEnabled() == " + Steamworks.isOverlayEnabled());
			log("activateGameOverlay('Friends') == " + Steamworks.activateGameOverlay("Friends"));
			log("isOverlayEnabled() == " + Steamworks.isOverlayEnabled());
		}

		private function enumerateSubscribedFiles(e:Event = null):void {
			if(!Steamworks.isReady) return;

			log("enumerateUserSubscribedFiles(0) == " + Steamworks.enumerateUserSubscribedFiles(0));
		}

		private var id:String;
		private var handle:String;
		private function onSteamResponse(e:SteamEvent):void{
			var apiCall:Boolean;
			switch(e.req_type){
				case SteamConstants.RESPONSE_OnUserStatsStored:
					log("RESPONSE_OnUserStatsStored: "+e.response);
					break;
				case SteamConstants.RESPONSE_OnUserStatsReceived:
					log("RESPONSE_OnUserStatsReceived: "+e.response);
					break;
				case SteamConstants.RESPONSE_OnAchievementStored:
					log("RESPONSE_OnAchievementStored: "+e.response);
					break;
				case SteamConstants.RESPONSE_OnPublishWorkshopFile:
					log("RESPONSE_OnPublishWorkshopFile: " + e.response);
					var file:String = Steamworks.publishWorkshopFileResult();
					log("File published as " + file);
					log("subscribePublishedFile(...) == " + Steamworks.subscribePublishedFile(file));
					break;
				case SteamConstants.RESPONSE_OnEnumerateUserSubscribedFiles:
					log("RESPONSE_OnEnumerateUserSubscribedFiles: " + e.response);
					var result:SubscribedFilesResult = Steamworks.enumerateUserSubscribedFilesResult();
					log("User subscribed files: " + result.resultsReturned + "/" + result.totalResults);
					for(var i:int = 0; i < result.resultsReturned; i++) {
						id = result.publishedFileId[i];
						apiCall = Steamworks.getPublishedFileDetails(result.publishedFileId[i]);
						log(i + ": " + result.publishedFileId[i] + " (" + result.timeSubscribed[i] + ") - " + apiCall);
					}
					break;
				case SteamConstants.RESPONSE_OnGetPublishedFileDetails:
					log("RESPONSE_OnGetPublishedFileDetails: " + e.response);
					var res:FileDetailsResult = Steamworks.getPublishedFileDetailsResult(id);
					log("Result for " + id + ": " + res);
					if(res) {
						log("File: " + res.fileName + ", handle: " + res.fileHandle);
						handle = res.fileHandle;
						apiCall = Steamworks.UGCDownload(res.fileHandle, 0);
						log("UGCDownload(...) == " + apiCall);
					}
					break;
				case SteamConstants.RESPONSE_OnUGCDownload:
					log("RESPONSE_OnUGCDownload: " + e.response);
					var ugcResult:DownloadUGCResult = Steamworks.getUGCDownloadResult(handle);
					log("Result for " + handle + ": " + ugcResult);
					if(ugcResult) {
						log("File: " + ugcResult.fileName + ", handle: " + ugcResult.fileHandle + ", size: " + ugcResult.size);
						var ba:ByteArray = new ByteArray();
						ba.length = ugcResult.size;
						apiCall = Steamworks.UGCRead(ugcResult.fileHandle, ugcResult.size, 0, ba);
						log("UGCRead(...) == " + apiCall);
						if(apiCall) {
							log("Result length: " + ba.position + "//" + ba.length);
							log("Result: " + ba.readUTFBytes(ugcResult.size));
						}
						break;
					}
				default:
					log("STEAMresponse type:"+e.req_type+" response:"+e.response);
			}
		}

		private function onExit(e:Event):void{
			log("Exiting application, cleaning up");
			Steamworks.dispose();
		}

		private function addButton(label:String, callback:Function):void {
			var button:Sprite = new Sprite();
			button.graphics.beginFill(0xaaaaaa);
			button.graphics.drawRoundRect(0, 0, 150, 30, 5, 5);
			button.graphics.endFill();
			button.buttonMode = true;
			button.useHandCursor = true;
			button.addEventListener(MouseEvent.CLICK, callback);
			button.x = 5;
			button.y = _buttonPos;
			_buttonPos += button.height + 5;

			button.addEventListener(MouseEvent.MOUSE_OVER, function(e:MouseEvent):void {
				button.graphics.clear();
				button.graphics.beginFill(0xccccccc);
				button.graphics.drawRoundRect(0, 0, 150, 30, 5, 5);
				button.graphics.endFill();
			});

			button.addEventListener(MouseEvent.MOUSE_OUT, function(e:MouseEvent):void {
				button.graphics.clear();
				button.graphics.beginFill(0xaaaaaa);
				button.graphics.drawRoundRect(0, 0, 150, 30, 5, 5);
				button.graphics.endFill();
			});

			var text:TextField = new TextField();
			text.text = label;
			text.width = 140;
			text.height = 25;
			text.x = 5;
			text.y = 5;
			text.mouseEnabled = false;

			button.addChild(text);
			addChild(button);
		}
	}
}

/*
 *  FRESteamWorks.h
 *  This file is part of FRESteamWorks.
 *
 *  Created by David ´Oldes´ Oliva on 3/29/12.
 *  Contributors: Ventero <http://github.com/Ventero>
 *  Copyright (c) 2012 Amanita Design. All rights reserved.
 *  Copyright (c) 2012-2013 Level Up Labs, LLC. All rights reserved.
 */

package
{
	import com.amanitadesign.steam.FRESteamWorks;
	import com.amanitadesign.steam.SteamConstants;
	import com.amanitadesign.steam.SteamEvent;
	import com.amanitadesign.steam.WorkshopConstants;

	import flash.desktop.NativeApplication;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.display.StageDisplayState;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.utils.ByteArray;

	public class FRESteamWorksTest extends Sprite
	{
		public var Steamworks:FRESteamWorks = new FRESteamWorks();
		public var tf:TextField;

		private var _buttonPos:int = 5;
		private var _appId:uint;

		public function FRESteamWorksTest()
		{
			tf = new TextField();
			tf.x = 160;
			tf.width = stage.stageWidth - tf.x;
			tf.height = stage.stageHeight;
			addChild(tf);

			addButton("Check stats/achievements", checkAchievements);
			addButton("Toggle achievement", toggleAchievement);
			addButton("Toggle cloud enabled", toggleCloudEnabled);
			addButton("Toggle file", toggleFile);
			addButton("Publish file", publishFile);
			addButton("Toggle fullscreen", toggleFullscreen);
			addButton("Show Friends overlay", activateOverlay);
			addButton("List subscribed files", enumerateSubscribedFiles);
			addButton("List shared files", enumerateSharedFiles);
			addButton("List workshop files", enumerateWorkshopFiles);

			Steamworks.addEventListener(SteamEvent.STEAM_RESPONSE, onSteamResponse);
			Steamworks.addOverlayWorkaround(stage, true);
			NativeApplication.nativeApplication.addEventListener(Event.EXITING, onExit);
			try {
				//Steamworks.useCrashHandler(480, "1.0", "Feb 20 2013", "21:42:20");
				if(!Steamworks.init()){
					log("STEAMWORKS API is NOT available");
					return;
				}

				log("STEAMWORKS API is available\n");
				log("User ID: " + Steamworks.getUserID());
				_appId = Steamworks.getAppID();
				log("App ID: " + _appId);
				log("Persona name: " + Steamworks.getPersonaName());
				log("isCloudEnabledForApp() == "+Steamworks.isCloudEnabledForApp());
				log("getFileCount() == "+Steamworks.getFileCount());
				log("fileExists('test.txt') == "+Steamworks.fileExists('test.txt'));
				log("getDLCCount() == " + Steamworks.getDLCCount());

				Steamworks.resetAllStats(true);
			} catch(e:Error) {
				log("*** ERROR ***");
				log(e.message);
				log(e.getStackTrace());
			}

		}
		private function log(value:String):void{
			tf.appendText(value+"\n");
			tf.scrollV = tf.maxScrollV;
		}

		public function writeFileToCloud(fileName:String, data:String):Boolean {
			var dataOut:ByteArray = new ByteArray();
			dataOut.writeUTFBytes(data);
			return Steamworks.fileWrite(fileName, dataOut);
		}

		public function readFileFromCloud(fileName:String):String {
			var dataIn:ByteArray = new ByteArray();
			var result:String;
			dataIn.position = 0;
			dataIn.length = Steamworks.getFileSize(fileName);

			if(dataIn.length>0 && Steamworks.fileRead(fileName,dataIn)){
				result = dataIn.readUTFBytes(dataIn.length);
			}
			return result;
		}

		private function checkAchievements(e:Event = null):void {
			if(!Steamworks.isReady) return;

			// current stats and achievement ids are from steam example app
			log("isAchievement('ACH_WIN_ONE_GAME') == "+Steamworks.isAchievement("ACH_WIN_ONE_GAME"));
			log("isAchievement('ACH_TRAVEL_FAR_SINGLE') == "+Steamworks.isAchievement("ACH_TRAVEL_FAR_SINGLE"));
			log("setStatFloat('FeetTraveled') == "+Steamworks.setStatFloat('FeetTraveled', 21.3));
			log("setStatInt('NumGames', 2) == "+Steamworks.setStatInt('NumGames', 2));
			Steamworks.storeStats();
			log("getStatInt('NumGames') == "+Steamworks.getStatInt('NumGames'));
			log("getStatFloat('FeetTraveled') == "+Steamworks.getStatFloat('FeetTraveled'));
		}

		private function toggleAchievement(e:Event = null):void{
			if(!Steamworks.isReady) return;

			var result:Boolean = Steamworks.isAchievement("ACH_WIN_ONE_GAME");
			log("isAchievement('ACH_WIN_ONE_GAME') == " + result);
			if(!result) {
				log("setAchievement('ACH_WIN_ONE_GAME') == "+Steamworks.setAchievement("ACH_WIN_ONE_GAME"));
			} else {
				log("clearAchievement('ACH_WIN_ONE_GAME') == "+Steamworks.clearAchievement("ACH_WIN_ONE_GAME"));
			}
		}

		private function toggleCloudEnabled(e:Event = null):void {
			if(!Steamworks.isReady) return;

			var enabled:Boolean = Steamworks.isCloudEnabledForApp();
			log("isCloudEnabledForApp() == " + enabled);
			log("setCloudEnabledForApp(" + !enabled + ") == " + Steamworks.setCloudEnabledForApp(!enabled));
			log("isCloudEnabledForApp() == " + Steamworks.isCloudEnabledForApp());
		}

		private function toggleFile(e:Event = null):void {
			if(!Steamworks.isReady) return;

			var result:Boolean = Steamworks.fileExists('test.txt');
			log("fileExists('test.txt') == " + result);
			if(result){
				log("readFileFromCloud('test.txt') == "+readFileFromCloud('test.txt') );
				log("fileDelete('test.txt') == "+Steamworks.fileDelete('test.txt'));
			} else {
				log("writeFileToCloud('test.txt','click') == "+writeFileToCloud('test.txt','click'));
			}
		}

		private function publishFile(e:Event = null):void {
			if(!Steamworks.isReady) return;

			var res:Boolean = Steamworks.publishWorkshopFile("test.txt", "", _appId,
				"Test.txt", "Test.txt", WorkshopConstants.VISIBILITY_Private,
				["TestTag"], WorkshopConstants.FILETYPE_Community);
			log("publishWorkshopFile('test.txt' ...) == " + res);
		}

		private function toggleFullscreen(e:Event = null):void {
			if(stage.displayState == StageDisplayState.NORMAL)
				stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
			else
				stage.displayState = StageDisplayState.NORMAL;
		}

		private function activateOverlay(e:Event = null):void {
			if(!Steamworks.isReady) return;

			log("isOverlayEnabled() == " + Steamworks.isOverlayEnabled());
			log("activateGameOverlay('Friends') == " + Steamworks.activateGameOverlay("Friends"));
			log("isOverlayEnabled() == " + Steamworks.isOverlayEnabled());
		}

		private function enumerateSubscribedFiles(e:Event = null):void {
			if(!Steamworks.isReady) return;

			log("enumerateUserSubscribedFiles(0) == " + Steamworks.enumerateUserSubscribedFiles(0));
		}

		private function enumerateSharedFiles(e:Event = null):void {
			if(!Steamworks.isReady) return;

			var userID:String = Steamworks.getUserID();
			var res:Boolean = Steamworks.enumerateUserSharedWorkshopFiles(userID, 0, [], []);
			log("enumerateSharedFiles(" + userID + ", 0, [], []) == " + res);
		}

		private function enumerateWorkshopFiles(e:Event = null):void {
			if(!Steamworks.isReady) return;

			var res:Boolean = Steamworks.enumeratePublishedWorkshopFiles(
				WorkshopConstants.ENUMTYPE_RankedByVote, 0, 10, 0, [], []);
			log("enumerateSharedFiles(...) == " + res);
		}

		private var id:String;
		private var handle:String;
		private function onSteamResponse(e:SteamEvent):void{
			var apiCall:Boolean;
			var i:int;
			switch(e.req_type){
				case SteamConstants.RESPONSE_OnUserStatsStored:
					log("RESPONSE_OnUserStatsStored: "+e.response);
					break;
				case SteamConstants.RESPONSE_OnUserStatsReceived:
					log("RESPONSE_OnUserStatsReceived: "+e.response);
					break;
				case SteamConstants.RESPONSE_OnAchievementStored:
					log("RESPONSE_OnAchievementStored: "+e.response);
					break;
				case SteamConstants.RESPONSE_OnPublishWorkshopFile:
					log("RESPONSE_OnPublishWorkshopFile: " + e.response);
					var file:String = Steamworks.publishWorkshopFileResult();
					log("File published as " + file);
					log("subscribePublishedFile(...) == " + Steamworks.subscribePublishedFile(file));
					break;
				case SteamConstants.RESPONSE_OnEnumerateUserSubscribedFiles:
					log("RESPONSE_OnEnumerateUserSubscribedFiles: " + e.response);
					var subRes:SubscribedFilesResult = Steamworks.enumerateUserSubscribedFilesResult();
					log("User subscribed files: " + subRes.resultsReturned + "/" + subRes.totalResults);
					for(i = 0; i < subRes.resultsReturned; i++) {
						id = subRes.publishedFileId[i];
						apiCall = Steamworks.getPublishedFileDetails(subRes.publishedFileId[i]);
						log(i + ": " + subRes.publishedFileId[i] + " (" + subRes.timeSubscribed[i] + ") - " + apiCall);
					}
					break;
				case SteamConstants.RESPONSE_OnEnumerateUserSharedWorkshopFiles:
					log("RESPONSE_OnEnumerateUserSharedWorkshopFiles: " + e.response);
					var userRes:UserFilesResult = Steamworks.enumerateUserSharedWorkshopFilesResult();
					log("User shared files: " + userRes.resultsReturned + "/" + userRes.totalResults);
					for(i = 0; i < userRes.resultsReturned; i++) {
						log(i + ": " + userRes.publishedFileId[i]);
					}
					break;
				case SteamConstants.RESPONSE_OnEnumeratePublishedWorkshopFiles:
					log("RESPONSE_OnEnumeratePublishedWorkshopFiles: " + e.response);
					var fileRes:WorkshopFilesResult = Steamworks.enumeratePublishedWorkshopFilesResult();
					log("Workshop files: " + fileRes.resultsReturned + "/" + fileRes.totalResults);
					for(i = 0; i < fileRes.resultsReturned; i++) {
						log(i + ": " + fileRes.publishedFileId[i] + " - " + fileRes.score[i]);
					}
					break;
				case SteamConstants.RESPONSE_OnGetPublishedFileDetails:
					log("RESPONSE_OnGetPublishedFileDetails: " + e.response);
					var res:FileDetailsResult = Steamworks.getPublishedFileDetailsResult(id);
					log("Result for " + id + ": " + res);
					if(res) {
						log("File: " + res.fileName + ", handle: " + res.fileHandle);
						handle = res.fileHandle;
						apiCall = Steamworks.UGCDownload(res.fileHandle, 0);
						log("UGCDownload(...) == " + apiCall);
					}
					break;
				case SteamConstants.RESPONSE_OnUGCDownload:
					log("RESPONSE_OnUGCDownload: " + e.response);
					var ugcResult:DownloadUGCResult = Steamworks.getUGCDownloadResult(handle);
					log("Result for " + handle + ": " + ugcResult);
					if(ugcResult) {
						log("File: " + ugcResult.fileName + ", handle: " + ugcResult.fileHandle + ", size: " + ugcResult.size);
						var ba:ByteArray = new ByteArray();
						ba.length = ugcResult.size;
						apiCall = Steamworks.UGCRead(ugcResult.fileHandle, ugcResult.size, 0, ba);
						log("UGCRead(...) == " + apiCall);
						if(apiCall) {
							log("Result length: " + ba.position + "//" + ba.length);
							log("Result: " + ba.readUTFBytes(ugcResult.size));
						}
					}
					break;
				default:
					log("STEAMresponse type:"+e.req_type+" response:"+e.response);
			}
		}

		private function onExit(e:Event):void{
			log("Exiting application, cleaning up");
			Steamworks.dispose();
		}

		private function addButton(label:String, callback:Function):void {
			var button:Sprite = new Sprite();
			button.graphics.beginFill(0xaaaaaa);
			button.graphics.drawRoundRect(0, 0, 150, 30, 5, 5);
			button.graphics.endFill();
			button.buttonMode = true;
			button.useHandCursor = true;
			button.addEventListener(MouseEvent.CLICK, callback);
			button.x = 5;
			button.y = _buttonPos;
			_buttonPos += button.height + 5;

			button.addEventListener(MouseEvent.MOUSE_OVER, function(e:MouseEvent):void {
				button.graphics.clear();
				button.graphics.beginFill(0xccccccc);
				button.graphics.drawRoundRect(0, 0, 150, 30, 5, 5);
				button.graphics.endFill();
			});

			button.addEventListener(MouseEvent.MOUSE_OUT, function(e:MouseEvent):void {
				button.graphics.clear();
				button.graphics.beginFill(0xaaaaaa);
				button.graphics.drawRoundRect(0, 0, 150, 30, 5, 5);
				button.graphics.endFill();
			});

			var text:TextField = new TextField();
			text.text = label;
			text.width = 140;
			text.height = 25;
			text.x = 5;
			text.y = 5;
			text.mouseEnabled = false;

			button.addChild(text);
			addChild(button);
		}
	}
}

Add tests for Enumerate{UserShared,Workshop}Files