AlexWang

增加Cursor及同步

... ... @@ -18,6 +18,7 @@ import VideoApe from 'apes/VideoApe';
import AudioApe from 'apes/AudioApe';
import DocApe from 'apes/DocApe';
import WhiteBoardApe from 'apes/WhiteBoardApe';
import CursorApe from 'apes/CursorApe';
import EngineUtils from "EngineUtils";
import GlobalConfig from 'GlobalConfig';
... ... @@ -44,6 +45,7 @@ let _video_ape;
let _audio_ape;
let _doc_ape;
let _whiteboard_ape;
let _cursor_ape;
let _recordPlayback;
let _mediaShareApe;
let _questionApe;
... ... @@ -126,6 +128,9 @@ export default class MessageEntrance extends Emiter {
_whiteboard_ape = new WhiteBoardApe();
_whiteboard_ape.on('*', (type, data) => this._emit(type, data));
_cursor_ape = new CursorApe();
_cursor_ape.on('*', (type, data) => this._emit(type, data));
_doc_ape = new DocApe();
_doc_ape.on('*', (type, data) => this._emit(type, data));
_doc_ape.on(MessageTypes.DOC_UPDATE, this.docUpdateHandler.bind(this));
... ... @@ -149,7 +154,7 @@ export default class MessageEntrance extends Emiter {
this.sendCloseClass = this._sendCloseClass.bind(this);
this.changeHandUpStatus = this._changeHandUpStatus.bind(this); //自己切换举手状态
this.controlHandUpStatus = this._controlHandUpStatus.bind(this); //控制别人的举手状态
this.controlSilenceStatus = this.controlSilenceStatus.bind(this); //改变禁言状态
this.controlSilenceStatus = this._controlSilenceStatus.bind(this); //改变禁言状态
this.sceneTableChange = this._sceneTableChange.bind(this); //控制别人的举手状态
... ... @@ -189,6 +194,9 @@ export default class MessageEntrance extends Emiter {
this.sendDeleteCurPageAnnotation = this._sendDeleteCurPageAnnotation.bind(this); //删除当前页的所有标注
this.sendGotoPrev = this._sendGotoPrev.bind(this); //当前页撤销上一步
// CursorApe
this.sendInsertCursor = this._sendInsertCursor.bind(this); //添加鼠标同步
//DocApe
this.sendDocumentUpload = this._sendDocumentUpload.bind(this); //上传文档
this.sendDocumentSwitchDoc = this._sendDocumentSwitchDoc.bind(this); //切换文档
... ... @@ -1391,6 +1399,18 @@ export default class MessageEntrance extends Emiter {
}
}
//CursorApe
// 添加鼠标同步
_sendInsertCursor(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if (_cursor_ape) {
_cursor_ape.sendInsertCursor(_param);
}
}
//删除当前页面上的所有标注
_sendDeleteCurPageAnnotation(_param) {
if (!_mcu.connected) {
... ...
... ... @@ -132,6 +132,7 @@ class GlobalConfig {
// 全局禁言状态
this.silence = data.silence || false;
// 自有禁言状态
this.selfSilence = data.selfSilence || '';
this.recordStatus = data.recordStatus || this.recordStatus; //当前录制状态
... ...
... ... @@ -9,6 +9,9 @@ function MessageTypes() {}
MessageTypes.CLASS_INIT_SUCCESS = "class_init_success"; //'class.init.success';//初始化成功
//MessageTypes.CLASS_INIT_FAILED='class.init.failed';//初始化失败
// 鼠标更新事件
MessageTypes.CURSOR_UPDATE = 'cursor_update';
//加入课堂相关事件定义
MessageTypes.CLASS_JOIN_MCU_SUCCESS = "class_join_mcu_success" // 'join.mcu.success';
//MessageTypes.CLASS_JOIN_FAILED = 'join.class.failed';
... ...
... ... @@ -140,6 +140,8 @@ ApeConsts.MEDIA_SESSION_ID = 19;
ApeConsts.SCREENSHARING_SESSION_ID = 20;
ApeConsts.POLL_SESSION_ID = 21;
ApeConsts.QUESTION_SESSION_ID = 22;
ApeConsts.CURSOR_SESSION_ID = 23;
// defs for common channel id
ApeConsts.BROADCAST_CHANNEL_ID = 0;
ApeConsts.CONFERENCE_CHANNEL_ID = ApeConsts.CONFERENCE_SESSION_ID;
... ... @@ -148,6 +150,7 @@ ApeConsts.GIFT_CHANNEL_ID = ApeConsts.GIFT_SESSION_ID;
ApeConsts.WEBSHARING_CHANNEL_ID = ApeConsts.WEBSHARING_SESSION_ID;
ApeConsts.DOCSHARING_CHANNEL_ID = ApeConsts.DOCSHARING_SESSION_ID;
ApeConsts.WHITEBOARD_CHANNEL_ID = ApeConsts.WHITEBOARD_SESSION_ID;
ApeConsts.CURSOR_CHANNEL_ID = ApeConsts.CURSOR_SESSION_ID;
ApeConsts.MEDIA_CHANNEL_ID = ApeConsts.MEDIA_SESSION_ID;
ApeConsts.SCREENSHARING_CHANNEL_ID = ApeConsts.SCREENSHARING_SESSION_ID;
... ... @@ -162,6 +165,7 @@ ApeConsts.VIDEO_SESSION_NAME = "video app";
ApeConsts.WEBSHARING_SESSION_NAME = "web sharing app";
ApeConsts.DOCSHARING_SESSION_NAME = "doc sharing app";
ApeConsts.WHITEBOARD_SESSION_NAME = "whiteboard app";
ApeConsts.CURSOR_SESSION_NAME = "cursor app";
ApeConsts.MEDIA_SESSION_NAME = "media sharing app";
ApeConsts.SCREENSHARING_SESSION_NAME = "screen sharing app";
ApeConsts.QUESTION_SESSION_NAME = "question app";
... ... @@ -175,6 +179,7 @@ ApeConsts.VIDEO_SESSION_TAG = "vid-tag";
ApeConsts.WEBSHARING_SESSION_TAG = "web-tag";
ApeConsts.DOCSHARING_SESSION_TAG = "doc-tag";
ApeConsts.WHITEBOARD_SESSION_TAG = "wbd-tag";
ApeConsts.CURSOR_SESSION_TAG = "cursor-tag";
ApeConsts.MEDIA_SESSION_TAG = "med-tag";
ApeConsts.SCREENSHARING_SESSION_TAG = "scr-tag";
ApeConsts.QUESTION_SESSION_TAG = "qst-tag";
... ... @@ -222,6 +227,11 @@ ApeConsts.WHITEBOARD_OBJ_TABLE_ID = ((ApeConsts.WHITEBOARD_SESSION_ID << 16) + 1
ApeConsts.WHITEBOARD_OBJ_TABLE_NAME = "wbd list";
ApeConsts.WHITEBOARD_OBJ_TABLE_TAG = "wbd list tag";
// cursor objects
ApeConsts.CURSOR_OBJ_TABLE_ID = ((ApeConsts.CURSOR_SESSION_ID << 16) + 1);
ApeConsts.CURSOR_OBJ_TABLE_NAME = "cursor list";
ApeConsts.CURSOR_OBJ_TABLE_TAG = "cursor list tag";
// media sharing objects
ApeConsts.MEDIA_OBJ_TABLE_ID = ((ApeConsts.MEDIA_SESSION_ID << 16) + 1);
ApeConsts.MEDIA_OBJ_TABLE_NAME = "med list";
... ...
... ... @@ -332,15 +332,10 @@ class ConferApe extends Ape {
}
// 全局禁言
silenceClass(isSilence) {
silenceClass(params) {
if (GlobalConfig.isHost) {
GlobalConfig.silence = !!isSilence;
//禁言状态改变
this._emit(MessageTypes.CLASS_SILENCE_CHANGE, GlobalConfig.silence);
//同步禁言状态
this.sendUpdaterClassStatusInfo();
this.sendUpdaterClassStatusInfo(params);
} else {
loger.warn('没有开始课堂的权限');
}
... ... @@ -670,11 +665,11 @@ class ConferApe extends Ape {
}
break;
case ApeConsts.USER_ACTION_SILENCE_STATUS_CHANGE:
let msgObj = null;
let silenceMsg = null;
try {
msgObj = JSON.parse(chatMsg.message);
if (msgObj && msgObj.nodeId == GlobalConfig.nodeId) {
this.changeSilenceStatus(msgObj);
silenceMsg = JSON.parse(chatMsg.message);
if (silenceMsg && silenceMsg.nodeId == GlobalConfig.nodeId) {
this.changeSilenceStatus(silenceMsg);
}
} catch (err) {
loger.warn('chatMsg->JSON数据解析失败');
... ... @@ -971,7 +966,7 @@ class ConferApe extends Ape {
classStatusInfo.activeDocCurPage = GlobalConfig.activeDocCurPage; //当前激活的文档的当前页
classStatusInfo.isStopAllPublishMedia = _param.isStopAllPublishMedia || false;
classStatusInfo.currentSceneTableId = GlobalConfig.currentSceneTableId;
classStatusInfo.silence = GlobalConfig.silence;
classStatusInfo.silence = _param.silence || false;
//loger.log("classStatusInfo--->", classStatusInfo);
/*
... ...
// //////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016-present All Rights Reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// http://www.apache.org/licenses/LICENSE-2.0
//
// Github Home: https://github.com/AlexWang1987
// Author: AlexWang
// Date: 2016-08-26 17:36:20
// QQ Email: 1669499355@qq.com
// Last Modified time: 2017-06-22 11:47:29
// Description: LiveClass-CursorApe
//
// //////////////////////////////////////////////////////////////////////////////
import Ape from './Ape';
import ApeConsts from './ApeConsts';
import pdu from 'pdus';
import Loger from 'Loger';
import MessageTypes from 'MessageTypes';
import GlobalConfig from 'GlobalConfig';
import EngineUtils from 'EngineUtils';
let loger = Loger.getLoger('CursorApe');
const DEFAULT_TYPE = 0; //鼠标
class CursorApe extends Ape {
constructor() {
super(
ApeConsts.CURSOR_SESSION_ID,
ApeConsts.CURSOR_SESSION_NAME,
ApeConsts.CURSOR_SESSION_TAG
);
//Ape Models
this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_TABLE, ApeConsts.CURSOR_OBJ_TABLE_ID,
ApeConsts.CURSOR_OBJ_TABLE_NAME, ApeConsts.CURSOR_OBJ_TABLE_TAG, 0, new ArrayBuffer);
// ape listeners
this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
}
_joinSessionHandler(_data) {
loger.log("RCPDU_SESSION_JOIN_RESPONSE");
}
// 添加鼠标
sendInsertCursor(_param) {
if (_param == null || EngineUtils.isEmptyObject(_param)) {
loger.warn('添加标注失败->参数错误->', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return;
}
let itemIdx = EngineUtils.creatSoleNumberFromTimestamp(); //创建时间戳,保证每条数据的唯一
let cursorModelPdu = this.packPdu(_param, itemIdx);
if (cursorModelPdu == null) {
loger.warn('添加标注失败-->参数错误->', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return;
}
//储存记录,用于返回上一步操作
this.insertHistory.push(cursorModelPdu);
let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
tableItemPdu.itemIdx = itemIdx; //直接用时间戳作为id
tableItemPdu.registerObjId = ApeConsts.CURSOR_OBJ_TABLE_ID;
tableItemPdu.owner = 0; //收到flash的是这个值,不清楚先写固定
tableItemPdu.itemData = cursorModelPdu.toArrayBuffer();
//insert
let tableInsertItemPdu = new pdu['RCRegistryTableInsertItemPdu'];
tableInsertItemPdu.type = pdu.RCPDU_REG_TABLE_INSERT_PDU; //
tableInsertItemPdu.items.push(tableItemPdu);
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.CURSOR_OBJ_TABLE_ID;
updateObjPdu.subType = tableInsertItemPdu.type;
updateObjPdu.userData = tableInsertItemPdu.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);
loger.log("添加标注->itemIdx=" + tableItemPdu.itemIdx);
this.sendUniform(adapterPdu, true);
}
/////鼠标数据接受/////////////////////////////////////////////////////////////////////////////////
tableInsertHandler(owner, itemIdx, itemData) {
let cursorModel = this.unPackPdu(owner, itemIdx, itemData);
loger.log('tableInsertHandler', "activeDocId->", GlobalConfig.activeDocId, "parentId->", cursorModel.parentId);
loger.log(cursorModel);
if (cursorModel) {
this._emit(MessageTypes.CURSOR_UPDATE, cursorModel);
}
}
///////鼠标数据发送/////////////////////////////////////////
packPdu(_param, _itemIdx) {
//验证坐标点集合数组是否合法
if (_param.pointGroup == null || _param.pointGroup.length < 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
//判断type类型,根据type设置不同的参数
let cursorModelPdu = new pdu['RCCursorDataModelPdu'];
//下面4个是必须的参数
cursorModelPdu.type = DEFAULT_TYPE;
cursorModelPdu.itemIdx = _itemIdx;
cursorModelPdu.initiator = GlobalConfig.nodeId;
cursorModelPdu.parentId = GlobalConfig.activeDocId; //当前激活的文档id
cursorModelPdu.curPageNo = GlobalConfig.activeDocCurPage; //当前激活的文档页码
cursorModelPdu.pointGroup = EngineUtils.arrayToJsonString(_param.pointGroup);
cursorModelPdu.color = _param.color || "#000000";
cursorModelPdu.thickness = _param.thickness || 1;
cursorModelPdu.duration = _param.duration || 0;
return cursorModelPdu;
}
unPackPdu(owner, itemIdx, itemData) {
try {
loger.log("鼠标标注数据->unPackPdu");
let cursorModelPdu = pdu['RCCursorDataModelPdu'].decode(itemData);
let _pointGroup = EngineUtils.arrayFromJsonString(cursorModelPdu.pointGroup);
cursorModelPdu.pointGroup = _pointGroup;
return cursorModelPdu;
} catch (err) {
loger.log("鼠标标注数据->unPackPdu->Pdu解析错误,itemIdx=" + itemIdx + " err:" + err.message);
}
return null;
}
}
export default CursorApe;
... ...
... ... @@ -962,6 +962,24 @@ message RCWhiteBoardDataModelPdu {
optional string text= 12;//文本内容
optional bytes data = 13;//暂时预留的参数
}
message RCCursorDataModelPdu {
required uint32 type= 1;//类型
required uint32 itemIdx= 2;//itemIdx 每一次绘制的唯一标识
required uint32 initiator=3; //绘制来自谁
required uint32 parentId=4; //父级的id
required uint32 cur_page_no= 5;//页码
optional string pointGroup=6; //坐标点集数组的JSON字符串
optional string color=7 [default = "#000000"]; //颜色
optional uint32 thickness= 8 ;//线条粗细
optional uint32 radius= 9;//园的半径
optional uint32 fontSize= 10;//字体大小
optional string fontName= 11;//字体名称
optional string text= 12;//文本内容
optional bytes data = 13;//暂时预留的参数
optional uint32 duration = 14; // 事件长度
}
message RCClassSendDataModelPdu {
optional uint32 item_idx=1;
optional uint32 from=2;
... ...