AlexWang

实际内部Confer内部处理用户禁言及全局禁言

PDU新增字段
... ... @@ -18,956 +18,994 @@ import Sass from 'Sass';
let loger = Loger.getLoger('ConferApe');
class ConferApe extends Ape {
constructor() {
super(
ApeConsts.CONFERENCE_SESSION_ID,
ApeConsts.CONFERENCE_SESSION_NAME,
ApeConsts.CONFERENCE_SESSION_TAG
);
constructor() {
super(
ApeConsts.CONFERENCE_SESSION_ID,
ApeConsts.CONFERENCE_SESSION_NAME,
ApeConsts.CONFERENCE_SESSION_TAG
);
this.rosters = {};//用户列表
this.timerCounter = new TimerCounter();//计时器
this.rosters = {}; //用户列表
this.timerCounter = new TimerCounter(); //计时器
//第三方消息控制 parent和Iframe直接的通讯
this.thirdMessage=new ThirdMessage();
this.thirdMessage.on(ThirdMessage.RECIVE_MESSAGE,this.onThirdReciveParentMessage.bind(this));
//第三方消息控制 parent和Iframe直接的通讯
this.thirdMessage = new ThirdMessage();
this.thirdMessage.on(ThirdMessage.RECIVE_MESSAGE, this.onThirdReciveParentMessage.bind(this));
// Ape Models
this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
// Ape Models
this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_ROSTER, ApeConsts.CONFERENCE_OBJ_ROSTER_ID,
ApeConsts.CONFERENCE_OBJ_ROSTER_NAME, ApeConsts.CONFERENCE_OBJ_ROSTER_TAG, 0, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_ROSTER, ApeConsts.CONFERENCE_OBJ_ROSTER_ID,
ApeConsts.CONFERENCE_OBJ_ROSTER_NAME, ApeConsts.CONFERENCE_OBJ_ROSTER_TAG, 0, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_QUEUE, ApeConsts.CONFERENCE_OBJ_QUEUE_ID,
ApeConsts.CONFERENCE_OBJ_QUEUE_NAME, ApeConsts.CONFERENCE_OBJ_QUEUE_TAG, 0, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_QUEUE, ApeConsts.CONFERENCE_OBJ_QUEUE_ID,
ApeConsts.CONFERENCE_OBJ_QUEUE_NAME, ApeConsts.CONFERENCE_OBJ_QUEUE_TAG, 0, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_TABLE, ApeConsts.CONFERENCE_OBJ_TABLE_ID,
ApeConsts.CONFERENCE_OBJ_TABLE_NAME, ApeConsts.CONFERENCE_OBJ_TABLE_TAG, 0, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_TABLE, ApeConsts.CONFERENCE_OBJ_TABLE_ID,
ApeConsts.CONFERENCE_OBJ_TABLE_NAME, ApeConsts.CONFERENCE_OBJ_TABLE_TAG, 0, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_COUNTER, ApeConsts.CONFERENCE_OBJ_COUNTER_ID,
ApeConsts.CONFERENCE_OBJ_COUNTER_NAME, ApeConsts.CONFERENCE_OBJ_COUNTER_TAG, 0, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_COUNTER, ApeConsts.CONFERENCE_OBJ_COUNTER_ID,
ApeConsts.CONFERENCE_OBJ_COUNTER_NAME, ApeConsts.CONFERENCE_OBJ_COUNTER_TAG, 0, new ArrayBuffer);
this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
this.on(pdu.RCPDU_SEND_CONFERENCE_DATA_REQUEST, this.conferMsgComingHandler.bind(this));//这个是课堂消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理
this.on(pdu.RCPDU_CONFERENCE_RECORD_REQUEST, this.onSendConferRecordRequestHandler.bind(this));//发送录制和停止录制消息
this.on(pdu.RCPDU_THIRD_BROADCAST_DATA_REQUEST, this.onThirdBroadcastDataHandler.bind(this));//第三方广播消息
}
this.on(pdu.RCPDU_SEND_CONFERENCE_DATA_REQUEST, this.conferMsgComingHandler.bind(this)); //这个是课堂消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理
this.on(pdu.RCPDU_CONFERENCE_RECORD_REQUEST, this.onSendConferRecordRequestHandler.bind(this)); //发送录制和停止录制消息
this.on(pdu.RCPDU_THIRD_BROADCAST_DATA_REQUEST, this.onThirdBroadcastDataHandler.bind(this)); //第三方广播消息
}
//加入课堂
_joinSessionHandler(_data) {
//let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
let nodeInfoRecordPdu = this.getNodeInfo();
//加入课堂
_joinSessionHandler(_data) {
//let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
let nodeInfoRecordPdu = this.getNodeInfo();
let userDataPdu = new pdu['RCNodeInfoUserDataPdu'];
userDataPdu.qq = '';
userDataPdu.skype = '';
let userDataPdu = new pdu['RCNodeInfoUserDataPdu'];
userDataPdu.qq = '';
userDataPdu.skype = '';
nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer();
nodeInfoRecordPdu.deviceType = GlobalConfig.deviceType;//设备类型
nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer();
nodeInfoRecordPdu.deviceType = GlobalConfig.deviceType; //设备类型
loger.log('开始加入->',nodeInfoRecordPdu);
loger.log('开始加入->', nodeInfoRecordPdu);
let item = new pdu['RCRegistryRosterItemPdu'];
item.nodeId = nodeInfoRecordPdu.nodeId;
item.nodeData = nodeInfoRecordPdu.toArrayBuffer();
let item = new pdu['RCRegistryRosterItemPdu'];
item.nodeId = nodeInfoRecordPdu.nodeId;
item.nodeData = nodeInfoRecordPdu.toArrayBuffer();
let rosterUpdateItem = new pdu['RCRegistryRosterUpdateItemPdu'];
rosterUpdateItem.type = pdu.RCPDU_REG_ROSTER_UPDATE_PDU;
rosterUpdateItem.items.push(item);
let rosterUpdateItem = new pdu['RCRegistryRosterUpdateItemPdu'];
rosterUpdateItem.type = pdu.RCPDU_REG_ROSTER_UPDATE_PDU;
rosterUpdateItem.items.push(item);
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_ROSTER_ID;
updateObjPdu.subType = rosterUpdateItem.type;
updateObjPdu.userData = rosterUpdateItem.toArrayBuffer();
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_ROSTER_ID;
updateObjPdu.subType = rosterUpdateItem.type;
updateObjPdu.userData = rosterUpdateItem.toArrayBuffer();
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
this.sendUniform(adapterPdu, true);
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
this.sendUniform(adapterPdu, true);
}
//获取角色信息
getNodeInfo(){
let nodeInfoRecordPdu = new pdu['RCNodeInfoRecordPdu'];
nodeInfoRecordPdu.nodeId= GlobalConfig.nodeId;
nodeInfoRecordPdu.name= GlobalConfig.userName;
nodeInfoRecordPdu.role= ApeConsts.userTypesToId[GlobalConfig.userRole] || 1; //NR_NORMAL用户的身份,根据用户登录时的身份设置;
nodeInfoRecordPdu.level= GlobalConfig.level;
//nodeInfoRecordPdu.audioRecords= GlobalConfig.audioRecords;
//nodeInfoRecordPdu.videoRecords= GlobalConfig.videoRecords;
//nodeInfoRecordPdu.status= GlobalConfig.status;
nodeInfoRecordPdu.userData= GlobalConfig.userData;
nodeInfoRecordPdu.userId= GlobalConfig.userId;
nodeInfoRecordPdu.handUpTime= GlobalConfig.handUpTime;
//nodeInfoRecordPdu.deviceType= GlobalConfig.deviceType;
//nodeInfoRecordPdu.mobileDirection= GlobalConfig.mobileDirection;
nodeInfoRecordPdu.microphones= GlobalConfig.microphones;
nodeInfoRecordPdu.cameras= GlobalConfig.cameras;
nodeInfoRecordPdu.openCamera= GlobalConfig.openCamera;
nodeInfoRecordPdu.openMicrophones= GlobalConfig.openMicrophones;
nodeInfoRecordPdu.videoQuality= GlobalConfig.videoQuality;
nodeInfoRecordPdu.userIp= GlobalConfig.userIp;
nodeInfoRecordPdu.curVideoQuality=GlobalConfig.curVideoQuality;
nodeInfoRecordPdu.micGain= GlobalConfig.micGain;
nodeInfoRecordPdu.speakerVolume=GlobalConfig.speakerVolume;
nodeInfoRecordPdu.micCode= GlobalConfig.micCode;
nodeInfoRecordPdu.curCamera=GlobalConfig.curCamera;
nodeInfoRecordPdu.curMicrophone=GlobalConfig.curMicrophone;
nodeInfoRecordPdu.country=GlobalConfig.country ;//国家
nodeInfoRecordPdu.city=GlobalConfig.city ;//城市
nodeInfoRecordPdu.province= GlobalConfig.province;//服务商
nodeInfoRecordPdu.isp=GlobalConfig.isp;//服务商
//用户的MS列表
let msListAll=GlobalConfig.msListAll;
for(let k=0;k<msListAll.length;k++){
let msItem=msListAll[k];
if(msItem){
let msListItemPdu = new pdu['MsListItemPdu'];
msListItemPdu.ip=msItem.ip||"";
msListItemPdu.port=msItem.port||"";
msListItemPdu.country=msItem.country||"";
msListItemPdu.province=msItem.province||"";
msListItemPdu.city=msItem.city||"";
nodeInfoRecordPdu.msList.push(msListItemPdu);
}
}
return nodeInfoRecordPdu;
}
//更新角色数据
updateUserInfo(){
let nodeInfoRecordPdu = this.getNodeInfo();
loger.log('更新用户信息->',nodeInfoRecordPdu);
let userDataPdu = new pdu['RCNodeInfoUserDataPdu'];
userDataPdu.qq = '';
userDataPdu.skype = '';
nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer();
nodeInfoRecordPdu.deviceType = GlobalConfig.deviceType;//设备类型
let item = new pdu['RCRegistryRosterItemPdu'];
item.nodeId = nodeInfoRecordPdu.nodeId;
item.nodeData = nodeInfoRecordPdu.toArrayBuffer();
let rosterUpdateItem = new pdu['RCRegistryRosterUpdateItemPdu'];
rosterUpdateItem.type = pdu.RCPDU_REG_ROSTER_UPDATE_PDU;
rosterUpdateItem.items.push(item);
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_ROSTER_ID;
updateObjPdu.subType = rosterUpdateItem.type;
updateObjPdu.userData = rosterUpdateItem.toArrayBuffer();
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
this.sendUniform(adapterPdu, true);
}
sendConferMsg(_messageInfo) {
if (this._classInfo == null || EngineUtils.isEmptyObject(this._classInfo)) {
loger.log('不能发送课堂消息.McuClient还未初始化数据!');
if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
}
return;
}
// to, message
loger.log('发送课堂控制消息.', _messageInfo);
let conferSendPdu = new pdu['RCConferenceSendDataRequestPdu'];
conferSendPdu.type = pdu.RCPDU_SEND_CONFERENCE_DATA_REQUEST;
conferSendPdu.initiator = this._classInfo.nodeId;//发起人
conferSendPdu.peer = parseInt(_messageInfo.to);//发送给谁,公聊的时候是0,私聊的时候是指定的用户id
conferSendPdu.userData = this._rCArrayBufferUtil.strToUint8Array("h5" + _messageInfo.message);
//conferSendPdu.userData =UTF8.setBytesFromString(_messageInfo.message);
conferSendPdu.isPublic = true;
conferSendPdu.actionType = _messageInfo.actionType;
// if (!(conferSendPdu.isPublic || 0 === conferSendPdu.peer)) {
if (!conferSendPdu.isPublic && 0 != conferSendPdu.peer) {
//发送给制定的人
//loger.log('发送私聊课堂消息.');
this.send(conferSendPdu);
} else {
//发送给所有人
// loger.log('发送公聊课堂消息.');
this.sendChatUniform(conferSendPdu);
}
}
//发送录制或停止录制的消息,{"recordStatus":true};true为开始录制,false为停止录制
sendConferRecordMsg(_param) {
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
if (_param == null) {
loger.warn("控制录制状的消息发送失败,参数错误", _param);
return;
}
/* message RCConferenceRecordRequestPdu {
optional uint32 initiator = 1; // 发起录像指令的node id
optional bool record = 2; // 录像指令 true:开始录像, false:停止录像
optional uint32 class_time = 3; // 课堂进行时间(秒)
optional string filename = 4; // 录像文件名称,filename中增加目录部分
}*/
//保存当前的录制状态
GlobalConfig.recordStatus = _param.recordStatus || false;
let conferRecordSendPdu = new pdu['RCConferenceRecordRequestPdu'];
conferRecordSendPdu.type = pdu.RCPDU_CONFERENCE_RECORD_REQUEST;
conferRecordSendPdu.peer = 0;//channel 为0
conferRecordSendPdu.isPublic = true;
conferRecordSendPdu.initiator = this._classInfo.nodeId;//发起人
conferRecordSendPdu.record = GlobalConfig.recordStatus;
//conferRecordSendPdu.classTime = GlobalConfig.classTimestamp;//不能使用课堂进行时间,这个时间结束课堂的时候会被清除
conferRecordSendPdu.classTime = GlobalConfig.recordTimestamp;//课堂录制的累积时间,不会被清除
conferRecordSendPdu.filename = GlobalConfig.recordFileName || GlobalConfig.classId + "_" + EngineUtils.creatTimestampYMD() + ".rec";
this.sendChatUniform(conferRecordSendPdu);
// to, message
loger.warn('发送录制消息-》', _param);
}
//开启录制
startRecord() {
//如果录制的时间长超出设定的最大录制时间就不再录制
if(GlobalConfig.recordTimestamp>=GlobalConfig.allowRecordMaxTime){
loger.warn('不能再录制,录制时间已经达到最大限制',GlobalConfig.recordTimestamp);
return;
}
loger.log('startRecord', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
//如果是host
if (GlobalConfig.isHost) {
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.sendConferRecordMsg({"recordStatus": true});
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this._emit(MessageTypes.CLASS_RECORD_START);//课堂开始录制
}
}
//停止录制
stopRecord(isForce) {
loger.log('stopRecord', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
if(isForce&&isForce==true){
//强制停止,可以是host之外的身份(比如当前课堂老师异常退出,没有老师,会随机选择一个人来做释放操作)
if (GlobalConfig.recordStatus) {
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.sendConferRecordMsg({"recordStatus": false});
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
}
}else {
//身份是host,并且当前正在录制中
if (GlobalConfig.isHost && GlobalConfig.recordStatus) {
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.sendConferRecordMsg({"recordStatus": false});
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
}
}
}
//主动离开课堂,发送通知到服务器
leaveClass() {
let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
let userDataPdu = new pdu['RCNodeInfoUserDataPdu'];
userDataPdu.qq = '';
userDataPdu.skype = '';
nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer();
nodeInfoRecordPdu.deviceType = GlobalConfig.deviceType;
let item = new pdu['RCRegistryRosterItemPdu'];
item.nodeId = nodeInfoRecordPdu.nodeId;
item.nodeData = nodeInfoRecordPdu.toArrayBuffer();
let rosterUpdateItem = new pdu['RCRegistryRosterDeleteItemPdu'];
rosterUpdateItem.type = pdu.RCPDU_REG_ROSTER_DELETE_PDU;
rosterUpdateItem.nodeId = GlobalConfig.nodeId;
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_ROSTER_ID;
updateObjPdu.subType = rosterUpdateItem.type;
updateObjPdu.userData = rosterUpdateItem.toArrayBuffer();
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
this.sendUniform(adapterPdu, true);
}
//还原课堂状态
restorClass() {
GlobalConfig.classTimestamp = 0;
GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_WAIT;
getNodeInfo() {
let nodeInfoRecordPdu = new pdu['RCNodeInfoRecordPdu'];
nodeInfoRecordPdu.nodeId = GlobalConfig.nodeId;
nodeInfoRecordPdu.selfSilence = JSON.stringify(GlobalConfig.selfSilence);
nodeInfoRecordPdu.name = GlobalConfig.userName;
nodeInfoRecordPdu.role = ApeConsts.userTypesToId[GlobalConfig.userRole] || 1; //NR_NORMAL用户的身份,根据用户登录时的身份设置;
nodeInfoRecordPdu.level = GlobalConfig.level;
//nodeInfoRecordPdu.audioRecords= GlobalConfig.audioRecords;
//nodeInfoRecordPdu.videoRecords= GlobalConfig.videoRecords;
//nodeInfoRecordPdu.status= GlobalConfig.status;
nodeInfoRecordPdu.userData = GlobalConfig.userData;
nodeInfoRecordPdu.userId = GlobalConfig.userId;
nodeInfoRecordPdu.handUpTime = GlobalConfig.handUpTime;
//nodeInfoRecordPdu.deviceType= GlobalConfig.deviceType;
//nodeInfoRecordPdu.mobileDirection= GlobalConfig.mobileDirection;
nodeInfoRecordPdu.microphones = GlobalConfig.microphones;
nodeInfoRecordPdu.cameras = GlobalConfig.cameras;
nodeInfoRecordPdu.openCamera = GlobalConfig.openCamera;
nodeInfoRecordPdu.openMicrophones = GlobalConfig.openMicrophones;
nodeInfoRecordPdu.videoQuality = GlobalConfig.videoQuality;
nodeInfoRecordPdu.userIp = GlobalConfig.userIp;
nodeInfoRecordPdu.curVideoQuality = GlobalConfig.curVideoQuality;
nodeInfoRecordPdu.micGain = GlobalConfig.micGain;
nodeInfoRecordPdu.speakerVolume = GlobalConfig.speakerVolume;
nodeInfoRecordPdu.micCode = GlobalConfig.micCode;
nodeInfoRecordPdu.curCamera = GlobalConfig.curCamera;
nodeInfoRecordPdu.curMicrophone = GlobalConfig.curMicrophone;
nodeInfoRecordPdu.country = GlobalConfig.country; //国家
nodeInfoRecordPdu.city = GlobalConfig.city; //城市
nodeInfoRecordPdu.province = GlobalConfig.province; //服务商
nodeInfoRecordPdu.isp = GlobalConfig.isp; //服务商
//用户的MS列表
let msListAll = GlobalConfig.msListAll;
for (let k = 0; k < msListAll.length; k++) {
let msItem = msListAll[k];
if (msItem) {
let msListItemPdu = new pdu['MsListItemPdu'];
msListItemPdu.ip = msItem.ip || "";
msListItemPdu.port = msItem.port || "";
msListItemPdu.country = msItem.country || "";
msListItemPdu.province = msItem.province || "";
msListItemPdu.city = msItem.city || "";
nodeInfoRecordPdu.msList.push(msListItemPdu);
}
}
return nodeInfoRecordPdu;
}
//更新角色数据
updateUserInfo() {
let nodeInfoRecordPdu = this.getNodeInfo();
loger.log('更新用户信息->', nodeInfoRecordPdu);
let userDataPdu = new pdu['RCNodeInfoUserDataPdu'];
userDataPdu.qq = '';
userDataPdu.skype = '';
nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer();
nodeInfoRecordPdu.deviceType = GlobalConfig.deviceType; //设备类型
let item = new pdu['RCRegistryRosterItemPdu'];
item.nodeId = nodeInfoRecordPdu.nodeId;
item.nodeData = nodeInfoRecordPdu.toArrayBuffer();
let rosterUpdateItem = new pdu['RCRegistryRosterUpdateItemPdu'];
rosterUpdateItem.type = pdu.RCPDU_REG_ROSTER_UPDATE_PDU;
rosterUpdateItem.items.push(item);
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_ROSTER_ID;
updateObjPdu.subType = rosterUpdateItem.type;
updateObjPdu.userData = rosterUpdateItem.toArrayBuffer();
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
this.sendUniform(adapterPdu, true);
}
sendConferMsg(_messageInfo) {
if (this._classInfo == null || EngineUtils.isEmptyObject(this._classInfo)) {
loger.log('不能发送课堂消息.McuClient还未初始化数据!');
if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
}
return;
}
// to, message
loger.log('发送课堂控制消息.', _messageInfo);
let conferSendPdu = new pdu['RCConferenceSendDataRequestPdu'];
conferSendPdu.type = pdu.RCPDU_SEND_CONFERENCE_DATA_REQUEST;
conferSendPdu.initiator = this._classInfo.nodeId; //发起人
conferSendPdu.peer = parseInt(_messageInfo.to); //发送给谁,公聊的时候是0,私聊的时候是指定的用户id
conferSendPdu.userData = this._rCArrayBufferUtil.strToUint8Array("h5" + _messageInfo.message);
//conferSendPdu.userData =UTF8.setBytesFromString(_messageInfo.message);
conferSendPdu.isPublic = true;
conferSendPdu.actionType = _messageInfo.actionType;
// if (!(conferSendPdu.isPublic || 0 === conferSendPdu.peer)) {
if (!conferSendPdu.isPublic && 0 != conferSendPdu.peer) {
//发送给制定的人
//loger.log('发送私聊课堂消息.');
this.send(conferSendPdu);
} else {
//发送给所有人
// loger.log('发送公聊课堂消息.');
this.sendChatUniform(conferSendPdu);
}
}
//发送录制或停止录制的消息,{"recordStatus":true};true为开始录制,false为停止录制
sendConferRecordMsg(_param) {
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return { "code": ApeConsts.RETURN_FAILED, "data": "已经断开连接" };
}
if (_param == null) {
loger.warn("控制录制状的消息发送失败,参数错误", _param);
return;
}
/* message RCConferenceRecordRequestPdu {
optional uint32 initiator = 1; // 发起录像指令的node id
optional bool record = 2; // 录像指令 true:开始录像, false:停止录像
optional uint32 class_time = 3; // 课堂进行时间(秒)
optional string filename = 4; // 录像文件名称,filename中增加目录部分
}*/
//保存当前的录制状态
GlobalConfig.recordStatus = _param.recordStatus || false;
let conferRecordSendPdu = new pdu['RCConferenceRecordRequestPdu'];
conferRecordSendPdu.type = pdu.RCPDU_CONFERENCE_RECORD_REQUEST;
conferRecordSendPdu.peer = 0; //channel 为0
conferRecordSendPdu.isPublic = true;
conferRecordSendPdu.initiator = this._classInfo.nodeId; //发起人
conferRecordSendPdu.record = GlobalConfig.recordStatus;
//conferRecordSendPdu.classTime = GlobalConfig.classTimestamp;//不能使用课堂进行时间,这个时间结束课堂的时候会被清除
conferRecordSendPdu.classTime = GlobalConfig.recordTimestamp; //课堂录制的累积时间,不会被清除
conferRecordSendPdu.filename = GlobalConfig.recordFileName || GlobalConfig.classId + "_" + EngineUtils.creatTimestampYMD() + ".rec";
this.sendChatUniform(conferRecordSendPdu);
// to, message
loger.warn('发送录制消息-》', _param);
}
//开启录制
startRecord() {
//如果录制的时间长超出设定的最大录制时间就不再录制
if (GlobalConfig.recordTimestamp >= GlobalConfig.allowRecordMaxTime) {
loger.warn('不能再录制,录制时间已经达到最大限制', GlobalConfig.recordTimestamp);
return;
}
loger.log('startRecord', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
//如果是host
if (GlobalConfig.isHost) {
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.sendConferRecordMsg({ "recordStatus": true });
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this._emit(MessageTypes.CLASS_RECORD_START); //课堂开始录制
}
}
//停止录制
stopRecord(isForce) {
loger.log('stopRecord', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
if (isForce && isForce == true) {
//强制停止,可以是host之外的身份(比如当前课堂老师异常退出,没有老师,会随机选择一个人来做释放操作)
if (GlobalConfig.recordStatus) {
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.stopRecord();
this.sendConferRecordMsg({ "recordStatus": false });
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this.sendUpdaterClassStatusInfo({"actionType": 0,isStopAllPublishMedia:true});
loger.log('restorClass');
}
//开始上课
startClass(_param) {
if (GlobalConfig.isHost) {
let timestamp = EngineUtils.creatTimestampStr();
GlobalConfig.classStopTime = timestamp;
//如果录制的文件名不存在,需要创建一个名字
let timestampYMD = EngineUtils.creatTimestampYMD();
GlobalConfig.recordFileName = GlobalConfig.recordFileName ||
GlobalConfig.siteId + "/" + timestampYMD + "/"
+ GlobalConfig.classId + "_" + timestampYMD + ".rec";//4、文件名称 $RECORD_HOME/`site id`/`日期`/`filename` 例:/data/record/su/20161216/`filename`
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT) {
//之前是为开始状态,第一次点开始
GlobalConfig.classStartTime = timestamp;
}
GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_STARTED;
//开始录制
this.startRecord();
//课堂状态改变
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//同步课堂状态
this.sendUpdaterClassStatusInfo({"actionType": 1,isStopAllPublishMedia:true});
//开始计时
this.startTimerCounter();
} else {
loger.warn('没有开始课堂的权限');
}
}
//暂停上课 {isForce:true} isForce->是否强制提交(true为是)
pauseClass(_param) {
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT) {
loger.warn('还没有开始,不能点暂停');
return;
}
GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_PAUSE;
}
} else {
//身份是host,并且当前正在录制中
if (GlobalConfig.isHost && GlobalConfig.recordStatus) {
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.stopRecord();
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE,_param);
this.sendUpdaterClassStatusInfo({"actionType": 2,isStopAllPublishMedia:true});
this.stopTimerCounter();
}
//关闭课堂
closeClass(_param) {
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT) {
loger.warn('还没有开始,不能点关闭');
return;
}
this.stopTimerCounter();
this.restorClass();
//把所有人都踢出课堂
this.sendConferMsg({"to": 0, "message": "所有人退出课堂", "actionType": ApeConsts.CLASS_ACTION_CLOSE_ALL});
this.sendConferRecordMsg({ "recordStatus": false });
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
}
}
}
//主动离开课堂,发送通知到服务器
leaveClass() {
let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
let userDataPdu = new pdu['RCNodeInfoUserDataPdu'];
userDataPdu.qq = '';
userDataPdu.skype = '';
nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer();
nodeInfoRecordPdu.deviceType = GlobalConfig.deviceType;
let item = new pdu['RCRegistryRosterItemPdu'];
item.nodeId = nodeInfoRecordPdu.nodeId;
item.nodeData = nodeInfoRecordPdu.toArrayBuffer();
let rosterUpdateItem = new pdu['RCRegistryRosterDeleteItemPdu'];
rosterUpdateItem.type = pdu.RCPDU_REG_ROSTER_DELETE_PDU;
rosterUpdateItem.nodeId = GlobalConfig.nodeId;
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_ROSTER_ID;
updateObjPdu.subType = rosterUpdateItem.type;
updateObjPdu.userData = rosterUpdateItem.toArrayBuffer();
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
this.sendUniform(adapterPdu, true);
}
//还原课堂状态
restorClass() {
GlobalConfig.classTimestamp = 0;
GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_WAIT;
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.stopRecord();
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this.sendUpdaterClassStatusInfo({ "actionType": 0, isStopAllPublishMedia: true });
loger.log('restorClass');
}
// 全局禁言
silenceClass(isSilence) {
if (GlobalConfig.isHost) {
GlobalConfig.silence = !!isSilence;
//禁言状态改变
this._emit(MessageTypes.CLASS_SILENCE_CHANGE, GlobalConfig.silence);
//同步禁言状态
this.sendUpdaterClassStatusInfo();
} else {
loger.warn('没有开始课堂的权限');
}
}
//开始上课
startClass(_param) {
if (GlobalConfig.isHost) {
let timestamp = EngineUtils.creatTimestampStr();
GlobalConfig.classStopTime = timestamp;
//如果录制的文件名不存在,需要创建一个名字
let timestampYMD = EngineUtils.creatTimestampYMD();
GlobalConfig.recordFileName = GlobalConfig.recordFileName ||
GlobalConfig.siteId + "/" + timestampYMD + "/" + GlobalConfig.classId + "_" + timestampYMD + ".rec"; //4、文件名称 $RECORD_HOME/`site id`/`日期`/`filename` 例:/data/record/su/20161216/`filename`
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT) {
//之前是为开始状态,第一次点开始
GlobalConfig.classStartTime = timestamp;
}
GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_STARTED;
//开始录制
this.startRecord();
//课堂状态改变
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//同步课堂状态
this.sendUpdaterClassStatusInfo({ "actionType": 1, isStopAllPublishMedia: true });
//开始计时
this.startTimerCounter();
} else {
loger.warn('没有开始课堂的权限');
}
}
//暂停上课 {isForce:true} isForce->是否强制提交(true为是)
pauseClass(_param) {
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT) {
loger.warn('还没有开始,不能点暂停');
return;
}
GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_PAUSE;
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.stopRecord();
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE, _param);
this.sendUpdaterClassStatusInfo({ "actionType": 2, isStopAllPublishMedia: true });
this.stopTimerCounter();
}
//关闭课堂
closeClass(_param) {
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT) {
loger.warn('还没有开始,不能点关闭');
return;
}
this.stopTimerCounter();
this.restorClass();
//把所有人都踢出课堂
this.sendConferMsg({ "to": 0, "message": "所有人退出课堂", "actionType": ApeConsts.CLASS_ACTION_CLOSE_ALL });
}
//更新设备信息
updateDeviceInfo(_param){
loger.log('更新用户的设备信息->',_param);
this.updateUserInfo();
}
//控制举手状态
controlHandUpStatus(_param){
//控制用户的举手状态
if(!_param||!_param.nodeId){
loger.log('控制举手状态->失败->参数错误',_param);
return;
}
let msgObj={};
msgObj.nodeId=_param.nodeId;
msgObj.isHandUp=false;
if(_param&&_param.isHandUp==true){
msgObj.isHandUp=true;
}
this.sendConferMsg({"to":_param.nodeId, "message":JSON.stringify(msgObj), "actionType": ApeConsts.CLASS_ACTION_HANDUP_STATUS_CHANGE});
}
//切换举手状态
changeHandUpStatus(_param){
loger.log('切换举手状态->',_param);
if(_param&&_param.isHandUp==true){
//举手
GlobalConfig.handUpTime=EngineUtils.creatTimestamp();
}else {
GlobalConfig.handUpTime=0;//默认0是没有举手的状态(大于0就是举手)
}
this.updateUserInfo();
updateDeviceInfo(_param) {
loger.log('更新用户的设备信息->', _param);
this.updateUserInfo();
}
// 禁言控制
controlSilenceStatus(_param) {
//控制用户的禁言状态
if (!_param || !_param.nodeId) {
loger.log('控制禁言状态->失败->参数错误', _param);
return;
}
let msgObj = {};
msgObj.nodeId = _param.nodeId;
msgObj.silence = _param.silence || '';
this.sendConferMsg({ "to": _param.nodeId, "message": JSON.stringify(msgObj), "actionType": ApeConsts.USER_ACTION_SILENCE_STATUS_CHANGE });
}
changeSilenceStatus(_param) {
loger.log('切换禁言状态->', _param);
GlobalConfig.selfSilence = _param.silence;
this.updateUserInfo();
}
//控制举手状态
controlHandUpStatus(_param) {
//控制用户的举手状态
if (!_param || !_param.nodeId) {
loger.log('控制举手状态->失败->参数错误', _param);
return;
}
let msgObj = {};
msgObj.nodeId = _param.nodeId;
msgObj.isHandUp = false;
if (_param && _param.isHandUp == true) {
msgObj.isHandUp = true;
}
this.sendConferMsg({ "to": _param.nodeId, "message": JSON.stringify(msgObj), "actionType": ApeConsts.CLASS_ACTION_HANDUP_STATUS_CHANGE });
}
//切换举手状态
changeHandUpStatus(_param) {
loger.log('切换举手状态->', _param);
if (_param && _param.isHandUp == true) {
//举手
GlobalConfig.handUpTime = EngineUtils.creatTimestamp();
} else {
GlobalConfig.handUpTime = 0; //默认0是没有举手的状态(大于0就是举手)
}
this.updateUserInfo();
}
//课堂的场景模块发送改变
sceneTableChange(_param){
if(GlobalConfig.isRecordPlayBack){
return;
}
loger.log('切换文档-媒体-屏幕模块切换->',_param);
//如果是host身份
if (GlobalConfig.isHost) {
if(_param){
GlobalConfig.currentSceneTableId=parseInt(_param.currentSceneTableId)||0;//当前场景显示的模块 0=文档模块、1=屏幕共享、2=媒体共享
//保存数据到Sass
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//同步消息给其他人
this.sendUpdaterClassStatusInfo({"actionType": 1,isStopAllPublishMedia:false});
}
}
sceneTableChange(_param) {
if (GlobalConfig.isRecordPlayBack) {
return;
}
loger.log('切换文档-媒体-屏幕模块切换->', _param);
//如果是host身份
if (GlobalConfig.isHost) {
if (_param) {
GlobalConfig.currentSceneTableId = parseInt(_param.currentSceneTableId) || 0; //当前场景显示的模块 0=文档模块、1=屏幕共享、2=媒体共享
//保存数据到Sass
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//同步消息给其他人
this.sendUpdaterClassStatusInfo({ "actionType": 1, isStopAllPublishMedia: false });
}
}
}
//更新课堂信息
sendUpdaterClassStatusInfo(_param) {
//{"actionType": 1,isStopAllPublishMedia:false} //actionType课堂状态 isStopAllPublishMedia是否停止当前的所有推流
loger.log('发送更新课堂信息->');
if (_param == null || EngineUtils.isEmptyObject(_param)) {
loger.log('发送更新课堂信息->参数错误');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return;
}
let itemIdx = ApeConsts.CONFERENCE_OBJ_TABLE_ID;// itemIdx=_param.itemIdx;
let modelPdu = this.packPdu(_param, itemIdx);
loger.log(modelPdu);
if (modelPdu == null) {
loger.log('发送更新课堂信息->参数错误');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return;
}
let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
tableItemPdu.itemIdx = itemIdx;
tableItemPdu.owner = 0;//收到flash的是这个值,不清楚先写固定
tableItemPdu.registerObjId = ApeConsts.CONFERENCE_OBJ_TABLE_ID;
tableItemPdu.itemData = modelPdu.toArrayBuffer();
//updater
let tableUpdateItem = new pdu['RCRegistryTableUpdateItemPdu'];
//optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
//repeated RCRegistryTableItemPdu items = 2;
tableUpdateItem.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;//
tableUpdateItem.items.push(tableItemPdu);
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_TABLE_ID;
updateObjPdu.subType = tableUpdateItem.type;
updateObjPdu.userData = tableUpdateItem.toArrayBuffer();
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
this.sendUniform(adapterPdu, true);
}
/////收到消息处理/////////////////////////////////////////////////////////////////////////////////
//加入channel成功
onJoinChannelHandlerSuccess() {
loger.log('ConferApe.onJoinChannelHandlerSuccess', GlobalConfig.classStatus);
this.timerCounter.addTimerCallBack(this.timerCounterUptate.bind(this), 1);
//如果当前课堂正在进行中,开启计时器
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
//开始计时
this.startTimerCounter();
//如果是host ,开始录制
this.startRecord();
}else if(GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT&&
GlobalConfig.isHost&& GlobalConfig.isAutoStartClass&&
!GlobalConfig.isRecordPlayBack){
//自动开始上课的4个条件
//1.如果自己是host,2.Sass配置的是自动开始上课,3.并且当前是未开始状态,4.当前不是录制回放,开始自动上课
loger.log('自动开始上课->classStatus:', GlobalConfig.classStatus, " isHost:",GlobalConfig.isHost, " isAutoStartClass:",GlobalConfig.isAutoStartClass, " isRecordPlayBack:",GlobalConfig.isRecordPlayBack);
this.startClass();
}
}
//开启计时器
startTimerCounter() {
this.stopTimerCounter();
if(this.timerCounter){
this.timerCounter.startTimer();
}
sendUpdaterClassStatusInfo(_param) {
//{"actionType": 1,isStopAllPublishMedia:false} //actionType课堂状态 isStopAllPublishMedia是否停止当前的所有推流
loger.log('发送更新课堂信息->');
if (_param == null || EngineUtils.isEmptyObject(_param)) {
loger.log('发送更新课堂信息->参数错误');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return;
}
let itemIdx = ApeConsts.CONFERENCE_OBJ_TABLE_ID; // itemIdx=_param.itemIdx;
let modelPdu = this.packPdu(_param, itemIdx);
loger.log(modelPdu);
if (modelPdu == null) {
loger.log('发送更新课堂信息->参数错误');
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return;
}
let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
tableItemPdu.itemIdx = itemIdx;
tableItemPdu.owner = 0; //收到flash的是这个值,不清楚先写固定
tableItemPdu.registerObjId = ApeConsts.CONFERENCE_OBJ_TABLE_ID;
tableItemPdu.itemData = modelPdu.toArrayBuffer();
//updater
let tableUpdateItem = new pdu['RCRegistryTableUpdateItemPdu'];
//optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
//repeated RCRegistryTableItemPdu items = 2;
tableUpdateItem.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU; //
tableUpdateItem.items.push(tableItemPdu);
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CONFERENCE_OBJ_TABLE_ID;
updateObjPdu.subType = tableUpdateItem.type;
updateObjPdu.userData = tableUpdateItem.toArrayBuffer();
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
this.sendUniform(adapterPdu, true);
}
/////收到消息处理/////////////////////////////////////////////////////////////////////////////////
//加入channel成功
onJoinChannelHandlerSuccess() {
loger.log('ConferApe.onJoinChannelHandlerSuccess', GlobalConfig.classStatus);
this.timerCounter.addTimerCallBack(this.timerCounterUptate.bind(this), 1);
//如果当前课堂正在进行中,开启计时器
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
//开始计时
this.startTimerCounter();
//如果是host ,开始录制
this.startRecord();
} else if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT &&
GlobalConfig.isHost && GlobalConfig.isAutoStartClass &&
!GlobalConfig.isRecordPlayBack) {
//自动开始上课的4个条件
//1.如果自己是host,2.Sass配置的是自动开始上课,3.并且当前是未开始状态,4.当前不是录制回放,开始自动上课
loger.log('自动开始上课->classStatus:', GlobalConfig.classStatus, " isHost:", GlobalConfig.isHost, " isAutoStartClass:", GlobalConfig.isAutoStartClass, " isRecordPlayBack:", GlobalConfig.isRecordPlayBack);
this.startClass();
}
}
//开启计时器
startTimerCounter() {
this.stopTimerCounter();
if (this.timerCounter) {
this.timerCounter.startTimer();
}
}
//停止计时器
stopTimerCounter() {
if (this.timerCounter) {
this.timerCounter.stopTimer();
}
}
timerCounterUptate() {
if (!this.mcu.connected) {
loger.warn('MCU 连接已经断开');
this.stopTimerCounter();
}
//如果还没开始或已经暂停、关闭,不做计时处理
if (GlobalConfig.classStatus != ApeConsts.CLASS_STATUS_STARTED) {
loger.warn('当前课堂已经暂停或者未开始,不计时', "classStatus-->", GlobalConfig.classStatus);
return;
}
GlobalConfig.classTimestamp = GlobalConfig.classTimestamp + 1; //计时
//老师身份的时候要记录录制的时间
if (GlobalConfig.isHost) {
GlobalConfig.recordTimestamp = GlobalConfig.recordTimestamp + 1;
}
//loger.log('课堂进行时间',GlobalConfig.classTimestamp);
this._emit(MessageTypes.CLASS_UPDATE_TIMER, { "classTimestamp": GlobalConfig.classTimestamp });
if (GlobalConfig.classTimestamp % GlobalConfig.updateClassInfoDelay == 0) {
//如果是host身份,需要同步时间给其他人,同时把当前的状态上传到服务器
if (GlobalConfig.isHost) {
//保存数据到Sass
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//同步消息给其他人
this.sendUpdaterClassStatusInfo({ "actionType": 1, isStopAllPublishMedia: false });
}
}
//停止计时器
stopTimerCounter() {
if(this.timerCounter){
this.timerCounter.stopTimer();
}
//进行MS动态选点,选择最快的MS服务器地址(录制回放不做处理)
if (!GlobalConfig.isRecordPlayBack && GlobalConfig.classTimestamp % GlobalConfig.msDynamicChooseIpDelay == 0) {
this._emit(MessageTypes.SWITCH_MS_IP);
}
}
timerCounterUptate() {
if (!this.mcu.connected) {
loger.warn('MCU 连接已经断开');
this.stopTimerCounter();
}
//如果还没开始或已经暂停、关闭,不做计时处理
if (GlobalConfig.classStatus != ApeConsts.CLASS_STATUS_STARTED) {
loger.warn('当前课堂已经暂停或者未开始,不计时', "classStatus-->", GlobalConfig.classStatus);
return;
}
GlobalConfig.classTimestamp = GlobalConfig.classTimestamp + 1;//计时
//老师身份的时候要记录录制的时间
if(GlobalConfig.isHost){
GlobalConfig.recordTimestamp=GlobalConfig.recordTimestamp+1;
}
//loger.log('课堂进行时间',GlobalConfig.classTimestamp);
this._emit(MessageTypes.CLASS_UPDATE_TIMER, {"classTimestamp": GlobalConfig.classTimestamp});
if (GlobalConfig.classTimestamp % GlobalConfig.updateClassInfoDelay == 0) {
//如果是host身份,需要同步时间给其他人,同时把当前的状态上传到服务器
if (GlobalConfig.isHost) {
//保存数据到Sass
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
tableUpdateHandler(owner, itemIdx, itemData) {
try {
let model = this.unPackPdu(owner, itemIdx, itemData);
loger.log('课堂数据更新->', model);
//同步消息给其他人
this.sendUpdaterClassStatusInfo({"actionType": 1,isStopAllPublishMedia:false});
}
}
//进行MS动态选点,选择最快的MS服务器地址(录制回放不做处理)
if (!GlobalConfig.isRecordPlayBack&&GlobalConfig.classTimestamp % GlobalConfig.msDynamicChooseIpDelay == 0) {
this._emit(MessageTypes.SWITCH_MS_IP);
}
}
//处理课堂更新的信息
if (model && model.classStatusInfo) {
GlobalConfig.setClassStatusInfo(model.classStatusInfo);
tableUpdateHandler(owner, itemIdx, itemData) {
try {
let model = this.unPackPdu(owner, itemIdx, itemData);
loger.log('课堂数据更新->',model);
//处理课堂更新的信息
if (model && model.classStatusInfo) {
GlobalConfig.setClassStatusInfo(model.classStatusInfo);
if( model.classStatusInfo.isStopAllPublishMedia){
//课堂状态发送改变 需要对当前正在推的流进行停止,因为录制的问题;
this._emit(MessageTypes.STOP_ALL_MEDIA_PUBLISH);
}
}
//通知应用层更新课堂状态
let classInfo=GlobalConfig.classStatusInfo;
loger.log('通知应用层更新课堂状态->CLASS_UPTATE_STATUS')
this._emit(MessageTypes.CLASS_UPTATE_STATUS,classInfo);
//如果MCU已经断开连接,停止计时器
if (!this.mcu.connected) {
//停止计时
this.stopTimerCounter();
return;
}
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
//如果课堂在进行中,开始计时器
this.startTimerCounter();
} else {
//停止计时
this.stopTimerCounter();
}
} catch (err) {
loger.warn('ConferApe table update got exception->err', err.message);
if (model.classStatusInfo.isStopAllPublishMedia) {
//课堂状态发送改变 需要对当前正在推的流进行停止,因为录制的问题;
this._emit(MessageTypes.STOP_ALL_MEDIA_PUBLISH);
}
}
}
conferMsgComingHandler(_data) {
//flash RCConferenceSendDataRequestPdu
//loger.warn('conferMsgComingHandler needs to be handled.');
//const recordInfo = pdu['RCWhiteboardDataRequestPdu'].decode(pdu);
//loger.log("conferMsgComingHandler",recordInfo);
let chatReceivePdu = pdu['RCConferenceSendDataRequestPdu'].decode(_data);
let chatMsg = {};
chatMsg.fromNodeID = chatReceivePdu.initiator;
chatMsg.toNodeID = chatReceivePdu.peer;
chatMsg.message = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.userData, 2);
chatMsg.actionType = chatReceivePdu.actionType;
loger.log("conferMsgComingHandler", chatMsg);//{"fromNodeID":418883112,"toNodeID":0,"message":"所有人退出课堂","actionType":1}
switch (chatMsg.actionType) {
case ApeConsts.CLASS_ACTION_CLOSE_ALL:
loger.log(chatMsg.message);
//收到课堂关闭,所有人都退出,执行自己关闭的流程
this._emit(MessageTypes.CLASS_RUN_EXIT,{'type':1});
break;
case ApeConsts.CLASS_ACTION_HANDUP_STATUS_CHANGE:
console.log('chatMsg',chatMsg);
let msgObj=null;
try{
msgObj =JSON.parse(chatMsg.message);
if(msgObj&&msgObj.nodeId==GlobalConfig.nodeId){
this.changeHandUpStatus(msgObj);
}
}catch (err){
loger.warn('chatMsg->JSON数据解析失败');
}
break;
default:
break;
}
}
//通知应用层更新课堂状态
let classInfo = GlobalConfig.classStatusInfo;
loger.log('通知应用层更新课堂状态->CLASS_UPTATE_STATUS')
this._emit(MessageTypes.CLASS_UPTATE_STATUS, classInfo);
//-------------第三方消息------------------------------
//收到父级页面的消息,需要广播发送出去
onThirdReciveParentMessage(_msg){
loger.log('收到页面的消息->广播给其他模块->',_msg);
this.sendThirdBroadcastData({to:0,message:_msg});
//如果MCU已经断开连接,停止计时器
if (!this.mcu.connected) {
//停止计时
this.stopTimerCounter();
return;
}
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
//如果课堂在进行中,开始计时器
this.startTimerCounter();
} else {
//停止计时
this.stopTimerCounter();
}
} catch (err) {
loger.warn('ConferApe table update got exception->err', err.message);
}
}
conferMsgComingHandler(_data) {
//flash RCConferenceSendDataRequestPdu
//loger.warn('conferMsgComingHandler needs to be handled.');
//const recordInfo = pdu['RCWhiteboardDataRequestPdu'].decode(pdu);
//loger.log("conferMsgComingHandler",recordInfo);
let chatReceivePdu = pdu['RCConferenceSendDataRequestPdu'].decode(_data);
let chatMsg = {};
chatMsg.fromNodeID = chatReceivePdu.initiator;
chatMsg.toNodeID = chatReceivePdu.peer;
chatMsg.message = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.userData, 2);
chatMsg.actionType = chatReceivePdu.actionType;
loger.log("conferMsgComingHandler", chatMsg); //{"fromNodeID":418883112,"toNodeID":0,"message":"所有人退出课堂","actionType":1}
switch (chatMsg.actionType) {
case ApeConsts.CLASS_ACTION_CLOSE_ALL:
loger.log(chatMsg.message);
//收到课堂关闭,所有人都退出,执行自己关闭的流程
this._emit(MessageTypes.CLASS_RUN_EXIT, { 'type': 1 });
break;
case ApeConsts.CLASS_ACTION_HANDUP_STATUS_CHANGE:
console.log('chatMsg', chatMsg);
let msgObj = null;
try {
msgObj = JSON.parse(chatMsg.message);
if (msgObj && msgObj.nodeId == GlobalConfig.nodeId) {
this.changeHandUpStatus(msgObj);
}
} catch (err) {
loger.warn('chatMsg->JSON数据解析失败');
}
break;
case ApeConsts.USER_ACTION_SILENCE_STATUS_CHANGE:
let msgObj = null;
try {
msgObj = JSON.parse(chatMsg.message);
if (msgObj && msgObj.nodeId == GlobalConfig.nodeId) {
this.changeSilenceStatus(msgObj);
}
} catch (err) {
loger.warn('chatMsg->JSON数据解析失败');
}
break;
default:
break;
}
}
//-------------第三方消息------------------------------
//收到父级页面的消息,需要广播发送出去
onThirdReciveParentMessage(_msg) {
loger.log('收到页面的消息->广播给其他模块->', _msg);
this.sendThirdBroadcastData({ to: 0, message: _msg });
}
//发送第三方广播消息
sendThirdBroadcastData(_param){
loger.log("发送第三方广播消息->",_param);
if (this._classInfo == null || EngineUtils.isEmptyObject(this._classInfo)) {
loger.log('发送第三方广播消息->失败->SDK还未初始化数据!');
if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
}
return;
}
let thirdBroadcastSendPdu = new pdu['RCThirdSendBroadcastDataRequestPdu'];
thirdBroadcastSendPdu.type = pdu.RCPDU_THIRD_BROADCAST_DATA_REQUEST;
thirdBroadcastSendPdu.initiator = this._classInfo.nodeId;//发起人
thirdBroadcastSendPdu.peer = parseInt(_param.to)||0;//发送给谁,公聊的时候是0,私聊的时候是指定的用户id
thirdBroadcastSendPdu.isPublic = true;
thirdBroadcastSendPdu.message = this._rCArrayBufferUtil.strToUint8Array("h5" + _param.message);
if (!thirdBroadcastSendPdu.isPublic && 0 != thirdBroadcastSendPdu.peer) {
//发送给制定的人
this.send(thirdBroadcastSendPdu);
} else {
//发送给所有人
this.sendChatUniform(thirdBroadcastSendPdu);
}
}
//监听第三方消息通道消息
onThirdBroadcastDataHandler(_data){
//loger.log("监听第三方消息通道消息->",_data);
let thirdBroadcastReceivePdu = pdu['RCThirdSendBroadcastDataRequestPdu'].decode(_data);
let thirdMessage = {};
thirdMessage.fromNodeID = thirdBroadcastReceivePdu.initiator;
thirdMessage.toNodeID = thirdBroadcastReceivePdu.peer;
//loger.log("监听第三方消息通道消息->1", thirdMessage);
thirdMessage.message = this._rCArrayBufferUtil.uint8ArrayToStr(thirdBroadcastReceivePdu.message, 2);
loger.log("监听第三方消息通道消息->", thirdMessage);
if(this.thirdMessage){
this.thirdMessage.sendMessageToParent(thirdMessage.message);
}
}
//------------------第三方消息 end-----------------------------------------
onSendConferRecordRequestHandler(_data) {
try {
let conferRecordSendPdu = pdu['RCConferenceRecordRequestPdu'].decode(_data);
// {"initiator":820461225,"record":false,"classTime":3213,"filename":"h5dev/20170410/1437784290_20170410.rec"}
loger.log("录制回放控制操作成功->",conferRecordSendPdu);
if(conferRecordSendPdu&&conferRecordSendPdu.record==true||conferRecordSendPdu.record=="true"){
//每次开启录制的时候,需要把当前显示的文档数据更新一次,否则无法录制已经显示的文件
this._emit(MessageTypes.CLASS_RECORD_SUCCESS);
}
} catch (err) {
loger.warn("录制回放控制操作错误->", err.message);
}
}
rosterInsertHandler(nodeId, nodeData) {
//loger.log("人员进入--->");
if (GlobalConfig.nodeId == nodeId) {
} else {
// loger.log("有人加入 rosterInsertHandler");
this.rosterUpdateHandler(nodeId, nodeData);
sendThirdBroadcastData(_param) {
loger.log("发送第三方广播消息->", _param);
if (this._classInfo == null || EngineUtils.isEmptyObject(this._classInfo)) {
loger.log('发送第三方广播消息->失败->SDK还未初始化数据!');
if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
}
return;
}
let thirdBroadcastSendPdu = new pdu['RCThirdSendBroadcastDataRequestPdu'];
thirdBroadcastSendPdu.type = pdu.RCPDU_THIRD_BROADCAST_DATA_REQUEST;
thirdBroadcastSendPdu.initiator = this._classInfo.nodeId; //发起人
thirdBroadcastSendPdu.peer = parseInt(_param.to) || 0; //发送给谁,公聊的时候是0,私聊的时候是指定的用户id
thirdBroadcastSendPdu.isPublic = true;
thirdBroadcastSendPdu.message = this._rCArrayBufferUtil.strToUint8Array("h5" + _param.message);
if (!thirdBroadcastSendPdu.isPublic && 0 != thirdBroadcastSendPdu.peer) {
//发送给制定的人
this.send(thirdBroadcastSendPdu);
} else {
//发送给所有人
this.sendChatUniform(thirdBroadcastSendPdu);
}
}
//监听第三方消息通道消息
onThirdBroadcastDataHandler(_data) {
//loger.log("监听第三方消息通道消息->",_data);
let thirdBroadcastReceivePdu = pdu['RCThirdSendBroadcastDataRequestPdu'].decode(_data);
let thirdMessage = {};
thirdMessage.fromNodeID = thirdBroadcastReceivePdu.initiator;
thirdMessage.toNodeID = thirdBroadcastReceivePdu.peer;
//loger.log("监听第三方消息通道消息->1", thirdMessage);
thirdMessage.message = this._rCArrayBufferUtil.uint8ArrayToStr(thirdBroadcastReceivePdu.message, 2);
loger.log("监听第三方消息通道消息->", thirdMessage);
if (this.thirdMessage) {
this.thirdMessage.sendMessageToParent(thirdMessage.message);
}
}
//------------------第三方消息 end-----------------------------------------
onSendConferRecordRequestHandler(_data) {
try {
let conferRecordSendPdu = pdu['RCConferenceRecordRequestPdu'].decode(_data);
// {"initiator":820461225,"record":false,"classTime":3213,"filename":"h5dev/20170410/1437784290_20170410.rec"}
loger.log("录制回放控制操作成功->", conferRecordSendPdu);
if (conferRecordSendPdu && conferRecordSendPdu.record == true || conferRecordSendPdu.record == "true") {
//每次开启录制的时候,需要把当前显示的文档数据更新一次,否则无法录制已经显示的文件
this._emit(MessageTypes.CLASS_RECORD_SUCCESS);
}
} catch (err) {
loger.warn("录制回放控制操作错误->", err.message);
}
}
rosterInsertHandler(nodeId, nodeData) {
//loger.log("人员进入--->");
if (GlobalConfig.nodeId == nodeId) {
} else {
// loger.log("有人加入 rosterInsertHandler");
this.rosterUpdateHandler(nodeId, nodeData);
}
}
//更新人员列表数据
rosterUpdateHandler(nodeId, nodeData) {
nodeData.userRole = ApeConsts.userTypes[nodeData.role];
//如果是自己的信息,不处理跳过
if (nodeId == GlobalConfig.nodeId) {
//loger.log("自己加入课堂的消息->",nodeId,"role-->", nodeData.role, ApeConsts.userTypes[nodeData.role]);
//自己加入的时候,需要做一下判断操作,如果满足以下3个条件就要暂停课堂:
// 1.当前课堂只有自己;2.自己的身份不是host;3当前的课堂状态为(CLASS_STATUS_STARTED= 1;//直播中)
let rosterLen = Object.keys(this.rosters).length;
if (rosterLen < 1 && !GlobalConfig.isHost && GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
loger.warn("当前课堂没有老师->暂停课堂");
this.pauseClass({ isForce: true });
this.stopRecord(true);
}
}
//更新人员列表数据
rosterUpdateHandler(nodeId, nodeData) {
nodeData.userRole=ApeConsts.userTypes[nodeData.role];
//如果是自己的信息,不处理跳过
if (nodeId == GlobalConfig.nodeId) {
//loger.log("自己加入课堂的消息->",nodeId,"role-->", nodeData.role, ApeConsts.userTypes[nodeData.role]);
//自己加入的时候,需要做一下判断操作,如果满足以下3个条件就要暂停课堂:
// 1.当前课堂只有自己;2.自己的身份不是host;3当前的课堂状态为(CLASS_STATUS_STARTED= 1;//直播中)
let rosterLen=Object.keys(this.rosters).length;
if(rosterLen<1&&!GlobalConfig.isHost&&GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED){
loger.warn("当前课堂没有老师->暂停课堂");
this.pauseClass({isForce:true});
this.stopRecord(true);
}
//处理用户信息
this.unPackRosterInfo(nodeId,nodeData);
return;
}
//loger.log(nodeId, "加入课堂,role-->", nodeData.role, ApeConsts.userTypes[nodeData.role]);
//新加入的人员不是自己
//1.判断进入的用户身份,如果进入的人身份是host,助教,监课,并且和自己的身份冲突,自己会被踢掉
//2.最后进入的人会踢掉之前进入的人,nodeId是按时间戳生成的,最后进入的人nodeId的值比之前进入的人大
if (parseInt(nodeId) > GlobalConfig.nodeId) {
if (nodeData.role == ApeConsts.NR_HOST && GlobalConfig.isHost) {
this.kickOutRoster();
return;
}else if(nodeData.userId==GlobalConfig.userId&&GlobalConfig.userId!="0"){
loger.log("异地登陆->userId->",GlobalConfig.userId);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_REMOTE_LANDING);
this._emit(MessageTypes.CLASS_RUN_EXIT,{'type':1});
}
}
/*if (parseInt(nodeId) > GlobalConfig.nodeId) {
if (nodeData.role == ApeConsts.NR_HOST && GlobalConfig.isHost) {
this.kickOutRoster();
return;
} else if (nodeData.role == ApeConsts.NR_PRESENTER && GlobalConfig.isPresenter) {
this.kickOutRoster();
return;
} else if (nodeData.role == ApeConsts.NR_ASSISTANT && GlobalConfig.isAssistant) {
this.kickOutRoster();
return;
} else if (nodeData.role == ApeConsts.NR_INVISIBLE && GlobalConfig.isInvisible) {
this.kickOutRoster();
return;
}else if(nodeData.userId==GlobalConfig.userId&&GlobalConfig.userId!="0"){
loger.log("异地登陆->userId->",GlobalConfig.userId);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_REMOTE_LANDING);
this._emit(MessageTypes.CLASS_RUN_EXIT,{'type':1});
}
}*/
//处理用户信息
this.unPackRosterInfo(nodeId,nodeData);
this.unPackRosterInfo(nodeId, nodeData);
return;
}
//loger.log(nodeId, "加入课堂,role-->", nodeData.role, ApeConsts.userTypes[nodeData.role]);
//新加入的人员不是自己
//1.判断进入的用户身份,如果进入的人身份是host,助教,监课,并且和自己的身份冲突,自己会被踢掉
//2.最后进入的人会踢掉之前进入的人,nodeId是按时间戳生成的,最后进入的人nodeId的值比之前进入的人大
if (parseInt(nodeId) > GlobalConfig.nodeId) {
if (nodeData.role == ApeConsts.NR_HOST && GlobalConfig.isHost) {
this.kickOutRoster();
return;
} else if (nodeData.userId == GlobalConfig.userId && GlobalConfig.userId != "0") {
loger.log("异地登陆->userId->", GlobalConfig.userId);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_REMOTE_LANDING);
this._emit(MessageTypes.CLASS_RUN_EXIT, { 'type': 1 });
}
}
/*if (parseInt(nodeId) > GlobalConfig.nodeId) {
if (nodeData.role == ApeConsts.NR_HOST && GlobalConfig.isHost) {
this.kickOutRoster();
return;
} else if (nodeData.role == ApeConsts.NR_PRESENTER && GlobalConfig.isPresenter) {
this.kickOutRoster();
return;
} else if (nodeData.role == ApeConsts.NR_ASSISTANT && GlobalConfig.isAssistant) {
this.kickOutRoster();
return;
} else if (nodeData.role == ApeConsts.NR_INVISIBLE && GlobalConfig.isInvisible) {
this.kickOutRoster();
return;
}else if(nodeData.userId==GlobalConfig.userId&&GlobalConfig.userId!="0"){
loger.log("异地登陆->userId->",GlobalConfig.userId);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_REMOTE_LANDING);
this._emit(MessageTypes.CLASS_RUN_EXIT,{'type':1});
}
}*/
//处理用户信息
this.unPackRosterInfo(nodeId, nodeData);
}
//处理用户信息
unPackRosterInfo(nodeId,nodeData){
let rosterExists = this.rosters[nodeId];
this.rosters[nodeId] = nodeData;
let userDataObj = null;
try {
userDataObj = pdu['RCNodeInfoUserDataPdu'].decode(nodeData.userData);
} catch (err) {
loger.log("RCNodeInfoUserDataPdu decode err", err.message);
}
let newNodeData = nodeData;
newNodeData.userData = userDataObj;
//如果是监课,不告诉其他人
if (nodeData.role == ApeConsts.NR_INVISIBLE&&GlobalConfig.userRole!=ApeConsts.invisible) {
loger.log("NR_INVISIBLE");
return;
}
if (!rosterExists) {
loger.log("人员加入->",newNodeData);
this._emit(MessageTypes.CLASS_INSERT_ROSTER, {"nodeId": nodeId, "nodeData": newNodeData});
this.emitRosterChange();
} else {
//loger.log("更新人员列表数据,rosterExists已经存在",rosterExists);
loger.log("人员更新信息->",newNodeData);
this._emit(MessageTypes.CLASS_UPDATE_ROSTER, {"nodeId": nodeId, "nodeData": newNodeData});
}
}
//踢出用户
kickOutRoster() {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_KICK_OUT);
this._emit(MessageTypes.CLASS_RUN_EXIT,{'type':1});
}
//视频模块发生更新,人员状态需要更新
updaterRosterStatus(_param) {
//loger.log("媒体模块发生更新,人员状态需要更新,fromNodeId->",_param);
//如果视频消息中channel的占用人 fromNodeId在人员列表中不存在,需要释放这channel,因为这个有可能是之前没释放成功的
if (_param && _param.status == ApeConsts.CHANNEL_STATUS_OPENING && this.rosters[_param.fromNodeId] == null) {
loger.log("媒体模块被占用->占有人已经不存在课堂中->释放->", _param);
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": _param.fromNodeId});
}
/* if (_param && _param.status == ApeConsts.CHANNEL_STATUS_OPENING) {
if(this.rosters[_param.fromNodeId] == null){
loger.log("媒体模块被占用,占有人已经不存在课堂中,释放Channel,_param->", _param);
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": _param.fromNodeId});
}
//如果音视频消息是自己的,需要设置麦克风和摄像头状态
if(_param.fromNodeId==GlobalConfig.nodeId){
if(_param.mediaId==ApeConsts.MEDIA_TYPE_AUDIO){
GlobalConfig.openMicrophones=EngineUtils.creatTimestamp();
GlobalConfig.openCamera=0;
}else {
GlobalConfig.openCamera=EngineUtils.creatTimestamp();
GlobalConfig.openMicrophones=GlobalConfig.openCamera;
}
this.updateUserInfo();
}
}else if (_param && _param.status == ApeConsts.CHANNEL_STATUS_RELEASED) {
//如果音视频消息是自己的,需要设置麦克风和摄像头状态
if(_param.fromNodeId==GlobalConfig.nodeId){
GlobalConfig.openCamera=0;
GlobalConfig.openMicrophones=0;
this.updateUserInfo();
}
}*/
unPackRosterInfo(nodeId, nodeData) {
let rosterExists = this.rosters[nodeId];
this.rosters[nodeId] = nodeData;
let userDataObj = null;
try {
userDataObj = pdu['RCNodeInfoUserDataPdu'].decode(nodeData.userData);
} catch (err) {
loger.log("RCNodeInfoUserDataPdu decode err", err.message);
}
let newNodeData = nodeData;
newNodeData.userData = userDataObj;
//如果是监课,不告诉其他人
if (nodeData.role == ApeConsts.NR_INVISIBLE && GlobalConfig.userRole != ApeConsts.invisible) {
loger.log("NR_INVISIBLE");
return;
}
if (!rosterExists) {
loger.log("人员加入->", newNodeData);
this._emit(MessageTypes.CLASS_INSERT_ROSTER, { "nodeId": nodeId, "nodeData": newNodeData });
this.emitRosterChange();
} else {
//loger.log("更新人员列表数据,rosterExists已经存在",rosterExists);
loger.log("人员更新信息->", newNodeData);
this._emit(MessageTypes.CLASS_UPDATE_ROSTER, { "nodeId": nodeId, "nodeData": newNodeData });
}
}
//踢出用户
kickOutRoster() {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_KICK_OUT);
this._emit(MessageTypes.CLASS_RUN_EXIT, { 'type': 1 });
}
//视频模块发生更新,人员状态需要更新
updaterRosterStatus(_param) {
//loger.log("媒体模块发生更新,人员状态需要更新,fromNodeId->",_param);
//如果视频消息中channel的占用人 fromNodeId在人员列表中不存在,需要释放这channel,因为这个有可能是之前没释放成功的
if (_param && _param.status == ApeConsts.CHANNEL_STATUS_OPENING && this.rosters[_param.fromNodeId] == null) {
loger.log("媒体模块被占用->占有人已经不存在课堂中->释放->", _param);
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, { "nodeId": _param.fromNodeId });
}
/* if (_param && _param.status == ApeConsts.CHANNEL_STATUS_OPENING) {
if(this.rosters[_param.fromNodeId] == null){
loger.log("媒体模块被占用,占有人已经不存在课堂中,释放Channel,_param->", _param);
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": _param.fromNodeId});
}
//如果音视频消息是自己的,需要设置麦克风和摄像头状态
if(_param.fromNodeId==GlobalConfig.nodeId){
if(_param.mediaId==ApeConsts.MEDIA_TYPE_AUDIO){
GlobalConfig.openMicrophones=EngineUtils.creatTimestamp();
GlobalConfig.openCamera=0;
}else {
GlobalConfig.openCamera=EngineUtils.creatTimestamp();
GlobalConfig.openMicrophones=GlobalConfig.openCamera;
}
this.updateUserInfo();
}
}else if (_param && _param.status == ApeConsts.CHANNEL_STATUS_RELEASED) {
//如果音视频消息是自己的,需要设置麦克风和摄像头状态
if(_param.fromNodeId==GlobalConfig.nodeId){
GlobalConfig.openCamera=0;
GlobalConfig.openMicrophones=0;
this.updateUserInfo();
}
}*/
}
//设备状态更新
updaterUserDeviecStatusChange(_data){
loger.log("音视频设备状态更新->",_data);
this.updateUserInfo();
}
//删除用户
rosterDelHandler(nodeId) {
if (GlobalConfig.nodeId == nodeId) {
loger.log("自己离开课堂");
// 自己退出
this._emit(MessageTypes.CLASS_RUN_EXIT,{'type':0});
updaterUserDeviecStatusChange(_data) {
loger.log("音视频设备状态更新->", _data);
this.updateUserInfo();
}
//删除用户
rosterDelHandler(nodeId) {
if (GlobalConfig.nodeId == nodeId) {
loger.log("自己离开课堂");
// 自己退出
this._emit(MessageTypes.CLASS_RUN_EXIT, { 'type': 0 });
} else {
let user = this.rosters[nodeId];
if (user) {
loger.log(nodeId, "->离开课堂->身份->", user.role);
}
delete this.rosters[nodeId];
this.emitRosterChange();
this._emit(MessageTypes.CLASS_DELETE_ROSTER, { "nodeId": nodeId });
//当前人员列表中抽一个人来检查离开人员是否占用频道
for (let key in this.rosters) {
let randNodeId = parseInt(key);
//如果抽到的人是自己就处理以下操作
if (randNodeId == GlobalConfig.nodeId) {
loger.log(randNodeId, "有权限检查离开的人员是否占用channel");
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, { "nodeId": nodeId });
//如果离开的人员是老师,需要暂停当前的课堂
if (user && user.role == ApeConsts.NR_HOST) {
this.pauseClass();
//强制停止录制
this.stopRecord(true);
}
} else {
let user=this.rosters[nodeId];
if(user){
loger.log(nodeId, "->离开课堂->身份->",user.role);
}
delete this.rosters[nodeId];
this.emitRosterChange();
this._emit(MessageTypes.CLASS_DELETE_ROSTER, {"nodeId": nodeId});
//当前人员列表中抽一个人来检查离开人员是否占用频道
for (let key in this.rosters) {
let randNodeId = parseInt(key);
//如果抽到的人是自己就处理以下操作
if (randNodeId == GlobalConfig.nodeId) {
loger.log(randNodeId, "有权限检查离开的人员是否占用channel");
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": nodeId});
//如果离开的人员是老师,需要暂停当前的课堂
if(user&&user.role==ApeConsts.NR_HOST){
this.pauseClass();
//强制停止录制
this.stopRecord(true);
}
} else {
loger.warn(GlobalConfig.nodeId, "没有权限检查离开的人员是否占用channel");
}
//查找到一个就跳出操作
return;
}
}
}
//广播当前的人数
emitRosterChange() {
this._emit(MessageTypes.CLASS_UPDATE_ROSTER_NUM, Object.keys(this.rosters).length);
}
///////数据的封包和解包/////////////////////////////////////////
packPdu(_param, _itemIdx) {
loger.log("课堂===packPdu ");
//验证坐标点集合数组是否合法
if (_param == null || _itemIdx == null) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
let classStatusInfo = new pdu['RCClassStatusInfoPdu'];
classStatusInfo.nodeId = GlobalConfig.nodeId;//mcu中的唯一ID
classStatusInfo.userId = GlobalConfig.userId;
classStatusInfo.userName = GlobalConfig.userName;
classStatusInfo.siteId = GlobalConfig.siteId;//站点号
classStatusInfo.classId = GlobalConfig.classId;
classStatusInfo.className = GlobalConfig.className;
classStatusInfo.classType = GlobalConfig.classType;//课堂类型
classStatusInfo.classStatus = GlobalConfig.classStatus;//课堂的状态
classStatusInfo.classStartTime = GlobalConfig.classStartTime;//课堂点击开始时间
classStatusInfo.classStopTime = GlobalConfig.classStopTime;//最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
classStatusInfo.classTimestamp = GlobalConfig.classTimestamp;//相对于点开始课堂的时间戳
classStatusInfo.classBeginTime = GlobalConfig.classBeginTime;//课堂创建的时间,这个是Sass返回的
classStatusInfo.classEndTime = GlobalConfig.classEndTime;//课堂结束的时间,这个是Sass返回的
classStatusInfo.recordStatus = GlobalConfig.recordStatus;//当前录制状态
classStatusInfo.recordTimestamp = GlobalConfig.recordTimestamp;//相对于首次开始录制的时间戳
classStatusInfo.recordFileName = GlobalConfig.recordFileName;//录制的文件名
classStatusInfo.recordDownloadUrl = GlobalConfig.recordDownloadUrl;//下载地址
classStatusInfo.serverTimestamp = GlobalConfig.serverTimestamp;//当前的系统时间戳
classStatusInfo.activeDocId = GlobalConfig.activeDocId;//当前激活的文档id
classStatusInfo.activeDocCurPage = GlobalConfig.activeDocCurPage;//当前激活的文档的当前页
classStatusInfo.isStopAllPublishMedia=_param.isStopAllPublishMedia||false;
classStatusInfo.currentSceneTableId=GlobalConfig.currentSceneTableId;
//loger.log("classStatusInfo--->", classStatusInfo);
/*
optional uint32 item_idx=1;
optional uint32 from=2;
optional uint32 owner=3;
optional uint32 action_type=4;//状态改变的类型
optional RCClassStatusInfoPdu class_status_info=5;//当前课堂状态的信息
*/
//判断type类型,根据type设置不同的参数
let modelPdu = new pdu['RCClassSendDataModelPdu'];
modelPdu.itemIdx = _itemIdx;
modelPdu.from = GlobalConfig.nodeId;
modelPdu.owner = GlobalConfig.nodeId;
//modelPdu.actionType =_param.actionType;
modelPdu.classStatusInfo = classStatusInfo;
return modelPdu;
}
unPackPdu(owner, itemIdx, itemData) {
loger.log("课堂数据->unPackPdu ");
if (owner == null || itemIdx == null || itemData == null) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
try {
let modelPdu = pdu['RCClassSendDataModelPdu'].decode(itemData);
return modelPdu;
} catch (err) {
loger.log("课堂收到数据 unPackPdu Pdu解析错误,itemIdx=" + itemIdx + " err:" + err.message);
}
return null;
}
loger.warn(GlobalConfig.nodeId, "没有权限检查离开的人员是否占用channel");
}
//查找到一个就跳出操作
return;
}
}
}
//广播当前的人数
emitRosterChange() {
this._emit(MessageTypes.CLASS_UPDATE_ROSTER_NUM, Object.keys(this.rosters).length);
}
///////数据的封包和解包/////////////////////////////////////////
packPdu(_param, _itemIdx) {
loger.log("课堂===packPdu ");
//验证坐标点集合数组是否合法
if (_param == null || _itemIdx == null) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
let classStatusInfo = new pdu['RCClassStatusInfoPdu'];
classStatusInfo.nodeId = GlobalConfig.nodeId; //mcu中的唯一ID
classStatusInfo.userId = GlobalConfig.userId;
classStatusInfo.userName = GlobalConfig.userName;
classStatusInfo.siteId = GlobalConfig.siteId; //站点号
classStatusInfo.classId = GlobalConfig.classId;
classStatusInfo.className = GlobalConfig.className;
classStatusInfo.classType = GlobalConfig.classType; //课堂类型
classStatusInfo.classStatus = GlobalConfig.classStatus; //课堂的状态
classStatusInfo.classStartTime = GlobalConfig.classStartTime; //课堂点击开始时间
classStatusInfo.classStopTime = GlobalConfig.classStopTime; //最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
classStatusInfo.classTimestamp = GlobalConfig.classTimestamp; //相对于点开始课堂的时间戳
classStatusInfo.classBeginTime = GlobalConfig.classBeginTime; //课堂创建的时间,这个是Sass返回的
classStatusInfo.classEndTime = GlobalConfig.classEndTime; //课堂结束的时间,这个是Sass返回的
classStatusInfo.recordStatus = GlobalConfig.recordStatus; //当前录制状态
classStatusInfo.recordTimestamp = GlobalConfig.recordTimestamp; //相对于首次开始录制的时间戳
classStatusInfo.recordFileName = GlobalConfig.recordFileName; //录制的文件名
classStatusInfo.recordDownloadUrl = GlobalConfig.recordDownloadUrl; //下载地址
classStatusInfo.serverTimestamp = GlobalConfig.serverTimestamp; //当前的系统时间戳
classStatusInfo.activeDocId = GlobalConfig.activeDocId; //当前激活的文档id
classStatusInfo.activeDocCurPage = GlobalConfig.activeDocCurPage; //当前激活的文档的当前页
classStatusInfo.isStopAllPublishMedia = _param.isStopAllPublishMedia || false;
classStatusInfo.currentSceneTableId = GlobalConfig.currentSceneTableId;
classStatusInfo.silence = GlobalConfig.silence;
//loger.log("classStatusInfo--->", classStatusInfo);
/*
optional uint32 item_idx=1;
optional uint32 from=2;
optional uint32 owner=3;
optional uint32 action_type=4;//状态改变的类型
optional RCClassStatusInfoPdu class_status_info=5;//当前课堂状态的信息
*/
//判断type类型,根据type设置不同的参数
let modelPdu = new pdu['RCClassSendDataModelPdu'];
modelPdu.itemIdx = _itemIdx;
modelPdu.from = GlobalConfig.nodeId;
modelPdu.owner = GlobalConfig.nodeId;
//modelPdu.actionType =_param.actionType;
modelPdu.classStatusInfo = classStatusInfo;
return modelPdu;
}
unPackPdu(owner, itemIdx, itemData) {
loger.log("课堂数据->unPackPdu ");
if (owner == null || itemIdx == null || itemData == null) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
try {
let modelPdu = pdu['RCClassSendDataModelPdu'].decode(itemData);
return modelPdu;
} catch (err) {
loger.log("课堂收到数据 unPackPdu Pdu解析错误,itemIdx=" + itemIdx + " err:" + err.message);
}
return null;
}
}
... ...
... ... @@ -896,6 +896,7 @@ message RCNodeInfoRecordPdu {
optional string province=27;
optional string isp=28;
repeated MsListItemPdu msList = 29;
optional string selfSilence = 30;
}
message RCVotingPollSettingsPdu {
... ... @@ -991,6 +992,7 @@ message RCClassStatusInfoPdu {
optional uint32 active_doc_cur_page=21;//当前激活的文档的当前页
optional bool isStopAllPublishMedia=22;//是否停止推流
optional uint32 currentSceneTableId=23;//文档区域的当前模块id
optional bool silence=24;//课堂禁言
}
message RCConferenceRecordRequestPdu {
... ...