李勇

1.增加聊天模块支持图片消息;2.增加踢人接口;3.修改CDN地址和m3u8地址拼接规则

... ... @@ -35,7 +35,7 @@ import QuestionApe from 'apes/QuestionApe';
import UTF8 from 'utf-8';
let loger = Loger.getLoger('McuClient');
let _sdkInfo = { "version": "v1.48.2.20170723", "author": "www.3mang.com" };
let _sdkInfo = { "version": "v1.49.1.20170724", "author": "www.3mang.com" };
//APE
let _sass;
... ... @@ -164,7 +164,9 @@ export default class MessageEntrance extends Emiter {
this.controlHandUpStatus = this._controlHandUpStatus.bind(this); //控制别人的举手状态
this.controlSilenceStatus = this._controlSilenceStatus.bind(this); //改变禁言状态
this.sceneTableChange = this._sceneTableChange.bind(this); //控制别人的举手状态
this.sceneTableChange = this._sceneTableChange.bind(this); //切换模块显示
this.kickOutRosterFormNodeId= this._kickOutRosterFormNodeId.bind(this); //把指定nodeId的人踢出课堂
//录制回放
this.initRecordPlayback = this._initRecordPlayback.bind(this);
... ... @@ -433,7 +435,8 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.portal = _param.portal;
GlobalConfig.isH5=_param.isH5||false;//外部传入的参数,是否是H5
if(GlobalConfig.isH5==true){
GlobalConfig.platform = 3;//3是H5
GlobalConfig.platform = "H5";
GlobalConfig.deviceType=3//3是H5
loger.warn("设备类型是H5");
}
//GlobalConfig.userId = _param.userId || "0";
... ... @@ -1054,6 +1057,17 @@ export default class MessageEntrance extends Emiter {
}
}
//将指定nodeId的人踢出课堂
_kickOutRosterFormNodeId(_param){
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return { "code": ApeConsts.RETURN_FAILED, "data": "" };
}
if (_confer_ape) {
_confer_ape.kickOutRosterFormNodeId(_param);
}
}
// 禁言控制
_controlSilenceStatus(_param) {
if (!_mcu.connected) {
... ... @@ -1244,7 +1258,8 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.MS_PLAY_HLS_IP = ipItem; //ip包含了端口
GlobalConfig.MS_PLAY_HLS_PORT = "";
loger.log('videoCDNAddr>初始->MSHls', GlobalConfig.MS_PLAY_HLS_IP);
} else if (ipItem.indexOf('rtmppull') >= 0) {
}
if (ipItem.indexOf('rtmppull')>= 0) {
//直播的时候rtmp拉流地址
GlobalConfig.MS_PLAY_RTMP_IP = ipItem; //ip包含了端口
GlobalConfig.MS_PLAY_RTMP_PORT = '';
... ... @@ -1838,12 +1853,12 @@ export default class MessageEntrance extends Emiter {
//音乐共享模块加入频道成功,同步到MCU服务器上的数据
musicShareApeJoinChannelSuccess() {
loger.log("伴音MUSIC模块加入频道成功->isHost=", GlobalConfig.isHost, "length=", GlobalConfig.sharedMusicList.length);
console.log("伴音MUSIC模块共享模数据->", GlobalConfig.sharedMusicList);
loger.log("伴音MUSIC模块加入频道成功->isHost=", GlobalConfig.isHost, "length=", GlobalConfig.musicListPrepare.length);
console.log("伴音MUSIC模块共享模数据->", GlobalConfig.musicListPrepare);
//如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传
if (GlobalConfig.isHost && GlobalConfig.sharedMusicList.length > 0) {
for (let i = 0; i < GlobalConfig.sharedMusicList.length; i++) {
let value = GlobalConfig.sharedMusicList[i];
if (GlobalConfig.isHost && GlobalConfig.musicListPrepare.length > 0) {
for (let i = 0; i < GlobalConfig.musicListPrepare.length; i++) {
let value = GlobalConfig.musicListPrepare[i];
if (value) {
let paramInfo = {
"status": 0,
... ...
... ... @@ -24,6 +24,7 @@ ApeConsts.CLASS_PAUSING = "class.update"; //更新当前的状态信息
ApeConsts.CLASS_ACTION_CLOSE_ALL = 1; //所有人关闭课堂
ApeConsts.CLASS_ACTION_HANDUP_STATUS_CHANGE = 2; //更改用户的举手状态
ApeConsts.USER_ACTION_SILENCE_STATUS_CHANGE = 3; //更改用户的禁言状态
ApeConsts.CLASS_ACTION_KICK_OUT_ROSTER=4; //指定的人踢出课堂
//课堂类型 1:1v1(2路流) 2:直播(1路流) 3:小班课(可以多路流)
ApeConsts.CLASS_TYPE_1 = 1; // 互动课堂,通过MS转发音视频,不能进行H5观看 1v1(2路流)
... ...
... ... @@ -58,6 +58,7 @@ class ChatApe extends Ape {
chatSendPdu.initiator = this._classInfo.nodeId;//发起人
chatSendPdu.peer = parseInt(_messageInfo.to);//发送给谁,公聊的时候是0,私聊的时候是指定的用户id
chatSendPdu.msgType=parseInt(_messageInfo.msgType)||0;
chatSendPdu.userData = this._rCArrayBufferUtil.strToUint8Array("h5" + _messageInfo.message);
chatSendPdu.fromName = this._rCArrayBufferUtil.strToUint8Array("h5" + this._classInfo.userName);
chatSendPdu.fromRole = this._classInfo.userRole;// classRole已经废弃
... ...
... ... @@ -91,6 +91,7 @@ class ConferApe extends Ape {
adapterPdu.item.push(adapterItemPdu);
this.sendUniform(adapterPdu, true);
}
//获取角色信息
getNodeInfo() {
let nodeInfoRecordPdu = new pdu['RCNodeInfoRecordPdu'];
... ... @@ -225,7 +226,7 @@ class ConferApe extends Ape {
sendConferRecordMsg(_param) {
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return { "code": ApeConsts.RETURN_FAILED, "data": "已经断开连接" };
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
if (_param == null) {
loger.warn("控制录制状的消息发送失败,参数错误", _param);
... ... @@ -269,7 +270,7 @@ class ConferApe extends Ape {
//如果是host
if (GlobalConfig.isHost) {
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.sendConferRecordMsg({ "recordStatus": true });
this.sendConferRecordMsg({"recordStatus": true});
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this._emit(MessageTypes.CLASS_RECORD_START); //课堂开始录制
}
... ... @@ -282,14 +283,14 @@ class ConferApe extends Ape {
//强制停止,可以是host之外的身份(比如当前课堂老师异常退出,没有老师,会随机选择一个人来做释放操作)
if (GlobalConfig.recordStatus) {
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.sendConferRecordMsg({ "recordStatus": false });
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.sendConferRecordMsg({"recordStatus": false});
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
}
}
... ... @@ -336,7 +337,7 @@ class ConferApe extends Ape {
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.stopRecord();
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this.sendUpdaterClassStatusInfo({ "actionType": 0, isStopAllPublishMedia: true });
this.sendUpdaterClassStatusInfo({"actionType": 0, isStopAllPublishMedia: true});
loger.log('restorClass');
}
... ... @@ -378,7 +379,7 @@ class ConferApe extends Ape {
//课堂状态改变
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//同步课堂状态
this.sendUpdaterClassStatusInfo({ "actionType": 1, isStopAllPublishMedia: true });
this.sendUpdaterClassStatusInfo({"actionType": 1, isStopAllPublishMedia: true});
//开始计时
this.startTimerCounter();
... ... @@ -398,7 +399,7 @@ class ConferApe extends Ape {
this.stopRecord();
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE, _param);
this.sendUpdaterClassStatusInfo({ "actionType": 2, isStopAllPublishMedia: true });
this.sendUpdaterClassStatusInfo({"actionType": 2, isStopAllPublishMedia: true});
this.stopTimerCounter();
}
... ... @@ -412,8 +413,9 @@ class ConferApe extends Ape {
this.stopTimerCounter();
this.restorClass();
//把所有人都踢出课堂
this.sendConferMsg({ "to": 0, "message": "所有人退出课堂", "actionType": ApeConsts.CLASS_ACTION_CLOSE_ALL });
this.sendConferMsg({"to": 0, "message": "所有人退出课堂", "actionType": ApeConsts.CLASS_ACTION_CLOSE_ALL});
}
//更新设备信息
updateDeviceInfo(_param) {
loger.log('更新用户的设备信息->', _param);
... ... @@ -434,7 +436,7 @@ class ConferApe extends Ape {
GlobalConfig.silenceUsers[_param.userId || _param.nodeId] = _param;
}
this.sendUpdaterClassStatusInfo({ silenceUsers: GlobalConfig.silenceUsers });
this.sendUpdaterClassStatusInfo({silenceUsers: GlobalConfig.silenceUsers});
}
changeSilenceStatus(_param) {
... ... @@ -443,6 +445,24 @@ class ConferApe extends Ape {
this.updateUserInfo();
}
//将指定nodeId的人踢出课堂
kickOutRosterFormNodeId(_param) {
if(GlobalConfig.isNormal){
loger.warn("普通身份没有踢人的权限");
return;
}
if (_param && _param.nodeId) {
this.sendConferMsg({
"to": parseInt(_param.nodeId),
"message": "" + _param.nodeId + "踢出课堂",
"actionType": ApeConsts.CLASS_ACTION_KICK_OUT_ROSTER
});
} else {
loger.warn("踢人失败-参数无效")
console.log(_param);
}
}
//控制举手状态
controlHandUpStatus(_param) {
//控制用户的举手状态
... ... @@ -456,7 +476,11 @@ class ConferApe extends Ape {
if (_param && _param.isHandUp == true) {
msgObj.isHandUp = true;
}
this.sendConferMsg({ "to": _param.nodeId, "message": JSON.stringify(msgObj), "actionType": ApeConsts.CLASS_ACTION_HANDUP_STATUS_CHANGE });
this.sendConferMsg({
"to": _param.nodeId,
"message": JSON.stringify(msgObj),
"actionType": ApeConsts.CLASS_ACTION_HANDUP_STATUS_CHANGE
});
}
//切换举手状态
... ... @@ -470,6 +494,7 @@ class ConferApe extends Ape {
}
this.updateUserInfo();
}
//课堂的场景模块发送改变
sceneTableChange(_param) {
if (GlobalConfig.isRecordPlayBack) {
... ... @@ -483,7 +508,7 @@ class ConferApe extends Ape {
//保存数据到Sass
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//同步消息给其他人
this.sendUpdaterClassStatusInfo({ "actionType": 1, isStopAllPublishMedia: false });
this.sendUpdaterClassStatusInfo({"actionType": 1, isStopAllPublishMedia: false});
}
}
... ... @@ -550,8 +575,7 @@ class ConferApe extends Ape {
//如果是host ,开始录制
this.startRecord();
} else if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT &&
GlobalConfig.isHost && GlobalConfig.isAutoStartClass &&
!GlobalConfig.isRecordPlayBack) {
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);
... ... @@ -593,7 +617,7 @@ class ConferApe extends Ape {
GlobalConfig.recordTimestamp = GlobalConfig.recordTimestamp + 1;
}
//loger.log('课堂进行时间',GlobalConfig.classTimestamp);
this._emit(MessageTypes.CLASS_UPDATE_TIMER, { "classTimestamp": GlobalConfig.classTimestamp });
this._emit(MessageTypes.CLASS_UPDATE_TIMER, {"classTimestamp": GlobalConfig.classTimestamp});
if (GlobalConfig.classTimestamp % GlobalConfig.updateClassInfoDelay == 0) {
//如果是host身份,需要同步时间给其他人,同时把当前的状态上传到服务器
... ... @@ -602,7 +626,7 @@ class ConferApe extends Ape {
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//同步消息给其他人
this.sendUpdaterClassStatusInfo({ "actionType": 1, isStopAllPublishMedia: false });
this.sendUpdaterClassStatusInfo({"actionType": 1, isStopAllPublishMedia: false});
}
}
... ... @@ -619,9 +643,9 @@ class ConferApe extends Ape {
//处理课堂更新的信息
if (model && model.classStatusInfo) {
try{
model.classStatusInfo.silenceUsers=JSON.parse( model.classStatusInfo.silenceUsers);
}catch (err){
try {
model.classStatusInfo.silenceUsers = JSON.parse(model.classStatusInfo.silenceUsers);
} catch (err) {
}
... ... @@ -670,15 +694,21 @@ class ConferApe extends Ape {
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}
loger.log("课堂控制消息", 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 });
this._emit(MessageTypes.CLASS_RUN_EXIT, {'type': 1});
break;
case ApeConsts.CLASS_ACTION_KICK_OUT_ROSTER:
if (chatMsg.toNodeID == GlobalConfig.nodeId) {
//自己被踢出课堂
this._emit(MessageTypes.CLASS_RUN_EXIT, {'type': 2});
}
break;
case ApeConsts.CLASS_ACTION_HANDUP_STATUS_CHANGE:
console.log('chatMsg', chatMsg);
//console.log('chatMsg', chatMsg);
let msgObj = null;
try {
msgObj = JSON.parse(chatMsg.message);
... ... @@ -709,8 +739,9 @@ class ConferApe extends Ape {
//收到父级页面的消息,需要广播发送出去
onThirdReciveParentMessage(_msg) {
loger.log('收到页面的消息->广播给其他模块->', _msg);
this.sendThirdBroadcastData({ to: 0, message: _msg });
this.sendThirdBroadcastData({to: 0, message: _msg});
}
//发送第三方广播消息
sendThirdBroadcastData(_param) {
loger.log("发送第三方广播消息->", _param);
... ... @@ -790,10 +821,10 @@ class ConferApe extends Ape {
//自己加入的时候,需要做一下判断操作,如果满足以下3个条件就要暂停课堂:
// 1.当前课堂只有自己;2.自己的身份不是host;3当前的课堂状态为(CLASS_STATUS_STARTED= 1;//直播中)
let rosterLen = Object.keys(this.rosters).length;
GlobalConfig.rosterNumber=rosterLen;//记录当前的总人数
GlobalConfig.rosterNumber = rosterLen;//记录当前的总人数
if (rosterLen < 1 && !GlobalConfig.isHost && GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
loger.warn("当前课堂没有老师->暂停课堂");
this.pauseClass({ isForce: true });
this.pauseClass({isForce: true});
this.stopRecord(true);
}
//处理用户信息
... ... @@ -813,7 +844,7 @@ class ConferApe extends Ape {
} 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._emit(MessageTypes.CLASS_RUN_EXIT, {'type': 1});
}
}
/*if (parseInt(nodeId) > GlobalConfig.nodeId) {
... ... @@ -839,6 +870,7 @@ class ConferApe extends Ape {
//处理用户信息
this.unPackRosterInfo(nodeId, nodeData);
}
//处理用户信息
unPackRosterInfo(nodeId, nodeData) {
let rosterExists = this.rosters[nodeId];
... ... @@ -859,13 +891,13 @@ class ConferApe extends Ape {
}
if (!rosterExists) {
loger.log("人员加入->", newNodeData);
this._emit(MessageTypes.CLASS_INSERT_ROSTER, { "nodeId": nodeId, "nodeData": 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 });
this._emit(MessageTypes.CLASS_UPDATE_ROSTER, {"nodeId": nodeId, "nodeData": newNodeData});
}
}
... ... @@ -873,7 +905,7 @@ class ConferApe extends Ape {
//踢出用户
kickOutRoster() {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_KICK_OUT);
this._emit(MessageTypes.CLASS_RUN_EXIT, { 'type': 1 });
this._emit(MessageTypes.CLASS_RUN_EXIT, {'type': 1});
}
//视频模块发生更新,人员状态需要更新
... ... @@ -882,7 +914,7 @@ class ConferApe extends Ape {
//如果视频消息中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 });
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": _param.fromNodeId});
}
/* if (_param && _param.status == ApeConsts.CHANNEL_STATUS_OPENING) {
... ... @@ -912,6 +944,7 @@ class ConferApe extends Ape {
}
}*/
}
//设备状态更新
updaterUserDeviecStatusChange(_data) {
loger.log("音视频设备状态更新->", _data);
... ... @@ -923,7 +956,7 @@ class ConferApe extends Ape {
if (GlobalConfig.nodeId == nodeId) {
loger.log("自己离开课堂");
// 自己退出
this._emit(MessageTypes.CLASS_RUN_EXIT, { 'type': 0 });
this._emit(MessageTypes.CLASS_RUN_EXIT, {'type': 0});
} else {
let user = this.rosters[nodeId];
if (user) {
... ... @@ -931,7 +964,7 @@ class ConferApe extends Ape {
}
delete this.rosters[nodeId];
this.emitRosterChange();
this._emit(MessageTypes.CLASS_DELETE_ROSTER, { "nodeId": nodeId });
this._emit(MessageTypes.CLASS_DELETE_ROSTER, {"nodeId": nodeId});
//当前人员列表中抽一个人来检查离开人员是否占用频道
for (let key in this.rosters) {
... ... @@ -939,7 +972,7 @@ class ConferApe extends Ape {
//如果抽到的人是自己就处理以下操作
if (randNodeId == GlobalConfig.nodeId) {
loger.log(randNodeId, "有权限检查离开的人员是否占用channel");
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, { "nodeId": nodeId });
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": nodeId});
//如果离开的人员是老师,需要暂停当前的课堂
if (user && user.role == ApeConsts.NR_HOST) {
... ...
... ... @@ -47,7 +47,8 @@ class MediaModule {
path = "http://" + GlobalConfig.MS_PLAY_HLS_IP
+ port + "/live/"
+ _param.streamId
+ "/"+fileName;
+".m3u8";//新版的规则,不需要加playlist 20170724
//+ "/"+fileName;//
} else {
... ...
... ... @@ -718,6 +718,7 @@ message RCChatSendDataRequestPdu {
required bytes user_data = 4;
required string from_role = 5;
required bytes from_name = 6;
optional uint32 msgType = 7 [default =0];//当前消息类型,0是文字消息 1是图片消息
}
message RCDocSendDataModelPdu {
... ...