Newer
Older
ubChattin / src / Master.as
/****************************************************************
 * Master.as, by Christopher Olsen <cwolsen@domainatlantic.com>
 * Copyright 2007,2008 Christopher Olsen <cwolsen@ubixos.com>
 *                     Mark Iuzzolino    <miuzzolino@ubixos.com>
 * 
 * This is the Master class used by the TUve player
 * 
 * $Id$
 ***************************************************************/
 
package {
  import flash.events.NetStatusEvent;
  import flash.events.SecurityErrorEvent;
  import flash.events.TimerEvent;
  import flash.filters.DropShadowFilter;
  import flash.media.*;
  import flash.net.NetConnection;
  import flash.net.NetStream;
  import flash.net.ObjectEncoding;
  import flash.net.Responder;
  import flash.net.SharedObject;
  import flash.system.System;
  import flash.utils.Timer;
  
  import mx.collections.ArrayCollection;
  import mx.controls.Alert;
  import mx.controls.Image;
  import mx.controls.TextArea;
  import mx.core.Application;
  import mx.core.UIComponent;
  import mx.events.FlexEvent;
  import mx.formatters.DateFormatter;
  import mx.managers.BrowserManager;
  import mx.managers.IBrowserManager;
  import mx.managers.PopUpManager;

  public class Master {  	
    /* Variables */
  	public var gateway:NetConnection;    // AMF Gateway
 	public var masterObject:Object;      // Parent reference
 	[Bindable]
    public var userName:String;          // User Infomation
    public var tvNetwork:tuveNetwork;    // Network Class
    public var version:String = "2.7";   // Current Client Version
        
    /* Streams */
    public var tvSyncNC:NetConnection;        // NetConnection For Sync Video
    public var tvSyncNS:NetStream;            // NetStream For Sync Video
    public var tvSyncST:SoundTransform;       // SoundTransform For Sync Video
    
    public var tvStartTime:Number;
    public var tvGotMeta:Boolean = false;
    
    public var curSong:String = "NO SONG SET";
    
    public var myTimer:Timer = new Timer(1000,10);
    public var myCount:Number = 0;
    
    private var ncTimer:Timer = new Timer(5000,1);
    private var ncCount:Number = 0;
    
    [Bindable]
	public var userList:XMLList;
	
	[Bindable]
	public var chanList:ArrayCollection;
	public var chanSpec:String;
    public var currentChannel:String;
    [Bindable]
    public var channels:XMLList;
    
    [Bindable]
	private var metaData:Object = {duration:0};
	
	private var imWins:Array;
	
	public var tvSO:SharedObject;
	
	public var vid:Number;
	public var tvSyncFailed:Boolean = false;
	public var tvTotal:Number;
	
	/* Pop Up Windows */
	private var tuveLW:listWindow;
	public var tuveIW:infoWindow;
	public var fwClosable:Boolean = false;
    public var login:Login;
    public var tuveTW:tipsWindow;
  	
  	/* Initialization Routine */
    public function init(mO:Object):Boolean {
    	
      /* Set Master Object */
      masterObject = mO;
    	
      /* Initialize the AMF gateway */	
      gateway = new NetConnection();
      gateway.connect("http://www.ubixonline.com/amfphp/gateway.php");
      
      tvNetwork = new tuveNetwork();
      tvNetwork.tvMaster = this;
      
          
      /* Set up sync stream */
      tvSyncNC = new NetConnection;
      tvSyncNC.addEventListener(NetStatusEvent.NET_STATUS, tvNetStatus);
      tvSyncNC.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
      tvSyncNC.client = this;
      tvSyncNC.objectEncoding = ObjectEncoding.AMF3;
      tvSyncNC.connect("rtmp://monkey.ubixos.com/oflaDemo");
      
      tvSO = SharedObject.getLocal("ubChattinINFO");
      
      if (tvSO.data.myID == null)
        tvSO.data.myID = new Date().getTime();
        
      imWins = new Array();
      
      myTimer.addEventListener(TimerEvent.TIMER,doCount);
      
      ncTimer.addEventListener(TimerEvent.TIMER_COMPLETE,doReconnect);
    
      return(true);
      } /* End init */
      
    private function  doReconnect(e:TimerEvent):void {
      tvSyncNC.connect("rtmp://monkey.ubixos.com/oflaDemo");
      ncTimer.reset();
      }
      
    public function tuveGetChans():void {
      gateway.call("tuve.getChans",new Responder(getChansRes,onFault),null);
      }
    private function getChansRes(result:Array):void {
      if (result) {
      	chanList = new ArrayCollection(result);
        }
       doLogin();
      }
      
    private function doCount(event:TimerEvent):void {
      myCount--;
      
      var min:Number = Math.floor((myCount/60));
      var sec:Number = (myCount%60);
      var secStr:String;
      
      if (sec < 10)
        secStr = "0" + sec.toString();
      else
        secStr = sec.toString();

      //masterObject.tvTimer.text = "(" + min.toString() + ":" + secStr + ")";
      }

    public function onMetaData(info:Object):void {
   	  if (tvGotMeta == false) {
   	    tvSyncNS.receiveVideo(false);
        if (tvStartTime > 0)
          tvSyncNS.seek(tvStartTime);
   	      
   	    tvGotMeta = true;
   	    }
      }

	public function onBWDone():void {
	  //Alert.show("Called BWDONE");
	  }
	  
	public function onPlayStatus(info:Object):void {
	}
	  
	public function tvNetStatus(e:NetStatusEvent):void {
		
	  if (e.info.code == "NetConnection.Connect.Success") {
	    if (e.currentTarget == tvSyncNC) {
	      if (tvSyncST != null)
	        tvSyncST = null;
	        
	      if (tvSyncNS != null)
	        tvSyncNS = null;
	        
          tvSyncNS = new NetStream(tvSyncNC);
          tvSyncNS.receiveVideo(false);
          tvSyncNS.client = this;
          //tvSyncVid.attachNetStream(tvSyncNS);
    	  tvSyncNS.close();       
          tvSyncST = tvSyncNS.soundTransform;
          tvSyncNS.addEventListener(NetStatusEvent.NET_STATUS, tvNetStatus,false,0,true);
          masterObject.updateVolume();
          if (tvSyncFailed == true) {
          	masterObject.chatWindow.htmlText += "<TEXTFORMAT LEADING=\"2\"><P ALIGN=\"LEFT\"><FONT FACE=\"Verdana\" SIZE=\"10\" COLOR=\"#990000\" LETTERSPACING=\"0\" KERNING=\"0\">[" + fmtdDate() + "] RTMP: Successfully Reconnected To Streaming Service.</FONT></P></TEXTFORMAT>";
          	if (myCount > 0)
          	  tvSyncNS.play(curSong,tvTotal - myCount);
          	tvSyncFailed = false;
            }
          }
        else
          Alert.show("Unknown stream");
	    }
	  else if (e.info.code == "NetConnection.Connect.Closed") {
	  	if (e.currentTarget == tvSyncNC) {
	  	  tvSyncFailed = true;
	  	  tvSyncNS = null;
	  	  masterObject.chatWindow.htmlText += "<TEXTFORMAT LEADING=\"2\"><P ALIGN=\"LEFT\"><FONT FACE=\"Verdana\" SIZE=\"10\" COLOR=\"#990000\" LETTERSPACING=\"0\" KERNING=\"0\">[" + fmtdDate() + "] RTMP: Lost Connection To Streaming Service. Attempting To Reconnect.</FONT></P></TEXTFORMAT>";
	  	  ncCount = 0;
	  	  ncTimer.reset();
	  	  ncTimer.start();
	  	  }
	    }
	  else if (e.info.code == "NetConnection.Connect.Failed") {
	  	if (ncCount < 4) {
	  	  ncCount++;
	  	  masterObject.chatWindow.htmlText += "<TEXTFORMAT LEADING=\"2\"><P ALIGN=\"LEFT\"><FONT FACE=\"Verdana\" SIZE=\"10\" COLOR=\"#990000\" LETTERSPACING=\"0\" KERNING=\"0\">[" + fmtdDate() + "] RTMP: Reconnect Failed. Attempting To Reconnect.</FONT></P></TEXTFORMAT>";
	  	  ncTimer.reset();
	  	  ncTimer.start();
	      }
	    else {
	  	  if (e.currentTarget == tvSyncNC)
  	  	    masterObject.chatWindow.htmlText += "<TEXTFORMAT LEADING=\"2\"><P ALIGN=\"LEFT\"><FONT FACE=\"Verdana\" SIZE=\"10\" COLOR=\"#990000\" LETTERSPACING=\"0\" KERNING=\"0\">[" + fmtdDate() + "] RTMP: Unable to connect to the streaming service. You will not be able to watch videos.</FONT></P></TEXTFORMAT>";
  	      }
	    }
	  }
      
    private function securityErrorHandler(event:SecurityErrorEvent):void {
	  Alert.show("securityError: " + event.text);
      }    
      
    /* AMF Fault Handlers */
    public function onFault(fault:String):void {
      Alert.show("Error: " + fault.toString());
      }
      
    public function changeChannel(newChan:String):void {
      tvNetwork.sendData("PART " + currentChannel + "\n");
      currentChannel = newChan;
      userList = null;
  	  userList = new XMLList();
  	  tvNetwork.sendData("JOIN " + currentChannel + "\n");
      }
      
    public function validateNick(str:String):Boolean {
            var pattern:RegExp = /^[a-zA-Z0-9]*$/;
            var result:Object = pattern.exec(str);
            if(result == null) {
                return false;
            }
            return true;
        }
      
    public function parseCommand(command:String):void {
      var dataArray:Array = command.split(" ");
      var tmpString:String;
      var i:Number;
      
      switch (dataArray[0]) {
      	case "/topic":
      	  tmpString = dataArray[1];
      	  for (i=2;dataArray[i] != null;i++)
            tmpString += " " + dataArray[i];
      	  
      	  tvNetwork.sendData("TOPIC " + currentChannel + ":" + tmpString);
      	  break;
      	case "/nick":
      	  if (dataArray[1].length < 32) {
      	  	if (validateNick(dataArray[1]) == true)
        	  tvNetwork.sendData("NICK " + dataArray[1]);
      	    }
      	  break;
      	case "/kick":
      	  tmpString = dataArray[2];
      	  for (i=3;dataArray[i] != null;i++)
      	    tmpString += " " + dataArray[i];
      	  tvNetwork.sendData("KICK " + currentChannel + ":" + dataArray[1] + ":" + tmpString + "\n");
      	  break;
      	case "/me":
      	case "/em":
      	  tmpString = dataArray[1];
      	  for (i=2;dataArray[i] != null;i++)
      	    tmpString += " " + dataArray[i];
      	  tvNetwork.sendData("EMOTE " + currentChannel + ":" + tmpString + "\n");
      	  masterObject.chatWindow.htmlText += "[" + fmtdDate() + "] " + userName + " " + tmpString + "\n";
      	  break;
      	case "/join":
      	  tmpString = dataArray[1];
      	  if (tmpString.indexOf("#") == 0) {
            changeChannel(tmpString);
  	        }
  	      else {
  	      	masterObject.chatWindow.htmlText += "Invalid Channel: " + tmpString + "\n";
  	        }
      	  break;
      	case "/status":
      	  tvNetwork.sendData("STATUS\n");
      	  break;
      	case "/whois":
      	  if (dataArray[1] != null)
      	    tvNetwork.sendData("WHOIS " + dataArray[1] + "\n");
      	  break; 
      	case "/ban":
      	  if (dataArray[1] != null)
      	    if (dataArray[2] != null)
      	      tvNetwork.sendData("BAN " + currentChannel + ":" + dataArray[1] + ":" + dataArray[2] + "\n");
      	    else
      	      tvNetwork.sendData("BAN " + currentChannel + ":" + dataArray[1] + ":300\n");
      	  break;
      	case "/unban":
      	  if (dataArray[1] != null)
      	    tvNetwork.sendData("UNBAN " + currentChannel + ":" + dataArray[1] + "\n");
      	  break;
      	case "/list":
      	  tvNetwork.sendData("LIST\n");
      	  break;
      	case "/msg":
      	  tmpString = dataArray[2];
      	  for (i=3;dataArray[i] != null;i++)
      	    tmpString += " " + dataArray[i];
      	   tvNetwork.sendData("MSG " + dataArray[1] + ":" + tmpString + "\n");  
      	    var tmpIM:imWindow;
            tmpIM = findIM(dataArray[1]);
            tmpIM.msgText.htmlText += "[" + fmtdDate() + "] " + userName + ": " + tmpString;
      	  break;
      	case "/clear":
      	  masterObject.chatWindow.text = "";
      	  break;
      	case "/tips":
      	  tuveShowTW();
      	  break;
      	default:
      	  //Alert.show("Command: " + dataArray[0]);
      	  break;
        }
      }     
  
     /* This function opens up a channel list window */
     public function tuveShowLW():void {
      if (tuveLW == null) {
   	  	tuveLW = new listWindow();
   	  	tuveLW.tvMaster = this;   	  	
  	  	tuveLW.x = ((masterObject.width - tuveLW.width) / 2);
  	  	tuveLW.y = ((masterObject.height - tuveLW.height) /2 );
  	  	tuveLW.addEventListener("closeWindow",tuveCloseLW,false,0,true);   	  	
   	  	masterObject.addChild(tuveLW);
   	    }
      } /* End tuveShowLW() */
      
    /* This function closes the channel list window */
    public function tuveCloseLW(event:FlexEvent):void {
      if (tuveLW != null) {
      	masterObject.removeChild(tuveLW);
      	tuveLW = null;
        }
      } /* End tuveCloseLW */
      
     public function tuveShowIW(vid:Number):void {
      if (tuveIW == null) {
   	  	tuveIW = new infoWindow();
   	  	tuveIW.tvSizable = false;
   	  	tuveIW.tvMaster = this;
   	  	
   	  	
  	  	tuveIW.x = ((masterObject.width - tuveIW.width) / 2);
  	  	tuveIW.y = ((masterObject.height - tuveIW.height) /2 );
  	  	tuveIW.addEventListener("closeWindow",tuveCloseIW,false,0,true);   	  	
   	  	masterObject.addChild(tuveIW);
   	  	tuveIW.getInfo(vid);
   	    }
   	  else {
   	  	tuveIW.getInfo(vid);
   	    }
      } /* End invShow */
    public function tuveCloseIW(event:FlexEvent):void {
      if (tuveIW != null) {
      	masterObject.removeChild(tuveIW);
      	tuveIW = null;
        }
      } 
            
     public function tuveShowTW():void {
      if (tuveTW == null) {
   	  	tuveTW = new tipsWindow();
   	  	tuveTW.tvSizable = false;
   	  	tuveTW.tvMaster = this;
   	  	
   	  	
  	  	tuveTW.x = ((masterObject.width - tuveTW.width) / 2);
  	  	tuveTW.y = ((masterObject.height - tuveTW.height) /2 );
  	  	tuveTW.addEventListener("closeWindow",tuveCloseTW,false,0,true);   	  	
   	  	masterObject.addChild(tuveTW);
   	    }
      } /* End invShow */
    public function tuveCloseTW(event:FlexEvent):void {
      if (tuveTW != null) {
      	masterObject.removeChild(tuveTW);
      	tuveTW = null;
        }
      } 
      
    public function setClip(tW:TextArea):void {
      System.setClipboard(tW.text.substring(tW.selectionBeginIndex,tW.selectionEndIndex));    
      }
      
    /*
     *
     * Private Message Functions
     *
     */
    public function sendIM(toNick:String,msg:String):void {
      var tmpIM:imWindow;
      tmpIM = findIM(toNick);
      tmpIM.msgText.htmlText += "[" + fmtdDate() + "] " + toNick + ": " + msg;
      }
      
    public function findIM(toNick:String):imWindow {
      var i:Number;
      var tmpIM:imWindow;
      
      /* Check to see if we have an open IM already */
      for (i=0;i<imWins.length;i++) {
      	tmpIM = imWins[i];
      	if (tmpIM.toNick.toLocaleLowerCase() == (toNick.toLocaleLowerCase()))
      	  return(tmpIM);
        }
      
      /* Create a new IM if there is no existing one */  
      tmpIM = new imWindow();
      tmpIM.toNick = toNick;
      tmpIM.tvMaster = this;
      tmpIM.addEventListener("closeWindow",imClose,false,0,true);
      tmpIM.title = "IM: " + toNick;
      imWins.push(tmpIM);
      tmpIM.x = (masterObject.width/2) - (tmpIM.width/2);
      tmpIM.y = (masterObject.height/2) - (tmpIM.height/2);
      masterObject.addChild(tmpIM);
      return(tmpIM);
      }
      
    /* This function closes an IM window */
  	private function imClose(event:FlexEvent):void {
  	  var toNick:String = (event.currentTarget as imWindow).toNick;
  	  var i:Number;
  	  var tmpIM:imWindow;
  	  var tmpArray:Array = new Array();
  	  
  	  for (i=0;i < imWins.length;i++) {
  	  	tmpIM = imWins[i];
  	  	if (tmpIM.toNick == toNick) {
  	  	  masterObject.removeChild(tmpIM);
          tmpIM = null;
  	  	  }
  	  	else 
  	  	  tmpArray.push(imWins[i]);
  	    }

  	  imWins = null;
  	  imWins = tmpArray;
  	  } /* End imClose() */          
  	/* End Private Message Functions */
  	
    /*
     *
     * Authentication Functions
     *
     */
    public function doLogin():void {
      if (login == null) {
        login = PopUpManager.createPopUp(this.masterObject as Application,Login,true) as Login;
        login.funcs = this;
        login.tvMaster = this;
        if (tvSO.data.userName != null)
          login.username.text = tvSO.data.userName;  
        PopUpManager.centerPopUp(login);
        }
      } /* End doLogin() */
    public function authUser(userN:String,channel:String):void {
      userName = userN;
      tvSO.data.userName = userN;
      currentChannel = channel;
      if (tvSO.data.quickTips == null)
        tuveShowTW();
               
      tvNetwork.init();
      } /* End authUser(userName,channel); */
    public function authFail(error:String):void {
      doLogin();
      login.logErr.text = "Error: " + error;
      login.loginButton.enabled = true;
      } /* End authFail(error) */

    public function authSuccess():void {      
      PopUpManager.removePopUp(login);
      login = null;
      //masterObject.updateVolume(); 
      } /* End authSuccess() */      
    /* End Authentication Functions */ 

    /* fmtDate() - Returns Current Time Formatted */
    public function fmtdDate():String {
      var rn:Date = new Date();
      var df:DateFormatter = new DateFormatter();
      
      df.formatString = "JJ:NN:SS";
      return(df.format(rn));
      }    
  
    } /* End Master */
    
  } /* End package */