LocalConnectionを共用させてみた

by codalx
LocalConnectionの接続名を共用させて、常にどれか一つの接続を保持させてみるテスト。
用途として、サンプル音声を再生するSWFが複数あったとき、再生状態の重複を防ぐのに使えるかもしれません。
♥0 | Line 159 | Modified 2010-12-25 14:38:47 | MIT License
play

ActionScript3 source code

/**
 * Copyright codalx ( http://wonderfl.net/user/codalx )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/jew6
 */

package 
{
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import flash.text.TextFormatAlign;
    
    [SWF(width="465", height="465", frameRate="30", backgroundColor="0xFFFFFF")]
    public class Main extends Sprite
    {
        private const SIZE : int = 465;
        
        public function Main()
        {
            if (stage) _init();
            else addEventListener(Event.ADDED_TO_STAGE, _init);
        }
        
        private var _tf : TextField;
        private var _lc : Concessor;
        private var _s : Shape;
        
        private function _init(e:Event = null):void
        {
            var _format : TextFormat = new TextFormat("_ゴシック", 13);
            
            _format.align = TextFormatAlign.CENTER;
            
            var _intro : String = 
            "\n"+
            "LocalConnectionの接続を譲りあうテスト\n"+
            "複数ウィンドウを表示させると、それぞれ同期して状態がかわったりします"
            
            with((addChild(_s = new Shape) as Shape).graphics)
            {
                beginFill(0x88AA, 0.5);
                drawRect(0,0,SIZE,SIZE);
                endFill();
            }
            
            with(addChild(new TextField))
            {
                editable = false;
                selectable = false;
                defaultTextFormat = _format;
                width = SIZE;
                text = _intro;
            }
            
            _format.bold = true;
            _format.size = 25;
            
            with (addChild(_tf = new TextField))
            {
                editable = false;
                selectable = false;
                defaultTextFormat = _format;
                width = SIZE;
                height = SIZE / 2;
                y = SIZE / 2;
            }
            
            with (_lc = new Concessor("testConnection"))
            {
                onActivate = _onActivate;
                onDeactivate = _onDeactivate;
                connect();
            }
            
            //ステージクリックで接続/切断操作させてます
            stage.addEventListener(MouseEvent.CLICK, _tryToConnect);
        }
        
        private function _tryToConnect(e:MouseEvent):void
        {
            if(_lc.connected) _lc.close();
            else _lc.connect();
        }
        
        private function _onActivate():void
        {
            _tf.text = "(`・ω・´)\n今から本気出す";
            _s.visible = true;
        }
        
        private function _onDeactivate():void
        {
            _tf.text = "(´・ω・`)\nやっぱやめた";
            _s.visible = false;
        }
    }
}

import flash.events.AsyncErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.events.StatusEvent;
import flash.net.LocalConnection;

internal class Concessor
{
    private const MONITORING_PREFIX : String = "(Monitoring)";
    private const CALLBACK_DEACTIVATE : String = "ON_DEACTIVATE";
    private const CALLBACK_SWITCHING : String = "ON_SWITCHED";
    private const _IDENTIFIER : String = "_ID_" + (Math.random() * 0xFFFFFF | 0);
    private var _connector : LocalConnection;
    private var _client : Object;
    private var _connectionName : String;
    private var _monitoring : Boolean = false;
    
    public function get connected():Boolean { return _connected; }
    private var _connected : Boolean = false;
    
    public function get onActivate():Function { return _onActivatedHandler; }
    public function set onActivate(func:Function):void { _onActivatedHandler = func; }
    private var _onActivatedHandler : Function = null;
    
    public function get onDeactivate():Function { return _onDeactivatedHandler; }
    public function set onDeactivate(func:Function):void{ _onDeactivatedHandler = func; }
    private var _onDeactivatedHandler : Function = null;
    
    public function Concessor(connectionName : String) 
    {
        _connectionName = connectionName;
        _init();
    }
    
    private function _init():void
    {
        _client = { };
        _client[CALLBACK_DEACTIVATE] = _onDeactivated;
        _client[CALLBACK_SWITCHING] = _onSwitched;
        
        with(_connector = new LocalConnection)
        {
            client = _client;
            addEventListener(AsyncErrorEvent.ASYNC_ERROR, trace);
            addEventListener(SecurityErrorEvent.SECURITY_ERROR, trace);
            //STATUSイベント入れないと例外がスローされちゃうみたい
            addEventListener(StatusEvent.STATUS, trace);
        }
    }
    
    public function connect():void
    {
        if (connected) return;
        
        var _established : Boolean = false;
        var _monitorable : Boolean = true;
        
        if (_monitoring){
            _connector.close();
            _monitoring = false;
        }
        
        try { _connector.connect(_connectionName); }
        catch (e:ArgumentError) { _established = true; }
        
        if(!_established){
            _connected = true;
            if (onActivate != null) onActivate();
        }else{
            _connected = false;
            
            try { _connector.connect(MONITORING_PREFIX + _connectionName);}
            catch(e:ArgumentError){_monitorable = false;}
            
            _connector.send(_connectionName, CALLBACK_DEACTIVATE, _IDENTIFIER);
        }
    }
    
    public function close():void
    {
        _onDeactivated(String(Math.random() * 0xFFFFF));
    }
    
    private function _onDeactivated(id : String):void
    {
        if(id != _IDENTIFIER){
            _connector.close();
            _connected = false;
            
            if (onDeactivate != null) onDeactivate();
            
            _connector.send(MONITORING_PREFIX + _connectionName, CALLBACK_SWITCHING);
        }
    }
    
    private function _onSwitched():void
    {
        _connector.close();
        connect();
    }
}