flash on 2012-5-27

by kske
♥0 | Line 182 | Modified 2012-05-27 22:21:50 | MIT License
play

ActionScript3 source code

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

package {
    import flash.display.DisplayObjectContainer;
    import flash.events.EventDispatcher;
    import flash.display.Sprite;
    
    public class RtmfpTest extends Sprite {
        public function RtmfpTest() {
            // write as3 code here..
            
        }
    }
    
    
    

}
import flash.net.NetConnection;
import flash.net.NetGroup;
import flash.net.GroupSpecifier;
import flash.text.TextField;
import flash.events.EventDispatcher;
import flash.events.Event;
import flash.events.NetStatusEvent;
import flash.display.DisplayObjectContainer;
import flash.events.IEventDispatcher;


    class UIController implements IEventDispatcher{
        private var user:TextField;
        private var message:TextField;
        private var log:TextField;
        
        private var parent:DisplayObjectContainer;
        
        private var dispatcher:EventDispatcher;
        
        public function UIController(stage:DisplayObjectContainer){
            if(!stage){
                throw(new Error("Parent display-object-container is not valid."));
            }
            
            parent = stage;
            
            if(!createViews()){
                throw(new Error("can't create UI"));
            }
            
            if(!putViews()){
                throw(new Error("sonnna bakana"));
            }
            
            dispatcher = new EventDispatcher(this);

        }
        
        
        private function createViews():Boolean{
            user = new TextField();
            message = new TextField();
            log = new TextField();
            
            log.multiline = true;
            
            return true;
        }
        
        private function putViews():Boolean{
            parent.addChild(user);
            parent.addChild(message);
            parent.addChild(log);
            
            return true;
        }
        
        public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void{
            dispatcher.removeEventListener(type, listener, useCapture);
        
        }
        
        public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void{
            dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
        }
        
        
        public function hasEventListener(type:String):Boolean{
            return dispatcher.hasEventListener(type);
        }

          
        public function willTrigger(type:String):Boolean{
            return dispatcher.willTrigger(type);
        }
        
        public function dispatchEvent(e:Event):Boolean{
            return dispatcher.dispatchEvent(e);
        }

    }
    
    class RtmfpController implements IEventDispatcher{
        private var dispatcher:EventDispatcher;
        private const URI:String = "rtmfp:";
        
        private var conn:NetConnection; // Connection / handler
        private var grp:NetGroup; // なんかまとめてくれるよ
        
        private var isConnected:Boolean;
        
        private var model:ChatModel; // model? への参照
        
        public function get IsConnected():Boolean{
            return isConnected;
        }

        
        public function RtmfpController(_model:ChatModel){
            dispatcher = new EventDispatcher(this);
            if(!model) throw new ArgumentError("Null Po(*‘ω‘ *)");
            model = _model;
        }
        
        public function connect():Boolean{
            conn = new NetConnection();
            conn.addEventListener(NetStatusEvent.NET_STATUS, updateStatus);
            try{
                conn.connect(URI);
            }catch(e:Error){
                dispatchEvent(new Event("CONNECTION ERROR"));
                model.addLog("can't connect to " + URI);
                
                conn.removeEventListener(NetStatusEvent.NET_STATUS, updateStatus);
                conn = null;
                return false;
            }
            return true;
        }
        
        private function initGroup():void{
            var gs:GroupSpecifier = new GroupSpecifier("kske.info/test1"); // nameはアプリケーションで統一されてたら任意でいいのかな?
            
            gs.ipMulticastMemberUpdatesEnabled = true;
            //グループメンバーシップに関する情報を IP マルチキャストソケットで交換できるかどうかを指定します。
            //IP マルチキャストサーバーでグループメンバーシップの更新を送信して、P2P メッシュまたは修復パーティションをブートストラップすることができます。
            //*日本語解読*
            //たぶんブートストラップは自動実行的な意味で使われてる。メンバー情報を交換してネットワークを最適化してくれるオプション、かな?
            gs.multicastEnabled = true;
            //multicast(特定の複数対象への送信)ではなくて、
            //NetGroup でストリーミングを有効にするかどうかを指定します、だそうだ。Stream使わないならいらないの?
            gs.addIPMulticastAddress("224.0.0.123:141412");
            //指定のIP multicast groupに参加して指定されたudp portを(listenして?)待機。
            //送信先だけじゃなくて、受信のために待機するのもぽいんと。
            //224.0.0.0/24はTTL 1でローカル専用。ルーティングされない
            gs.serverChannelEnabled = true;
            //NetGroup のメンバーがサーバーへのチャンネルを開くことができるかどうかを指定します。デフォルトでは、このプロパティは FALSE です。
            //サーバーがグループメンバーにサポート機能を提供するには、サーバーへのチャンネルを開く必要があります。サーバーの設定に応じて、サポート機能がこのチャンネル経由で提供されたり、提供されなかったりします。
            //よくわかんない(´・ω・`)サーバーからグループメンバーにサポート機能を提供したいときにtrueにすればいいのかな。Local P2Pならfalseでよい気も
            //Question: サーバーのサポート機能ってなに?
            // Cirrus 使わない時は serverChannelEnabled = true いらない #RTMFP_LAB from @superbacker 氏 らしい!
            gs.postingEnabled = true;
            // NetGroup でアップロードを有効にするかどうかを指定します。 関連 > post()メソッド
            // post()は同grp内のメンバにメッセージを送信する。ただしメッセージは同一の物は送信されないことがあるのでsequenceなんかをつけて回避
            // 順序・確実な送信は保証されない
            
            gs.routingEnabled = true;
            // NetGroup で転送メソッドを有効にするかどうかを指定。関連 >sendToNearest()メソッド
            // sendToNearest()は指定されたグループアドレスに最も近いネイバー(ローカルノード)にメッセージを送信。
            // リング全体のネイバーを考慮してメッセージが宛先に正しく送信された場合、NetGroupSendResult.SENT を返すので成否が分かる。
            // 注意:呼び出す前に、NetGroup.Neighbor.Connect イベントをテスト
            
            model.addLog("Group Spec:" + gs.groupspecWithAuthorizations());
            // よくわかんない。Withoutもあるようだ
            // NetStream および NetGroup コンストラクターに渡すことができる権限を含めた(Withoutの方は当然含めない)不透明な groupspec ストリングを返します。
            // コンストラクタに必須の定義文字列とかそんな感じ?
            
            grp = new NetGroup(conn, gs.groupspecWithAuthorizations());
            // NetGroupのインスタンス生成。
            // 通信を相互に行う集合の定義的な何かだと思う。
            // 使うConnectionとGroupSpecifierのなんちゃら文字列をぶっこむ。
            
            grp.addEventListener(NetStatusEvent.NET_STATUS, updateGroupStatus);
            // NetStatusEvent.NET_STATUSのリスナー
            // NetGroupの場合、NetStatusEvent.info.codeが"NetGroup."で始まると思う。
            // なんでオブジェクト分けてないかは知らない。メソッドをまとめることも出来ると思うけど、どっちがいいだろう。

        }
        
        // GroupのStatus Handler
        public function updateGroupStatus(e:NetStatusEvent):void{
            
        }
        
        // NetConnectionのステータスハンドラ
        public function updateStatus(e:NetStatusEvent):void{
            model.addLog(e.info.code);
            
            switch(e.info.code){
                case "NetConnection.Connect.Success":
                initGroup();
                //コネクションが作れたらより詳細なNetGroupを作成するよ
                break;
                
                case "NetConnection.Connect.Failed":
                model.addLog("Connection Failed!");
            }
        }




        
        public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void{
            dispatcher.removeEventListener(type, listener, useCapture);
        
        }
        
        public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void{
            dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
        }
        
        
        public function hasEventListener(type:String):Boolean{
            return dispatcher.hasEventListener(type);
        }

          
        public function willTrigger(type:String):Boolean{
            return dispatcher.willTrigger(type);
        }
        
        public function dispatchEvent(e:Event):Boolean{
            return dispatcher.dispatchEvent(e);
        }
    }
    
    class ChatModel implements IEventDispatcher{
        private var dispatcher:EventDispatcher;
        private var log:String;
        private var user:String;
        private var message:String;
        
        public function get Log():String{
            return log;
        }
        
        public function addLog(s:String):void{
            log += s;

            if(!s.match("\n")){
                log += "\n"
            }

            this.dispatchEvent(new LogEvent("_LOG_CHANGED", log));
        }


        
        public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void{
            dispatcher.removeEventListener(type, listener, useCapture);
        
        }
        
        public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void{
            dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
        }
        
        
        public function hasEventListener(type:String):Boolean{
            return dispatcher.hasEventListener(type);
        }

          
        public function willTrigger(type:String):Boolean{
            return dispatcher.willTrigger(type);
        }
        
        public function dispatchEvent(e:Event):Boolean{
            return dispatcher.dispatchEvent(e);
        }
    }
    
    class LogEvent extends Event{
        private var log:String;
        
        public function LogEvent(type:String, newLog:String, bubbles:Boolean = true, cancelable:Boolean = false){
            super(type, bubbles, cancelable);
            log = newLog;
        }
        
        public function get Log():String{
            return log;
        }
        
        public override function clone():Event{
            return new LogEvent(type, log, bubbles, cancelable);
            
        }
        
        public override function toString():String{
            return formatToString("LogEvent", "Log", "type", "bubbles", "cancelable", "eventPhase")
        }
    }