idPool = ["guest_1", "guest_2", "guest_3", "guest_4"];//数组,当堆栈用.全局的
application.onAppStart = function(){
users_so = SharedObject.get("users");//获取本地共享对象users.注意,这是在服务端.不需要远程,而是本地
}
application.onConnect = function(client, name){//client为带协议的地址串的连接表示,name为输入的参数
if (idPool.length <= 0){//如果对象池满
application.rejectConnection(client, {msg:"Too many users."});//拒绝连接请求,给出信息,指明原因
}
client.id = idPool.pop();//从堆栈顶部弹出一个.并且给client多安个id属性。现在client有id属性了,后面可以使用了
application.acceptConnection(client);//接受连接请求
client.call("setID", null, client.id);//调用client的setID,给client发消息,将id传过去,null说明没有指定返回信息处理器
users_so.setProperty(client.id, name); //将id:name值对保存到共享对象里。注意,这是服务器端
}
application.onDisconnect = function(client){
idPool.push(client.id);//将要回收的id压回堆栈
users_so.setProperty(client.id, null); //在共享对象里,将与id对应的值对设置为空,即删除。
}
myID = ""; //每个客户端都有一个id,表示自己,独一无二
nc = new NetConnection(); //连接对象。全局使用
/**
* setID is a remote method that will be called by the server
* after the client connects. Once we get our unique ID from the
* server we can use it to publish our stream.
*/
nc.setID = function(id){ //setID方法,绑到连接上.如此,服务端就可以用client调用,给客户端发送消息了.这里,发送了id信息
myID = id; //事实上,"我"的id是服务器分配的.
statusInput.text = "Online. Your client's ID is: " + myID;//在状态栏显示在线信息及id
ns = new NetStream(nc);//建立流
ns.attachAudio(Microphone.get());//将流管道接到麦克音频源上
var cam = Camera.get();//打开摄像头
ns.attachVideo(cam);//将同一管道流接到摄像头上.这样,音频视频都接到同一管道上了.也可以使用上面接麦克的写法,一个
//语句即可.因为下面还要用到,所以把引用拿出来了.
ns.publish(id);//发布id信息
_root[id].video.attachVideo(cam);//将摄像头同时连到自己的视频播放窗口.就能自拍了.同时有4个剪辑对象(被拖到)在舞台
//上,形成数组.每个剪辑里有嵌入式视频与文本输入框.现在要访问剪辑里的视频对象,使用这种方式.video是剪辑里视频对象
init();//开始初始化工作
}//这个方法在客户端执行,因此可以使用客户端的资源,如麦克和摄像头等.它被服务端调用,因此又可得到(传递)消息.
/**
* onStatus is called whenever the status of the network
* connection changes. It is how we know if we are connected
* or not.
*/
nc.onStatus = function(info){//状态事件处理器.一旦网络连接状态改变,就调用它.诸如连接成功,失败等.info是服务器返回的
connectButton.label = "Connect";
connectButton.enabled = true;
switch(info.code){
case "NetConnection.Connect.Success":// 成功状态
connectButton.label = "Disconnect";//标签改为"断开"
statusInput.text = "Online";//标识"在线"
break;
case "NetConnection.Connect.Failed": //失败状态
statusInput.text = "Cannot reach server. Possible network error.";
break;
case "NetConnection.Connect.Rejected"://连接拒绝
statusInput.text = info.application.msg;//显示原因
break;
case "NetConnection.Connect.Closed"://连接关闭
statusInput.text += " Connection closed.";
break;
}
}
connectButton.addEventListener("click", this);//给按钮注册事件监听器.this代表谁?
/**
* click() is called when the connectButton is pressed.
* Depending on the label of the button either a
* connection is attempted or the current connection is
* closed.
*/
function click(ev){//点击事件处理器.传入事件对象
var button = ev.target;//取事件源
var command = button.label;//取按钮的文字标签
switch(command){
case "Connect"://连接命令
nc.connect("rtmp:/helloVideo", userNameInput.text);//连接,到服务端应用,传递用户名
button.label = "Wait...";
button.enabled = false;//按钮不可用
break;
case "Disconnect"://断开
nc.close();//关闭连接
button.label = "Connect";
break;
}
}
/**
* init() is called after the server calls the setID method
* It initializes the shared users object and then connects it.
*/
function init(){//服务端调用setID后,执行本初始化函数
users_so = SharedObject.getRemote("users", nc.uri);//获取远程共享对象,到uri,连接到users上
users_so.onSync = function(infoList){//共享对象同步事件处理器.共享对象里发生任何状态变化,都执行.信息列表里有具体信息
for (var i in infoList){//逐条检测信息列表
var info = infoList[i];//一条信息
switch(info.code){//检测信息码
case "change": //数据改变
var id = info.name;//取出名字,为id.name是信息的一个属性吗?规范在哪里?
var mc = _root[id];//找对应的剪辑对象
mc.nameInput.text = users_so.data[id];//还记得存入共享对象里的值对吗?现在按名字把值取出来.剪辑将它显示出来
if (myID != id){//判断数据变化的id与播放窗口是不是同一个。
var ns = new NetStream(nc);//建立管道流
mc.video.attachVideo(ns);//连到剪辑的播放窗口里
ns.play(id);//播放流, guest_1,
mc.ns = ns;//mc有ns属性吗?这里是新加的,还是已有的?在什么时候用到?还是已经用到了?
}//事实上,有4个窗口对象,只有一个是自己的,其余3个id都不一样.这样,就给3个窗口分别连到自己的流了.关键是
//每个窗口播放自己的流. 当然了,前提是数据流要变化.数据不变化,就不需要播放,因为没数据嘛
break;
case "delete"://有人离开了,就删除之
var id = info.name; //这个人离开了
var mc = _root[id];//取它的剪辑
mc.ns.close();//将剪辑里的流关闭.上面新加的属性,这里用上了
mc.nameInput.text = "";
mc.video.clear();//视频窗口处理
break;
}
}//上面,info只有两个属性出现过:info.code和info.name.进一步查资料
}
users_so.connect(nc); //共享对象连接. 注意:1)连接放在同步处理后面;2)有连接,就有状态变化,这都是服务端调用的
}