/****************************************************************
* 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 */