李勇

1.增加录制回放接口

2.增加录制文件解析模块 RecordPlayBackParse.js
3.所有“会议” 改成 “课堂”
此 diff 太大无法显示。
@@ -6,6 +6,7 @@ require('string.fromcodepoint'); @@ -6,6 +6,7 @@ require('string.fromcodepoint');
6 import Emiter from './Emiter'; 6 import Emiter from './Emiter';
7 import Sass from 'Sass'; 7 import Sass from 'Sass';
8 import ServerCheck from 'ServerCheck'; 8 import ServerCheck from 'ServerCheck';
  9 +import RecordPlayBackParse from 'RecordPlayBackParse';
9 import Mcu from 'mcu'; 10 import Mcu from 'mcu';
10 import MessageTypes from 'MessageTypes'; 11 import MessageTypes from 'MessageTypes';
11 import Loger from 'Loger'; 12 import Loger from 'Loger';
@@ -20,945 +21,1120 @@ import GlobalConfig from 'GlobalConfig'; @@ -20,945 +21,1120 @@ import GlobalConfig from 'GlobalConfig';
20 import ApeConsts from 'apes/ApeConsts'; 21 import ApeConsts from 'apes/ApeConsts';
21 import Base64 from 'base64-js'; 22 import Base64 from 'base64-js';
22 import ArrayBufferUtil from 'libs/ArrayBufferUtil'; 23 import ArrayBufferUtil from 'libs/ArrayBufferUtil';
  24 +
23 import UTF8 from 'utf-8'; 25 import UTF8 from 'utf-8';
24 26
25 let loger = Loger.getLoger('MessageEntrance'); 27 let loger = Loger.getLoger('MessageEntrance');
26 -let _sdkInfo={"version":"v.1.0.2017.0307","author":"www.3mang.com"}; 28 +let _sdkInfo = {"version": "v.1.0.2017.0307", "author": "www.3mang.com"};
27 29
28 //APE 30 //APE
29 let _sass; 31 let _sass;
30 let _serverCheck; 32 let _serverCheck;
31 -let _mcu ; 33 +let _mcu;
32 let _confer_ape; 34 let _confer_ape;
33 let _chat_ape; 35 let _chat_ape;
34 let _video_ape; 36 let _video_ape;
35 let _audio_ape; 37 let _audio_ape;
36 let _doc_ape; 38 let _doc_ape;
37 let _whiteboard_ape; 39 let _whiteboard_ape;
38 - 40 +let _parseBuf;
39 41
40 //MCUClient 外部实例化主类 42 //MCUClient 外部实例化主类
41 export default class MessageEntrance extends Emiter { 43 export default class MessageEntrance extends Emiter {
42 - constructor() {  
43 - super();  
44 - //sdk 信息  
45 - this.sdkInfo = _sdkInfo;  
46 - loger.log(this.sdkInfo);  
47 -  
48 - //初始化状态  
49 - GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_0);  
50 -  
51 - //全局的Error处理  
52 - this.on(MessageTypes.MCU_ERROR, this._mcuErrorHandler.bind(this));  
53 -  
54 - // Sass平台层  
55 - _sass = Sass;  
56 - _sass.on('*', (type, data) => this._emit(type, data));  
57 - _sass.on(_sass.SUCCESS, this._sassJoinSuccessHandler.bind(this));//通过SASS平台验证(密码和MD5)  
58 - _sass.on(_sass.CLASS_INIT_SUCCESS, this._sassInitSuccessHandler.bind(this));//获取会议初始化信息  
59 - //_sass.on(_sass.CLASS_GET_CLASS_DETAIL, this._sassGetClassDetailSuccessHandler.bind(this));//获取会议的基本信息  
60 - _sass.on(_sass.CLASS_GET_CLASS_PARAM, this._sassGetClassParamSuccessHandler.bind(this));//获取会议的最全信息和历史保存的数据  
61 -  
62 - _sass.on(_sass.CLASS_SAVE_STATUS_INFO_SUCCESS, this._sassSaveClassStatusInfoSuccessHandler.bind(this));//保存会议状态信息  
63 - _sass.on(_sass.CLASS_SAVE_RECORD_INFO_SUCCESS, this._sassSaveClassRecordInfoSuccessHandler.bind(this));//保存会议录制信息  
64 - _sass.on(_sass.DELETE_DOCUMENT_SUCCESS, this._sassDeleteDocumentSuccess.bind(this));//sass删除文档成功  
65 -  
66 - //ServerCheck ip  
67 - _serverCheck=ServerCheck;  
68 - _serverCheck.on(_serverCheck.SEVER_CHECK_BEST_IP_SUCCESS, this._serverCheckBestIpSuccessHandler.bind(this));//ip选点,获取最佳ip完成  
69 -  
70 -  
71 - // 底层MCU消息层  
72 - _mcu = Mcu;  
73 - _mcu.on('*', (type, data) => this._emit(type, data));  
74 - _mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuJoinMCUClassSuccessHandler.bind(this));//加入MCU会议完成  
75 -  
76 -  
77 - // 注册所有应用Ape  
78 - _confer_ape = new ConferApe();  
79 - _confer_ape.on('*', (type, data) => this._emit(type, data));  
80 - _confer_ape.on(MessageTypes.CLASS_EXIT, this._doClassExit.bind(this));//监听自己的关闭事件  
81 - _confer_ape.on(MessageTypes.CLASS_STATUS_INFO_CHANGE, this._onClassStatusInfoChange.bind(this));//当前会议状态信息发生改变  
82 - _confer_ape.on(MessageTypes.CLASS_DELETE_ROSTER, this._onClassDeleteRoster.bind(this));//当前会议人员离开  
83 - _confer_ape.on(MessageTypes.CLASS_NONENTITY_ROSTER,this._onClassNonentityRoster.bind(this));//当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在  
84 - _confer_ape.on(MessageTypes.CLASS_RECORD_START,this._onClassRecordStart.bind(this));//会议开始录制  
85 -  
86 -  
87 - _chat_ape = new ChatApe();  
88 - _chat_ape.on('*', (type, data) => this._emit(type, data));  
89 -  
90 - _video_ape = new VideoApe();  
91 - _video_ape.on('*', (type, data) => this._emit(type, data));  
92 - _video_ape.on(MessageTypes.VIDEO_UPDATE, this.videoUpdate.bind(this));//这个监听事件不能删除,需要通知会议模块,检查channel占用  
93 -  
94 -  
95 - _audio_ape= new AudioApe();  
96 - _audio_ape.on('*', (type, data) => this._emit(type, data));  
97 - _audio_ape.on(MessageTypes.AUDIO_UPDATE, this.audioUpdate.bind(this));//这个监听事件不能删除,需要通知会议模块,检查channel占用  
98 -  
99 - _whiteboard_ape = new WhiteBoardApe();  
100 - _whiteboard_ape.on('*', (type, data) => this._emit(type, data));  
101 - //_whiteboard_ape.on(MessageTypes.WHITEBOARD_ANNOTATION_UPDATE, this.annoUpdateHandler.bind(this));  
102 -  
103 - _doc_ape = new DocApe();  
104 - _doc_ape.on('*', (type, data) => this._emit(type, data));  
105 - _doc_ape.on(MessageTypes.DOC_UPDATE, this.docUpdateHandler.bind(this));  
106 - _doc_ape.on(MessageTypes.DOC_DELETE, this.docDeleteHandler.bind(this));  
107 - _doc_ape.on(DocApe.DOC_JOIN_CHANNEL_SUCCESS, this.docJoinChannelSuccess.bind(this));  
108 -  
109 -  
110 -  
111 - //公开外部调用的方法  
112 - //class  
113 - this.init = this._init.bind(this);  
114 - this.joinClass = this._joinClass.bind(this);  
115 - this.leaveClass = this._leaveClass.bind(this);  
116 - this.getMcuClientStatus = this._getMcuClientStatus.bind(this);  
117 - //this.getClassDetail = this._getClassDetail;//停用  
118 - this.getClassStatusInfo = this._getClassStatusInfo.bind(this);  
119 - this.sendStartClass = this._sendStartClass.bind(this);  
120 - this.sendPauseClass = this._sendPauseClass.bind(this);  
121 - this.sendCloseClass = this._sendCloseClass.bind(this);  
122 -  
123 -  
124 - //chatApe  
125 - this.sendChatMsg = this._sendChatMsg.bind(this);  
126 -  
127 - //videoApe  
128 - //this.getVideoPlayPath = this._getVideoPlayPath.bind(this);  
129 - this.getVideoPublishPath = this._getVideoPublishPath.bind(this);  
130 - this.getVideoAllChannelInfo = this._getVideoAllChannelInfo.bind(this);  
131 - this.publishVideo = this._publishVideo.bind(this);  
132 - this.stopPublishVideo = this._stopPublishVideo.bind(this);  
133 - this.sendVideoBroadcastMsg=this._sendVideoBroadcastMsg.bind(this);  
134 -  
135 -  
136 - //audioApe  
137 - //this.getAudioPlayPath = this._getPlayAudioPath.bind(this);  
138 - this.getAudioPublishPath = this._getPublishAudioPath.bind(this);  
139 - this.getAudioAllChannelInfo = this._getAudioAllChannelInfo.bind(this);  
140 - this.publishAudio = this._publishAudio.bind(this);  
141 - this.stopPublishAudio = this._stopPublishAudio.bind(this);  
142 - this.sendAudioBroadcastMsg=this.sendAudioCommandMsg.bind(this);  
143 -  
144 - //whiteBoradApe  
145 - this.sendInsertAnnotaion = this._sendInsertAnnotaion.bind(this);  
146 - //this.sendDeleteAnnotaion=this._sendDeleteAnnotaion;  
147 - this.sendDeleteAllAnnotation = this._sendDeleteAllAnnotation.bind(this);  
148 - this.sendDeleteCurPageAnnotation = this._sendDeleteCurPageAnnotation.bind(this);  
149 - this.sendGotoPrev = this._sendGotoPrev.bind(this); 44 + constructor() {
  45 + super();
  46 + //sdk 信息
  47 + this.sdkInfo = _sdkInfo;
  48 + loger.log(this.sdkInfo);
  49 +
  50 + //初始化状态
  51 + GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_0);
  52 +
  53 + //全局的Error处理
  54 + this.on(MessageTypes.MCU_ERROR, this._mcuErrorHandler.bind(this));
  55 +
  56 + // Sass平台层
  57 + _sass = Sass;
  58 + _sass.on('*', (type, data) => this._emit(type, data));
  59 + _sass.on(_sass.SUCCESS, this._sassJoinSuccessHandler.bind(this));//通过SASS平台验证(密码和MD5)
  60 + _sass.on(_sass.CLASS_INIT_SUCCESS, this._sassInitSuccessHandler.bind(this));//获取课堂初始化信息
  61 + //_sass.on(_sass.CLASS_GET_CLASS_DETAIL, this._sassGetClassDetailSuccessHandler.bind(this));//获取课堂的基本信息
  62 + _sass.on(_sass.CLASS_GET_CLASS_PARAM, this._sassGetClassParamSuccessHandler.bind(this));//获取课堂的最全信息和历史保存的数据
  63 +
  64 + _sass.on(_sass.CLASS_SAVE_STATUS_INFO_SUCCESS, this._sassSaveClassStatusInfoSuccessHandler.bind(this));//保存课堂状态信息
  65 + _sass.on(_sass.CLASS_SAVE_RECORD_INFO_SUCCESS, this._sassSaveClassRecordInfoSuccessHandler.bind(this));//保存课堂录制信息
  66 + _sass.on(_sass.DELETE_DOCUMENT_SUCCESS, this._sassDeleteDocumentSuccess.bind(this));//sass删除文档成功
  67 +
  68 + //ServerCheck ip
  69 + _serverCheck = ServerCheck;
  70 + _serverCheck.on(_serverCheck.SEVER_CHECK_BEST_IP_SUCCESS, this._serverCheckBestIpSuccessHandler.bind(this));//ip选点,获取最佳ip完成
  71 +
  72 +
  73 + // 底层MCU消息层
  74 + _mcu = Mcu;
  75 + _mcu.on('*', (type, data) => this._emit(type, data));
  76 + _mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuJoinMCUClassSuccessHandler.bind(this));//加入MCU课堂完成
  77 +
  78 + //录制回放
  79 + _parseBuf = RecordPlayBackParse;
  80 + _parseBuf.on('*', (type, data) => this._emit(type, data));
  81 + _parseBuf.on(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS, this._joinRecordPlaybackSuccessHandler.bind(this));//加入录制回放完成
  82 +
  83 +
  84 + // 注册所有应用Ape
  85 + _confer_ape = new ConferApe();
  86 + _confer_ape.on('*', (type, data) => this._emit(type, data));
  87 + _confer_ape.on(MessageTypes.CLASS_EXIT, this._doClassExit.bind(this));//监听自己的关闭事件
  88 + _confer_ape.on(MessageTypes.CLASS_STATUS_INFO_CHANGE, this._onClassStatusInfoChange.bind(this));//当前课堂状态信息发生改变
  89 + _confer_ape.on(MessageTypes.CLASS_DELETE_ROSTER, this._onClassDeleteRoster.bind(this));//当前课堂人员离开
  90 + _confer_ape.on(MessageTypes.CLASS_NONENTITY_ROSTER, this._onClassNonentityRoster.bind(this));//当前课堂中视频或音频占用channel的nodeId ,在人员列表中不存在
  91 + _confer_ape.on(MessageTypes.CLASS_RECORD_START, this._onClassRecordStart.bind(this));//课堂开始录制
  92 +
  93 +
  94 + _chat_ape = new ChatApe();
  95 + _chat_ape.on('*', (type, data) => this._emit(type, data));
  96 +
  97 + _video_ape = new VideoApe();
  98 + _video_ape.on('*', (type, data) => this._emit(type, data));
  99 + _video_ape.on(MessageTypes.VIDEO_UPDATE, this.videoUpdate.bind(this));//这个监听事件不能删除,需要通知课堂模块,检查channel占用
  100 +
  101 +
  102 + _audio_ape = new AudioApe();
  103 + _audio_ape.on('*', (type, data) => this._emit(type, data));
  104 + _audio_ape.on(MessageTypes.AUDIO_UPDATE, this.audioUpdate.bind(this));//这个监听事件不能删除,需要通知课堂模块,检查channel占用
  105 +
  106 + _whiteboard_ape = new WhiteBoardApe();
  107 + _whiteboard_ape.on('*', (type, data) => this._emit(type, data));
  108 + //_whiteboard_ape.on(MessageTypes.WHITEBOARD_ANNOTATION_UPDATE, this.annoUpdateHandler.bind(this));
  109 +
  110 + _doc_ape = new DocApe();
  111 + _doc_ape.on('*', (type, data) => this._emit(type, data));
  112 + _doc_ape.on(MessageTypes.DOC_UPDATE, this.docUpdateHandler.bind(this));
  113 + _doc_ape.on(MessageTypes.DOC_DELETE, this.docDeleteHandler.bind(this));
  114 + _doc_ape.on(DocApe.DOC_JOIN_CHANNEL_SUCCESS, this.docJoinChannelSuccess.bind(this));
  115 +
  116 + //公开外部调用的方法
  117 + //class
  118 + this.init = this._init.bind(this);
  119 + this.joinClass = this._joinClass.bind(this);
  120 + this.leaveClass = this._leaveClass.bind(this);
  121 + this.getMcuClientStatus = this._getMcuClientStatus.bind(this);
  122 + //this.getClassDetail = this._getClassDetail;//停用
  123 + this.getClassStatusInfo = this._getClassStatusInfo.bind(this);
  124 + this.sendStartClass = this._sendStartClass.bind(this);
  125 + this.sendPauseClass = this._sendPauseClass.bind(this);
  126 + this.sendCloseClass = this._sendCloseClass.bind(this);
  127 +
  128 + //录制回放
  129 + this.initRecordPlayback = this._initRecordPlayback.bind(this);
  130 + this.startRecordPlayback = this._startRecordPlayback.bind(this);
  131 + this.stopRecordPlayback = this._stopRecordPlayback.bind(this);
  132 + this.pauseRecordPlayback = this._pauseRecordPlayback.bind(this);
  133 + this.seekRecordPlayback = this._seekRecordPlayback.bind(this);
  134 +
  135 + this.addBuffer = this._addBuffer.bind(this);
  136 + this.read = this._read.bind(this);
  137 + this.writeBuffer = this._writeBuffer.bind(this);
  138 +
  139 + //chatApe
  140 + this.sendChatMsg = this._sendChatMsg.bind(this);
  141 +
  142 + //videoApe
  143 + //this.getVideoPlayPath = this._getVideoPlayPath.bind(this);
  144 + this.getVideoPublishPath = this._getVideoPublishPath.bind(this);
  145 + this.getVideoAllChannelInfo = this._getVideoAllChannelInfo.bind(this);
  146 + this.publishVideo = this._publishVideo.bind(this);
  147 + this.stopPublishVideo = this._stopPublishVideo.bind(this);
  148 + this.sendVideoBroadcastMsg = this._sendVideoBroadcastMsg.bind(this);
  149 +
  150 +
  151 + //audioApe
  152 + //this.getAudioPlayPath = this._getPlayAudioPath.bind(this);
  153 + this.getAudioPublishPath = this._getPublishAudioPath.bind(this);
  154 + this.getAudioAllChannelInfo = this._getAudioAllChannelInfo.bind(this);
  155 + this.publishAudio = this._publishAudio.bind(this);
  156 + this.stopPublishAudio = this._stopPublishAudio.bind(this);
  157 + this.sendAudioBroadcastMsg = this.sendAudioCommandMsg.bind(this);
  158 +
  159 + //whiteBoradApe
  160 + this.sendInsertAnnotaion = this._sendInsertAnnotaion.bind(this);
  161 + //this.sendDeleteAnnotaion=this._sendDeleteAnnotaion;
  162 + this.sendDeleteAllAnnotation = this._sendDeleteAllAnnotation.bind(this);
  163 + this.sendDeleteCurPageAnnotation = this._sendDeleteCurPageAnnotation.bind(this);
  164 + this.sendGotoPrev = this._sendGotoPrev.bind(this);
  165 +
  166 + //DocApe
  167 + this.sendDocumentUpload = this._sendDocumentUpload.bind(this);//上传文档
  168 + this.sendDocumentSwitchDoc = this._sendDocumentSwitchDoc.bind(this); //切换文档
  169 + this.sendDocumentSwitchPage = this._sendDocumentSwitchPage.bind(this);//翻页
  170 + this.sendDocumentDelete = this._sassDeleteDocument.bind(this);
  171 + //删除文档,先通过Sass删除,sass删除成功之后再同步mcu
  172 + //this.sendDocumentDeleteAll= this._documentDeleteAll;//删除所有文档
  173 + this.sendDocumentCommand = this._sendDocumentCommand.bind(this);
  174 + //操作文档(翻页、缩放、滚动...)
  175 + this.getDocImageFullPath = this._getDocImageFullPath.bind(this);
  176 + //获取文档图片的完整路径
  177 + this.getDocPDFFullPath = this._getDocPDFFullPath.bind(this);//获取文档的完整路径
  178 +
  179 + }
  180 +
  181 + //mcu异常监听
  182 + _mcuErrorHandler(_data, _option) {
  183 + let option = _option || "";
  184 + let errorMessage = {"code": _data, "reson": MessageTypes.ErrorReson[_data] + " " + option};
  185 + loger.error("MCU_ERROR", errorMessage);
  186 +
  187 + this._emit(MessageTypes.ERROR_EVENT, errorMessage);
  188 +
  189 + /* if (_mcuErrorCallBackFun) {
  190 + _mcuErrorCallBackFun(errorMessage);
  191 + }*/
  192 + }
  193 +
  194 + //获取当前的状态
  195 + _getMcuClientStatus() {
  196 + return GlobalConfig.getCurrentStatus();
  197 + }
  198 +
  199 +//获取课堂信息
  200 + _getClassDetail() {
  201 + return GlobalConfig.getClassDetail();
  202 + }
  203 +
  204 + //获取当前课堂的状态信息
  205 + _getClassStatusInfo() {
  206 + return GlobalConfig.classStatusInfo;
  207 + }
  208 +
  209 + //关闭课堂,所有人都退出
  210 + _doClassClose(_param) {
  211 + this._leaveClass();
  212 + }
  213 +
  214 + //离开课堂,断开连接
  215 + _doClassExit() {
  216 + this._leaveClass();
  217 + }
  218 +
  219 + //当前的课堂状态信息发生改变,需要保存课堂状态到Sass
  220 + _onClassStatusInfoChange(_param) {
  221 + //如果MCU连接已经断开,不发送
  222 + if (GlobalConfig.getCurrentStatus().code != GlobalConfig.statusCode_2.code) {
  223 + loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());
  224 + return;
  225 + }
  226 + this._sassSaveClassStatusInfo();
  227 + }
150 228
151 - //DocApe  
152 - this.sendDocumentUpload = this._sendDocumentUpload.bind(this);//上传文档  
153 - this.sendDocumentSwitchDoc = this._sendDocumentSwitchDoc.bind(this); //切换文档  
154 - this.sendDocumentSwitchPage = this._sendDocumentSwitchPage.bind(this);//翻页  
155 - this.sendDocumentDelete = this._sassDeleteDocument.bind(this);;//删除文档,先通过Sass删除,sass删除成功之后再同步mcu  
156 - //this.sendDocumentDeleteAll= this._documentDeleteAll;//删除所有文档  
157 - this.sendDocumentCommand = this._sendDocumentCommand.bind(this);;//操作文档(翻页、缩放、滚动...)  
158 - this.getDocImageFullPath=this._getDocImageFullPath.bind(this);;//获取文档图片的完整路径  
159 - this.getDocPDFFullPath=this._getDocPDFFullPath.bind(this);;//获取文档的完整路径  
160 - }  
161 -  
162 -  
163 - //mcu异常监听  
164 - _mcuErrorHandler(_data, _option) {  
165 - let option = _option || "";  
166 - let errorMessage = {"code": _data, "reson": MessageTypes.ErrorReson[_data] + " " + option};  
167 - loger.error("MCU_ERROR", errorMessage);  
168 -  
169 - this._emit(MessageTypes.ERROR_EVENT,errorMessage);  
170 -  
171 -/* if (_mcuErrorCallBackFun) {  
172 - _mcuErrorCallBackFun(errorMessage);  
173 - }*/  
174 - }  
175 -  
176 - //获取当前的状态  
177 - _getMcuClientStatus() {  
178 - return GlobalConfig.getCurrentStatus();  
179 - }  
180 -  
181 -//获取会议信息  
182 - _getClassDetail() {  
183 - return GlobalConfig.getClassDetail();  
184 - }  
185 -  
186 - //获取当前会议的状态信息  
187 - _getClassStatusInfo(){  
188 - return GlobalConfig.classStatusInfo;  
189 - }  
190 - //关闭会议,所有人都退出  
191 - _doClassClose(_param) {  
192 - this._leaveClass();  
193 - }  
194 -  
195 - //离开会议,断开连接  
196 - _doClassExit() {  
197 - this._leaveClass();  
198 - }  
199 -  
200 - //当前的会议状态信息发生改变,需要保存会议状态到Sass  
201 - _onClassStatusInfoChange(_param) {  
202 - //如果MCU连接已经断开,不发送  
203 - if(GlobalConfig.getCurrentStatus().code!=GlobalConfig.statusCode_2.code){  
204 - loger.warn("不能保存会议状态",GlobalConfig.getCurrentStatus());  
205 - return;  
206 - }  
207 - this._sassSaveClassStatusInfo();  
208 - }  
209 -  
210 - //如果是第一次点击开始上课,需要创建录制时的文件名  
211 - _onClassRecordStart(_param){  
212 - if(GlobalConfig.getCurrentStatus().code!=GlobalConfig.statusCode_2.code){  
213 - loger.warn("不能保存会议状态",GlobalConfig.getCurrentStatus());  
214 - return;  
215 - }  
216 - if(_sass){  
217 - _sass.saveClassRecordContrlInfo(_param);  
218 - }  
219 - }  
220 -  
221 -  
222 - //有人员离开  
223 - _onClassDeleteRoster(_data){  
224 - //{"nodeId":nodeId}  
225 - //当有人员离开的时候,如果离开的人员已经推流,那么需要停止推流,然后释放channel;  
226 - /* if(_data!=null&&_data.nodeId!=null){  
227 - loger.log("有人员离开,检查一下离开的人员是否关闭推流");  
228 - if(_video_ape){  
229 - _video_ape.stopPublishVideo(_data);  
230 - }  
231 - if(_audio_ape){  
232 - _audio_ape.stopPublishAudio(_data);  
233 - }  
234 - }*/  
235 - }  
236 -  
237 - //当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel  
238 - //的占用状态导致,对于这种情况,需要释放掉  
239 - _onClassNonentityRoster(_param){  
240 - if(_param==null||_param.nodeId==null){  
241 - loger.warn("onClassNonentityRoster.参数错误")  
242 - return;  
243 - }  
244 - let data={"nodeId":_param.nodeId};  
245 - if(_video_ape){  
246 - _video_ape.stopPublishVideo(data);  
247 - }  
248 - if(_audio_ape){  
249 - _audio_ape.stopPublishAudio(data);  
250 - }  
251 - }  
252 -  
253 -  
254 - //Sass  
255 - //初始化  
256 - _init(_param) {  
257 - //{"classId":"1653304953","portal":"112.126.80.182:80","userRole":"normal","userId":0}  
258 - //判断传入的参数是否存在  
259 - if (_param == null || EngineUtils.isEmptyObject(_param)) {  
260 - loger.error('init初始化失败,参数错误');  
261 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);  
262 - return;  
263 - }  
264 - //判断必要的参数字段值  
265 - if (_param.classId == null || isNaN(_param.classId) || _param.portal == null || _param.portal == "") {  
266 - loger.error('init初始化失败', _param);  
267 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);  
268 - return;  
269 - }  
270 - loger.log('init', _param);  
271 -  
272 - //保存参数  
273 - GlobalConfig.classId = parseInt(_param.classId);  
274 - GlobalConfig.portal = _param.portal;  
275 - GlobalConfig.userRole = _param.userRole || ApeConsts.normal;  
276 - GlobalConfig.userId = _param.userId || "0";  
277 - GlobalConfig.userName=_param.userName || "";  
278 -  
279 - //获取课堂校验信息  
280 - if (_sass) {  
281 - _sass.getJoinParams(GlobalConfig.getClassInfo());  
282 - }  
283 - }  
284 -  
285 - //外部请求加入会议  
286 - _joinClass(_param) {  
287 - //_joinClassSuccessCallBackFun = _onSuccess;  
288 - //{"userName":"名字","password":""}  
289 - if (_param == null || EngineUtils.isEmptyObject(_param)) {  
290 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);  
291 - loger.log('不能进入会议,传递的参数不对.', _param);  
292 - return;  
293 - }  
294 - //判断userName  
295 - if (_param.userName == null || _param.userName == "") {  
296 - loger.log('不能进入会议,传递的参数不对.名字不能为空');  
297 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);  
298 - return;  
299 - }  
300 -  
301 - if(GlobalConfig.userName==null||GlobalConfig.userName==""){  
302 - GlobalConfig.userName = _param.userName;  
303 - }  
304 - GlobalConfig.password = _param.password || "";  
305 - GlobalConfig.hasCamera=(typeof _param.hasCamera=="boolean")? _param.hasCamera:false;  
306 - GlobalConfig.hasMicrophone=(typeof _param.hasMicrophone=="boolean")? _param.hasMicrophone:false;  
307 -  
308 - //debugger;  
309 - //开始校验  
310 - if (_sass) {  
311 - _sass.passwordAndMd5Checking(GlobalConfig.getClassInfo());  
312 - }  
313 - }  
314 -  
315 - // 用classId向SASS平台获取入会验证信息成功  
316 - _sassInitSuccessHandler(_data) {  
317 - //{"siteId":"h5test","passwordRequired":true,"md5":"de399d5540b3da2fbc1eb0a770d4fd66","code":0,"msType":1}  
318 - //储存数据  
319 - GlobalConfig.md5 = _data.md5 || "";//这个暂时用假数据,后台接口写完就有数据了  
320 - GlobalConfig.msType = _data.msType || 1;  
321 - GlobalConfig.siteId = _data.siteId || "";  
322 - GlobalConfig.classType = _data.meetingType || 0;  
323 -  
324 - //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的  
325 - GlobalConfig.passwordRequired = _data.passwordRequired || false;//md5验证的时候需要Sass返回的值,不能更改  
326 -  
327 - loger.log('SASS平台获取入会验证信息成功.');  
328 -  
329 - //设置当前的会议状态  
330 - GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_1);  
331 - //返回给客户端初始化成功的数据  
332 - let initSuccessCallBackData = {};  
333 - initSuccessCallBackData.siteId = GlobalConfig.siteId;  
334 - initSuccessCallBackData.classId = GlobalConfig.classId;  
335 - initSuccessCallBackData.userRole = GlobalConfig.userRole;  
336 - initSuccessCallBackData.userId = GlobalConfig.userId;  
337 - initSuccessCallBackData.userName= GlobalConfig.userName;  
338 - initSuccessCallBackData.classType = GlobalConfig.classType;  
339 -  
340 - //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的  
341 - if (GlobalConfig.userRole== ApeConsts.host) {  
342 - initSuccessCallBackData.passwordRequired =true;  
343 - } else {  
344 - initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;  
345 - }  
346 -  
347 - this._emit(MessageTypes.CLASS_INIT_SUCCESS,initSuccessCallBackData);  
348 -  
349 -/* if (_initSuccessCallBackFun) {  
350 - _initSuccessCallBackFun(initSuccessCallBackData);  
351 - }*/  
352 -  
353 - }  
354 -  
355 - // 通过SASS平台验证(密码和MD5)  
356 - _sassJoinSuccessHandler(_data) {  
357 - //返回值  
358 - /* flag 数值型 无 True:成功  
359 - Flag:失败  
360 - h5_mcu_list 字符串 H5muc列表  
361 - maxVideoChannels 数值型 最大视频路数  
362 - maxAudioChannels 数值型 最大音频路数  
363 - h5Module 数值型 H5开关  
364 - ms 字符串 Ms列表  
365 - mcu 字符串 Mcu列表  
366 - rs 字符串 Rs列表  
367 - doc 字符串 Doc列表*/  
368 - //获取会议最完整的数据  
369 - if (_sass) {  
370 - _sass.getClassParam();  
371 - }  
372 - }  
373 -  
374 - //获取会议所有参数 api/meeting/detail.do? flash中的接口文件是 getClassParam.do  
375 - _sassGetClassParamSuccessHandler(_data) {  
376 - //console.log(GlobalConfig.classStatusInfo)  
377 - loger.log('获取课堂会议的完整信息完成.');  
378 - // console.log(_data);  
379 - //包含整个会议最全的信息,储存数据  
380 - if (_data) {  
381 - GlobalConfig.mcuDelay=_data.mcuDelay || 60;//mcu消息延迟,用于文档模块  
382 - GlobalConfig.className = _data.meetingName || "";  
383 - GlobalConfig.classBeginTime = _data.beginTime || "";  
384 - GlobalConfig.classEndTime = _data.endTime || "";  
385 - GlobalConfig.userIp=_data.userIp||"";  
386 -  
387 - GlobalConfig.maxVideoChannels = _data.maxVideoChannels;  
388 - GlobalConfig.maxAudioChannels = _data.maxAudioChannels;  
389 -  
390 - GlobalConfig.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表  
391 - GlobalConfig.setRecordList(_data.recordList);//录制回放地址  
392 - GlobalConfig.setDocList(_data.docList);//文档地址  
393 - GlobalConfig.setMsList(_data.msList);//推流播流服务器地址  
394 - GlobalConfig.setRsList(_data.rsList);//播放m3u8格式的地址  
395 - GlobalConfig.setMcuList(_data.mcuList);//mcu  
396 - GlobalConfig.setMusicList(_data.musicList);//  
397 - GlobalConfig.setMusicListPrepare(_data.musicListPrepare);//提前上传的声音文件列表  
398 -  
399 -  
400 - if (_data.mcuList) {  
401 - //MCU地址默认使用第一个  
402 - GlobalConfig.MCUServerIP =_data.mcuList[0].ip||"";  
403 - GlobalConfig.MCUServerPort =_data.mcuList[0].port||"";  
404 - }  
405 -  
406 - //视频推流播流地址  
407 - if (_data.msList) {  
408 - //MS地址默认使用第一个  
409 - GlobalConfig.MSServerIP =_data.msList[0].ip||"";  
410 - GlobalConfig.MSServerPort =_data.msList[0].port||"";  
411 - }  
412 -  
413 - //m3u8播流地址  
414 - if(_data.rsList){  
415 - //RS地址默认使用第一个  
416 - GlobalConfig.RSServerIP =_data.rsList[0].ip||"";  
417 - GlobalConfig.RSServerPort =_data.rsList[0].port||"";  
418 - }  
419 -  
420 - //文档地址  
421 - if(_data.docList){  
422 - //doc地址默认使用第一个  
423 - GlobalConfig.DOCServerIP =_data.docList[0].ip||"";  
424 - GlobalConfig.DOCServerPort =_data.docList[0].port||"";  
425 - }  
426 -  
427 - //record  
428 - if(_data.recordList){  
429 - //地址默认使用第一个  
430 - GlobalConfig.RecordServerIP =_data.recordList[0].ip||"";  
431 - GlobalConfig.RecordServerPort =_data.recordList[0].port||"";  
432 - }  
433 -  
434 - }  
435 -  
436 - if (_data.currentInfo) {  
437 - //根据从Sass获取的数据信息,同步最后一次保存的会议状态信息  
438 - loger.log("同步最后一次保存过的会议状态信息");  
439 - GlobalConfig.setClassStatusInfo(_data.currentInfo);  
440 - console.log(GlobalConfig.classStatusInfo);  
441 - } else {  
442 - loger.log("还没有保存过会议状信息");  
443 - }  
444 -  
445 - //根据用户的userIp获取信息  
446 - this.getUserIpInfo();  
447 - }  
448 - //根据UserIp获取ip信息  
449 - getUserIpInfo(){  
450 - if(_serverCheck){  
451 - _serverCheck.getUserIpInfo("",GlobalConfig.userIp);  
452 - }  
453 - }  
454 - //MCU MS ip选点完成,开加入MCU  
455 - _serverCheckBestIpSuccessHandler(_data){  
456 - loger .log("_serverCheckBestIpSuccessHandler,IP选点结束");  
457 - this._joinMCU();  
458 - }  
459 -  
460 - //保存会议状态信息  
461 - _sassSaveClassStatusInfo() {  
462 - if (GlobalConfig.isHost) {  
463 - //只有加入会议之后才能保存数据  
464 - if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) {  
465 - //POST 保存数据  
466 - _sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo});//保存会议状态信息  
467 - } else {  
468 - loger.error("不能保存会议数据", GlobalConfig.getCurrentStatus());  
469 - }  
470 - } else {  
471 - loger.log("没有保存会议状态信息的权限 isHost", GlobalConfig.isHost);  
472 - }  
473 - }  
474 -  
475 - //保存会态信息成功  
476 - _sassSaveClassStatusInfoSuccessHandler(_data) {  
477 - loger.log('保存会议状态信息成功.');  
478 - console.log(_data);  
479 - }  
480 - _sassSaveClassRecordInfoSuccessHandler(_data){  
481 - loger.log('保存会议录制信息成功.');  
482 - console.log(_data);  
483 - }  
484 -  
485 - //Sass校验流程结束之后,开始加入MCU  
486 - _joinMCU() {  
487 - loger.log('加入底层MCU会议.');  
488 - if (_mcu) {  
489 - _mcu.joinMCU(GlobalConfig.getClassInfo());  
490 - }  
491 - }  
492 -  
493 - // MCU 会议成功  
494 - _mcuJoinMCUClassSuccessHandler(_data) {  
495 - loger.log('MCU 会议成功.');  
496 - GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);  
497 -  
498 - //返回给客户端初始化成功的数据  
499 - let joinClassSuccessCallBackData = {};  
500 -  
501 - joinClassSuccessCallBackData.DOCServerIP =GlobalConfig.DOCServerIP;  
502 - joinClassSuccessCallBackData.DOCServerPort =GlobalConfig.DOCServerPort;  
503 -  
504 - joinClassSuccessCallBackData.classId = GlobalConfig.classId;  
505 - joinClassSuccessCallBackData.className = GlobalConfig.className;  
506 - joinClassSuccessCallBackData.h5Module = GlobalConfig.h5Module;  
507 - joinClassSuccessCallBackData.isHost = GlobalConfig.isHost;  
508 - joinClassSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;  
509 - joinClassSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;  
510 - joinClassSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;  
511 -  
512 - joinClassSuccessCallBackData.msType = GlobalConfig.msType;  
513 - joinClassSuccessCallBackData.nodeId = GlobalConfig.nodeId;  
514 - joinClassSuccessCallBackData.password = GlobalConfig.password;  
515 - joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;// 老师的默认是true  
516 - //GlobalConfig.passwordRequired 老师的默认是true  
517 - //GlobalConfig.portal=_data.portal;  
518 - joinClassSuccessCallBackData.role = GlobalConfig.role;  
519 - joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;  
520 - joinClassSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;  
521 - joinClassSuccessCallBackData.userId = GlobalConfig.userId;  
522 - joinClassSuccessCallBackData.userName = GlobalConfig.userName;  
523 - joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;  
524 - joinClassSuccessCallBackData.userType = GlobalConfig.userType;  
525 -  
526 - joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;  
527 - joinClassSuccessCallBackData.classId = GlobalConfig.classId;  
528 - joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;  
529 - joinClassSuccessCallBackData.userId = GlobalConfig.userId;  
530 - joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;  
531 - joinClassSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_INTERACT;  
532 -  
533 - joinClassSuccessCallBackData.country = GlobalConfig.country;//国家  
534 - joinClassSuccessCallBackData.city = GlobalConfig.city;//城市  
535 - joinClassSuccessCallBackData.province = GlobalConfig.province;//服务商  
536 - joinClassSuccessCallBackData.isp = GlobalConfig.isp;//服务商  
537 -  
538 - loger.log('加入会议成功');  
539 - console.log(joinClassSuccessCallBackData);  
540 -  
541 - //加入会议成功,广播消息  
542 - this._emit(MessageTypes.CLASS_JOIN_SUCCESS,joinClassSuccessCallBackData);  
543 - }  
544 -  
545 - //Sass删除文档数据  
546 - _sassDeleteDocument(_param) {  
547 - if(!_mcu.connected){  
548 - loger.warn(GlobalConfig.getCurrentStatus());  
549 - return;  
550 - }  
551 -  
552 - //判断传入的参数是否存在  
553 - if (_param == null || EngineUtils.isEmptyObject(_param)) {  
554 - loger.error('sassDeleteDocument失败,参数错误', _param);  
555 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);  
556 - return;  
557 - }  
558 - //判断必要的参数字段值  
559 - if (_param.itemIdx == null || isNaN(_param.itemIdx) || _param.docId == null || _param.docId == "") {  
560 - loger.error('sassDeleteDocument失败', _param);  
561 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);  
562 - return;  
563 - }  
564 - loger.log('_sassDeleteDocument', _param);  
565 -  
566 - if (_sass) {  
567 - _sass.sassDeleteDocument(_param);  
568 - }  
569 - }  
570 -  
571 - //Sass删除文档成功之后,同步删除MCU数据  
572 - _sassDeleteDocumentSuccess(_param) {  
573 - loger.log('sassDeleteDocumentSuccess', _param);  
574 - this._sendDocumentDelete(_param);  
575 - }  
576 -  
577 - //ConferApe  
578 - //开始上课  
579 - _sendStartClass(_param){  
580 - if(!_mcu.connected){  
581 - loger.warn(GlobalConfig.getCurrentStatus());  
582 - return;  
583 - }  
584 -  
585 - if(_confer_ape){  
586 - _confer_ape.startClass(_param);  
587 - }  
588 - }  
589 - //暂停上课  
590 - _sendPauseClass(_param){  
591 - if(!_mcu.connected){  
592 - loger.warn(GlobalConfig.getCurrentStatus());  
593 - return;  
594 - }  
595 - if(_confer_ape){  
596 - _confer_ape.pauseClass(_param);  
597 - }  
598 - }  
599 - //停止上课  
600 - _sendCloseClass(_param){  
601 - if(!_mcu.connected){  
602 - loger.warn(GlobalConfig.getCurrentStatus());  
603 - return;  
604 - }  
605 - if(_confer_ape){  
606 - _confer_ape.closeClass(_param);  
607 - }  
608 - }  
609 - // 离开会议  
610 - _leaveClass() {  
611 - if(!_mcu.connected){  
612 - loger.warn(GlobalConfig.getCurrentStatus());  
613 - return; 229 + //如果是第一次点击开始上课,需要创建录制时的文件名
  230 + _onClassRecordStart(_param) {
  231 + if (GlobalConfig.getCurrentStatus().code != GlobalConfig.statusCode_2.code) {
  232 + loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());
  233 + return;
  234 + }
  235 + if (_sass) {
  236 + _sass.saveClassRecordContrlInfo(_param);
  237 + }
614 } 238 }
615 239
616 - //停止推流  
617 - if(_video_ape){  
618 - _video_ape.stopPublishVideo(); 240 +
  241 + //有人员离开
  242 + _onClassDeleteRoster(_data) {
  243 +
  244 + //在conferApe中做处理,这里不需要再处理
  245 + //{"nodeId":nodeId}
  246 + //当有人员离开的时候,如果离开的人员已经推流,那么需要停止推流,然后释放channel;
  247 + /* if(_data!=null&&_data.nodeId!=null){
  248 + loger.log("有人员离开,检查一下离开的人员是否关闭推流");
  249 + if(_video_ape){
  250 + _video_ape.stopPublishVideo(_data);
  251 + }
  252 + if(_audio_ape){
  253 + _audio_ape.stopPublishAudio(_data);
  254 + }
  255 + }*/
619 } 256 }
620 - if(_audio_ape){  
621 - _audio_ape.stopPublishAudio(); 257 +
  258 + //当前课堂中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel
  259 + //的占用状态导致,对于这种情况,需要释放掉
  260 + _onClassNonentityRoster(_param) {
  261 + if (_param == null || _param.nodeId == null) {
  262 + loger.warn("onClassNonentityRoster.参数错误")
  263 + return;
  264 + }
  265 + let data = {"nodeId": _param.nodeId};
  266 + if (_video_ape) {
  267 + _video_ape.stopPublishVideo(data);
  268 + }
  269 + if (_audio_ape) {
  270 + _audio_ape.stopPublishAudio(data);
  271 + }
622 } 272 }
623 - //离开会议  
624 - if(_confer_ape){  
625 - _confer_ape.stopRecord();  
626 - _confer_ape.leaveClass(); 273 +
  274 +
  275 + //Sass
  276 + //初始化
  277 + _init(_param) {
  278 + //{"classId":"1653304953","portal":"112.126.80.182:80","userRole":"normal","userId":0}
  279 + //判断传入的参数是否存在
  280 + if (_param == null || EngineUtils.isEmptyObject(_param)) {
  281 + loger.error('init初始化失败,参数错误');
  282 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);
  283 + return;
  284 + }
  285 + //判断必要的参数字段值
  286 + if (_param.classId == null || isNaN(_param.classId) || _param.portal == null || _param.portal == "") {
  287 + loger.error('init初始化失败', _param);
  288 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);
  289 + return;
  290 + }
  291 + loger.log('init', _param);
  292 +
  293 + //保存参数
  294 + GlobalConfig.isRecordPlayBack=false;//设置为非录制回放状态
  295 + GlobalConfig.classId = parseInt(_param.classId);
  296 + GlobalConfig.portal = _param.portal;
  297 + GlobalConfig.userRole = _param.userRole || ApeConsts.normal;
  298 + GlobalConfig.userId = _param.userId || "0";
  299 + GlobalConfig.userName = _param.userName || "";
  300 +
  301 + //获取课堂校验信息
  302 + if (_sass) {
  303 + _sass.getJoinParams(GlobalConfig.getClassInfo());
  304 + }
627 } 305 }
628 - //断开MCU连接  
629 - if(_mcu){  
630 - _mcu.leaveMCU();  
631 - GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_3); 306 +
  307 + //外部请求加入课堂
  308 + _joinClass(_param) {
  309 + //_joinClassSuccessCallBackFun = _onSuccess;
  310 + //{"userName":"名字","password":""}
  311 + if (_param == null || EngineUtils.isEmptyObject(_param)) {
  312 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);
  313 + loger.log('不能进入课堂,传递的参数不对.', _param);
  314 + return;
  315 + }
  316 + //判断userName
  317 + if (_param.userName == null || _param.userName == "") {
  318 + loger.log('不能进入课堂,传递的参数不对.名字不能为空');
  319 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);
  320 + return;
  321 + }
  322 +
  323 + if (GlobalConfig.userName == null || GlobalConfig.userName == "") {
  324 + GlobalConfig.userName = _param.userName;
  325 + }
  326 + GlobalConfig.password = _param.password || "";
  327 + GlobalConfig.hasCamera = (typeof _param.hasCamera == "boolean") ? _param.hasCamera : false;
  328 + GlobalConfig.hasMicrophone = (typeof _param.hasMicrophone == "boolean") ? _param.hasMicrophone : false;
  329 +
  330 + //debugger;
  331 + //开始校验
  332 + if (_sass) {
  333 + _sass.passwordAndMd5Checking(GlobalConfig.getClassInfo());
  334 + }
632 } 335 }
633 - }  
634 336
  337 + // 用classId向SASS平台获取入会验证信息成功
  338 + _sassInitSuccessHandler(_data) {
  339 + //{"siteId":"h5test","passwordRequired":true,"md5":"de399d5540b3da2fbc1eb0a770d4fd66","code":0,"msType":1}
  340 + //储存数据
  341 + GlobalConfig.md5 = _data.md5 || "";//这个暂时用假数据,后台接口写完就有数据了
  342 + GlobalConfig.msType = _data.msType || 1;
  343 + GlobalConfig.siteId = _data.siteId || "";
  344 + GlobalConfig.classType = _data.meetingType || 0;
  345 +
  346 + //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
  347 + GlobalConfig.passwordRequired = _data.passwordRequired || false;//md5验证的时候需要Sass返回的值,不能更改
  348 +
  349 + loger.log('SASS平台获取入会验证信息成功.');
  350 +
  351 + //设置当前的课堂状态
  352 + GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_1);
  353 + //返回给客户端初始化成功的数据
  354 + let initSuccessCallBackData = {};
  355 + initSuccessCallBackData.siteId = GlobalConfig.siteId;
  356 + initSuccessCallBackData.classId = GlobalConfig.classId;
  357 + initSuccessCallBackData.userRole = GlobalConfig.userRole;
  358 + initSuccessCallBackData.userId = GlobalConfig.userId;
  359 + initSuccessCallBackData.userName = GlobalConfig.userName;
  360 + initSuccessCallBackData.classType = GlobalConfig.classType;
  361 +
  362 + //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
  363 + if (GlobalConfig.userRole == ApeConsts.host) {
  364 + initSuccessCallBackData.passwordRequired = true;
  365 + } else {
  366 + initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
  367 + }
635 368
636 - //ChatApe  
637 - // 发送聊天消息  
638 - _sendChatMsg(_messageInfo) {  
639 - if(!_mcu.connected){  
640 - loger.warn(GlobalConfig.getCurrentStatus());  
641 - return; 369 + this._emit(MessageTypes.CLASS_INIT_SUCCESS, initSuccessCallBackData);
  370 + }
  371 +
  372 + // 通过SASS平台验证(密码和MD5)
  373 + _sassJoinSuccessHandler(_data) {
  374 + //返回值
  375 + /* flag 数值型 无 True:成功
  376 + Flag:失败
  377 + h5_mcu_list 字符串 H5muc列表
  378 + maxVideoChannels 数值型 最大视频路数
  379 + maxAudioChannels 数值型 最大音频路数
  380 + h5Module 数值型 H5开关
  381 + ms 字符串 Ms列表
  382 + mcu 字符串 Mcu列表
  383 + rs 字符串 Rs列表
  384 + doc 字符串 Doc列表*/
  385 + //获取课堂最完整的数据
  386 + if (_sass) {
  387 + _sass.getClassParam();
  388 + }
642 } 389 }
643 - if(_messageInfo===null||EngineUtils.isEmptyObject(_messageInfo)){  
644 - loger.log('sendChatMsg 传递的参数不对',_messageInfo);  
645 - return ; 390 +
  391 + //获取课堂所有参数 api/meeting/detail.do? flash中的接口文件是 getClassParam.do
  392 + _sassGetClassParamSuccessHandler(_data) {
  393 + //console.log(GlobalConfig.classStatusInfo)
  394 + loger.log('获取课堂课堂的完整信息完成.');
  395 + // console.log(_data);
  396 + //包含整个课堂最全的信息,储存数据
  397 + if (_data) {
  398 + GlobalConfig.mcuDelay = _data.mcuDelay || 60;//mcu消息延迟,用于文档模块
  399 + GlobalConfig.className = _data.meetingName || "";
  400 + GlobalConfig.classBeginTime = _data.beginTime || "";
  401 + GlobalConfig.classEndTime = _data.endTime || "";
  402 + GlobalConfig.userIp = _data.userIp || "";
  403 +
  404 + GlobalConfig.maxVideoChannels = _data.maxVideoChannels;
  405 + GlobalConfig.maxAudioChannels = _data.maxAudioChannels;
  406 +
  407 + GlobalConfig.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表
  408 + GlobalConfig.setRecordList(_data.recordList);//录制回放地址
  409 + GlobalConfig.setDocList(_data.docList);//文档地址
  410 + GlobalConfig.setMsList(_data.msList);//推流播流服务器地址
  411 + GlobalConfig.setRsList(_data.rsList);//播放m3u8格式的地址
  412 + GlobalConfig.setMcuList(_data.mcuList);//mcu
  413 + GlobalConfig.setMusicList(_data.musicList);//
  414 + GlobalConfig.setMusicListPrepare(_data.musicListPrepare);//提前上传的声音文件列表
  415 +
  416 +
  417 + if (_data.mcuList&&_data.mcuList.length>0) {
  418 + //MCU地址默认使用第一个
  419 + GlobalConfig.MCUServerIP = _data.mcuList[0].ip || "";
  420 + GlobalConfig.MCUServerPort = _data.mcuList[0].port || "";
  421 + }
  422 +
  423 + //视频推流播流地址
  424 + if (_data.msList&&_data.msList.length>0) {
  425 + //MS地址默认使用第一个
  426 + GlobalConfig.MSServerIP = _data.msList[0].ip || "";
  427 + GlobalConfig.MSServerPort = _data.msList[0].port || "";
  428 + }
  429 +
  430 + //m3u8播流地址
  431 + if (_data.rsList&&_data.rsList.length>0) {
  432 + //RS地址默认使用第一个
  433 + GlobalConfig.RSServerIP = _data.rsList[0].ip || "";
  434 + GlobalConfig.RSServerPort = _data.rsList[0].port || "";
  435 + }
  436 +
  437 + //文档地址
  438 + if (_data.docList&&_data.docList.length>0) {
  439 + //doc地址默认使用第一个
  440 + GlobalConfig.DOCServerIP = _data.docList[0].ip || "";
  441 + GlobalConfig.DOCServerPort = _data.docList[0].port || "";
  442 + }
  443 +
  444 + //record
  445 + if (_data.recordList&&_data.recordList.length>0) {
  446 + //地址默认使用第一个
  447 + GlobalConfig.RecordServerIP = _data.recordList[0].ip || "";
  448 + GlobalConfig.RecordServerPort = _data.recordList[0].port || "";
  449 + }
  450 +
  451 + }
  452 +
  453 + if (_data.currentInfo) {
  454 + //根据从Sass获取的数据信息,同步最后一次保存的课堂状态信息
  455 + loger.log("本地同步最后一次保存过的课堂状态信息");
  456 + GlobalConfig.setClassStatusInfo(_data.currentInfo);
  457 + console.log(GlobalConfig.classStatusInfo);
  458 + } else {
  459 + loger.log("还没有保存过课堂状信息");
  460 + }
  461 +
  462 +
  463 + //录制回放不需要选点
  464 + if(GlobalConfig.isRecordPlayBack){
  465 + if (_parseBuf) {
  466 + //开启录制回放流程
  467 + loger.log("开启录制回放流程");
  468 + _parseBuf.readyRecordPlay();
  469 + }else {
  470 + loger.warn("开启录制回放流程失败,还未创建模块");
  471 + }
  472 + }else {
  473 + //根据用户的userIp获取信息
  474 + this.getUserIpInfo();
  475 + }
646 } 476 }
647 - if (_chat_ape) {  
648 - _chat_ape.sendChatMsg(_messageInfo); 477 +
  478 + //根据UserIp获取ip信息
  479 + getUserIpInfo() {
  480 + if (_serverCheck) {
  481 + _serverCheck.getUserIpInfo("", GlobalConfig.userIp);
  482 + }
649 } 483 }
650 - }  
651 484
652 - //VidoeApe  
653 - videoUpdate(_data){  
654 - //视频同步的消息发送改变,需要通知ferApe模块中的用户更新状态  
655 - if(_confer_ape){  
656 - _confer_ape.updaterRosterStatus(_data); 485 + //MCU MS ip选点完成,开加入MCU
  486 + _serverCheckBestIpSuccessHandler(_data) {
  487 + loger.log("_serverCheckBestIpSuccessHandler,IP选点结束");
  488 + this._joinMCU();
  489 + }
  490 +
  491 + //保存课堂状态信息
  492 + _sassSaveClassStatusInfo() {
  493 + if (GlobalConfig.isHost) {
  494 + //只有加入课堂之后才能保存数据
  495 + if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) {
  496 + //POST 保存数据
  497 + _sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo});//保存课堂状态信息
  498 + } else {
  499 + loger.error("不能保存课堂数据", GlobalConfig.getCurrentStatus());
  500 + }
  501 + } else {
  502 + loger.log("没有保存课堂状态信息的权限 isHost", GlobalConfig.isHost);
  503 + }
657 } 504 }
658 - }  
659 505
660 - _sendVideoBroadcastMsg(_param){  
661 - if(!_mcu.connected){  
662 - loger.warn(GlobalConfig.getCurrentStatus());  
663 - return; 506 + //保存会态信息成功
  507 + _sassSaveClassStatusInfoSuccessHandler(_data) {
  508 + loger.log('保存课堂状态信息成功.');
  509 + console.log(_data);
664 } 510 }
665 - if(_video_ape){  
666 - return _video_ape.sendVideoBroadcastMsg(_param); 511 +
  512 + _sassSaveClassRecordInfoSuccessHandler(_data) {
  513 + loger.log('保存课堂录制信息成功.');
  514 + console.log(_data);
667 } 515 }
668 - }  
669 516
670 - _getVideoPlayPath(_param){  
671 - if(_video_ape){  
672 - return _video_ape.getPlayVideoPath(_param); 517 + //Sass校验流程结束之后,开始加入MCU
  518 + _joinMCU() {
  519 + loger.log('加入底层MCU课堂.');
  520 + if (_mcu) {
  521 + _mcu.joinMCU(GlobalConfig.getClassInfo());
  522 + }
673 } 523 }
674 - }  
675 524
676 - _getVideoPublishPath(_param){  
677 - if(_video_ape){  
678 - return _video_ape.getPublishVideoPath(_param); 525 + // MCU 课堂成功
  526 + _mcuJoinMCUClassSuccessHandler(_data) {
  527 + loger.log('MCU 课堂成功.');
  528 + GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);
  529 +
  530 + //返回给客户端初始化成功的数据
  531 + let joinClassSuccessCallBackData = {};
  532 +
  533 + joinClassSuccessCallBackData.isRecordPlayBack=GlobalConfig.isRecordPlayBack;
  534 +
  535 + joinClassSuccessCallBackData.DOCServerIP = GlobalConfig.DOCServerIP;
  536 + joinClassSuccessCallBackData.DOCServerPort = GlobalConfig.DOCServerPort;
  537 +
  538 + joinClassSuccessCallBackData.classId = GlobalConfig.classId;
  539 + joinClassSuccessCallBackData.className = GlobalConfig.className;
  540 + joinClassSuccessCallBackData.h5Module = GlobalConfig.h5Module;
  541 + joinClassSuccessCallBackData.isHost = GlobalConfig.isHost;
  542 + joinClassSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;
  543 + joinClassSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;
  544 + joinClassSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;
  545 +
  546 + joinClassSuccessCallBackData.msType = GlobalConfig.msType;
  547 + joinClassSuccessCallBackData.nodeId = GlobalConfig.nodeId;
  548 + joinClassSuccessCallBackData.password = GlobalConfig.password;
  549 + joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;// 老师的默认是true
  550 + //GlobalConfig.passwordRequired 老师的默认是true
  551 + //GlobalConfig.portal=_data.portal;
  552 + joinClassSuccessCallBackData.role = GlobalConfig.role;
  553 + joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
  554 + joinClassSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;
  555 + joinClassSuccessCallBackData.userId = GlobalConfig.userId;
  556 + joinClassSuccessCallBackData.userName = GlobalConfig.userName;
  557 + joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
  558 + joinClassSuccessCallBackData.userType = GlobalConfig.userType;
  559 +
  560 + joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
  561 + joinClassSuccessCallBackData.classId = GlobalConfig.classId;
  562 + joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
  563 + joinClassSuccessCallBackData.userId = GlobalConfig.userId;
  564 + joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
  565 + joinClassSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_INTERACT;
  566 +
  567 + joinClassSuccessCallBackData.country = GlobalConfig.country;//国家
  568 + joinClassSuccessCallBackData.city = GlobalConfig.city;//城市
  569 + joinClassSuccessCallBackData.province = GlobalConfig.province;//服务商
  570 + joinClassSuccessCallBackData.isp = GlobalConfig.isp;//服务商
  571 +
  572 + loger.log('加入课堂成功');
  573 + console.log(joinClassSuccessCallBackData);
  574 +
  575 + //加入课堂成功,广播消息
  576 + this._emit(MessageTypes.CLASS_JOIN_SUCCESS, joinClassSuccessCallBackData);
  577 + }
  578 +
  579 + //Sass删除文档数据
  580 + _sassDeleteDocument(_param) {
  581 + if (!_mcu.connected) {
  582 + loger.warn(GlobalConfig.getCurrentStatus());
  583 + return;
  584 + }
  585 +
  586 + //判断传入的参数是否存在
  587 + if (_param == null || EngineUtils.isEmptyObject(_param)) {
  588 + loger.error('sassDeleteDocument失败,参数错误', _param);
  589 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);
  590 + return;
  591 + }
  592 + //判断必要的参数字段值
  593 + if (_param.itemIdx == null || isNaN(_param.itemIdx) || _param.docId == null || _param.docId == "") {
  594 + loger.error('sassDeleteDocument失败', _param);
  595 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);
  596 + return;
  597 + }
  598 + loger.log('_sassDeleteDocument', _param);
  599 +
  600 + if (_sass) {
  601 + _sass.sassDeleteDocument(_param);
  602 + }
679 } 603 }
680 - }  
681 - _getVideoAllChannelInfo(_param){  
682 - if(_video_ape){  
683 - return _video_ape.getAllChannelInfo(_param); 604 +
  605 + //Sass删除文档成功之后,同步删除MCU数据
  606 + _sassDeleteDocumentSuccess(_param) {
  607 + loger.log('sassDeleteDocumentSuccess', _param);
  608 + this._sendDocumentDelete(_param);
684 } 609 }
685 - }  
686 610
687 - _publishVideo(_param){  
688 - if(!_mcu.connected){  
689 - loger.warn(GlobalConfig.getCurrentStatus());  
690 - return; 611 + //ConferApe
  612 + //开始上课
  613 + _sendStartClass(_param) {
  614 + if (!_mcu.connected) {
  615 + loger.warn(GlobalConfig.getCurrentStatus());
  616 + return;
  617 + }
  618 +
  619 + if (_confer_ape) {
  620 + _confer_ape.startClass(_param);
  621 + }
691 } 622 }
692 - if(_video_ape){  
693 - return _video_ape.publishVideo(_param); 623 +
  624 + //暂停上课
  625 + _sendPauseClass(_param) {
  626 + if (!_mcu.connected) {
  627 + loger.warn(GlobalConfig.getCurrentStatus());
  628 + return;
  629 + }
  630 + if (_confer_ape) {
  631 + _confer_ape.pauseClass(_param);
  632 + }
694 } 633 }
695 - }  
696 634
697 - _stopPublishVideo(_param){  
698 - if(!_mcu.connected){  
699 - loger.warn(GlobalConfig.getCurrentStatus());  
700 - return; 635 + //停止上课
  636 + _sendCloseClass(_param) {
  637 + if (!_mcu.connected) {
  638 + loger.warn(GlobalConfig.getCurrentStatus());
  639 + return;
  640 + }
  641 + if (_confer_ape) {
  642 + _confer_ape.closeClass(_param);
  643 + }
701 } 644 }
702 - if(_video_ape){  
703 - return _video_ape.stopPublishVideo(_param); 645 +
  646 + // 离开课堂
  647 + _leaveClass() {
  648 + if (!_mcu.connected) {
  649 + loger.warn(GlobalConfig.getCurrentStatus());
  650 + return;
  651 + }
  652 +
  653 + //停止推流
  654 + if (_video_ape) {
  655 + _video_ape.stopPublishVideo();
  656 + }
  657 + if (_audio_ape) {
  658 + _audio_ape.stopPublishAudio();
  659 + }
  660 + //离开课堂
  661 + if (_confer_ape) {
  662 + _confer_ape.stopRecord();
  663 + _confer_ape.leaveClass();
  664 + }
  665 + //断开MCU连接
  666 + if (_mcu) {
  667 + _mcu.leaveMCU();
  668 + GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_3);
  669 + }
704 } 670 }
705 - }  
706 671
707 - //AudioApe  
708 - audioUpdate(_data){  
709 - //音频同步的消息发送改变,需要通知ferApe模块中的用户更新状态  
710 - if(_confer_ape){  
711 - _confer_ape.updaterRosterStatus(_data); 672 +
  673 + //ChatApe
  674 + // 发送聊天消息
  675 + _sendChatMsg(_messageInfo) {
  676 + if (!_mcu.connected) {
  677 + loger.warn(GlobalConfig.getCurrentStatus());
  678 + return;
  679 + }
  680 + if (_messageInfo === null || EngineUtils.isEmptyObject(_messageInfo)) {
  681 + loger.log('sendChatMsg 传递的参数不对', _messageInfo);
  682 + return;
  683 + }
  684 + if (_chat_ape) {
  685 + _chat_ape.sendChatMsg(_messageInfo);
  686 + }
712 } 687 }
713 - }  
714 688
715 - sendAudioCommandMsg(_param){  
716 - if(!_mcu.connected){  
717 - loger.warn(GlobalConfig.getCurrentStatus());  
718 - return; 689 + //VidoeApe
  690 + videoUpdate(_data) {
  691 + //视频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
  692 + if (_confer_ape) {
  693 + _confer_ape.updaterRosterStatus(_data);
  694 + }
  695 + }
  696 +
  697 + _sendVideoBroadcastMsg(_param) {
  698 + if (!_mcu.connected) {
  699 + loger.warn(GlobalConfig.getCurrentStatus());
  700 + return;
  701 + }
  702 + if (_video_ape) {
  703 + return _video_ape.sendVideoBroadcastMsg(_param);
  704 + }
719 } 705 }
720 - if(_audio_ape){  
721 - return _audio_ape.sendAudioBroadcastMsg(_param); 706 +
  707 + _getVideoPlayPath(_param) {
  708 + if (_video_ape) {
  709 + return _video_ape.getPlayVideoPath(_param);
  710 + }
722 } 711 }
723 - }  
724 712
725 - _getPlayAudioPath(_param){  
726 - if(_audio_ape){  
727 - return _audio_ape.getAudioPlayPath(_param); 713 + _getVideoPublishPath(_param) {
  714 + if (_video_ape) {
  715 + return _video_ape.getPublishVideoPath(_param);
  716 + }
728 } 717 }
729 - }  
730 718
731 - _getPublishAudioPath(_param){  
732 - if(_audio_ape){  
733 - return _audio_ape.getAudioPublishPath(_param); 719 + _getVideoAllChannelInfo(_param) {
  720 + if (_video_ape) {
  721 + return _video_ape.getAllChannelInfo(_param);
  722 + }
734 } 723 }
735 - }  
736 - _getAudioAllChannelInfo(_param){  
737 - if(_audio_ape){  
738 - return _audio_ape.getAllChannelInfo(_param); 724 +
  725 + _publishVideo(_param) {
  726 + if (!_mcu.connected) {
  727 + loger.warn(GlobalConfig.getCurrentStatus());
  728 + return;
  729 + }
  730 + if (_video_ape) {
  731 + return _video_ape.publishVideo(_param);
  732 + }
739 } 733 }
740 - }  
741 - _publishAudio(_param){  
742 - if(!_mcu.connected){  
743 - loger.warn(GlobalConfig.getCurrentStatus());  
744 - return; 734 +
  735 + _stopPublishVideo(_param) {
  736 + if (!_mcu.connected) {
  737 + loger.warn(GlobalConfig.getCurrentStatus());
  738 + return;
  739 + }
  740 + if (_video_ape) {
  741 + return _video_ape.stopPublishVideo(_param);
  742 + }
745 } 743 }
746 - if(_audio_ape){  
747 - return _audio_ape.publishAudio(_param); 744 +
  745 + //AudioApe
  746 + audioUpdate(_data) {
  747 + //音频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
  748 + if (_confer_ape) {
  749 + _confer_ape.updaterRosterStatus(_data);
  750 + }
748 } 751 }
749 - }  
750 752
751 - _stopPublishAudio(_param){  
752 - if(!_mcu.connected){  
753 - loger.warn(GlobalConfig.getCurrentStatus());  
754 - return; 753 + sendAudioCommandMsg(_param) {
  754 + if (!_mcu.connected) {
  755 + loger.warn(GlobalConfig.getCurrentStatus());
  756 + return;
  757 + }
  758 + if (_audio_ape) {
  759 + return _audio_ape.sendAudioBroadcastMsg(_param);
  760 + }
755 } 761 }
756 - if(_audio_ape){  
757 - return _audio_ape.stopPublishAudio(_param); 762 +
  763 + _getPlayAudioPath(_param) {
  764 + if (_audio_ape) {
  765 + return _audio_ape.getAudioPlayPath(_param);
  766 + }
758 } 767 }
759 - }  
760 768
  769 + _getPublishAudioPath(_param) {
  770 + if (_audio_ape) {
  771 + return _audio_ape.getAudioPublishPath(_param);
  772 + }
  773 + }
761 774
762 - //WhiteBoardApe  
763 - // 添加标注,发送信息  
764 - _sendInsertAnnotaion(_param){  
765 - if(!_mcu.connected){  
766 - loger.warn(GlobalConfig.getCurrentStatus());  
767 - return; 775 + _getAudioAllChannelInfo(_param) {
  776 + if (_audio_ape) {
  777 + return _audio_ape.getAllChannelInfo(_param);
  778 + }
768 } 779 }
769 - if(_whiteboard_ape){  
770 - _whiteboard_ape.sendInsetAnnotaion(_param);  
771 - }  
772 - }  
773 -  
774 - //删除标注,发送信息  
775 - _sendDeleteAnnotaion(_param){  
776 - if(!_mcu.connected){  
777 - loger.warn(GlobalConfig.getCurrentStatus());  
778 - return;  
779 - }  
780 - if(_whiteboard_ape){  
781 - _whiteboard_ape.sendDeleteAnnotaion(_param);  
782 - }  
783 - }  
784 - //删除当前页面上的所有标注  
785 - _sendDeleteCurPageAnnotation(_param){  
786 - if(!_mcu.connected){  
787 - loger.warn(GlobalConfig.getCurrentStatus());  
788 - return;  
789 - }  
790 - if(_whiteboard_ape){  
791 - _whiteboard_ape.sendDeleteCurPageAnnotation(_param);  
792 - }  
793 - }  
794 - //删除所有标注  
795 - _sendDeleteAllAnnotation(_param){  
796 - if(!_mcu.connected){  
797 - loger.warn(GlobalConfig.getCurrentStatus());  
798 - return;  
799 - }  
800 - if(_whiteboard_ape){  
801 - _whiteboard_ape.sendDeleteAllAnnotation(_param);  
802 - }  
803 - }  
804 - //返回上一步标注  
805 - _sendGotoPrev(_param){  
806 - if(_whiteboard_ape){  
807 - _whiteboard_ape.sendGotoPrev(_param);  
808 - }  
809 - }  
810 -  
811 -  
812 - //DocApe  
813 - //获取文档完整路径  
814 - _getDocImageFullPath(_param){  
815 - if(_doc_ape){  
816 - return _doc_ape.getDocImageFullPath(_param);  
817 - }else {  
818 - loger.error("文档模块还没有创建,无法获取");  
819 - return [];  
820 - }  
821 - }  
822 - _getDocPDFFullPath(_param){  
823 - if(_doc_ape){  
824 - return _doc_ape.getDocPDFFullPath(_param);  
825 - }else {  
826 - loger.error("文档模块还没有创建,无法获取");  
827 - return [];  
828 - }  
829 - }  
830 - //上传文档  
831 - _sendDocumentUpload(_param){  
832 - if(!_mcu.connected){  
833 - loger.warn(GlobalConfig.getCurrentStatus());  
834 - return;  
835 - }  
836 - if(_doc_ape){  
837 - _doc_ape.documentUpload(_param);  
838 - }  
839 - }  
840 - //切换文档  
841 - _sendDocumentSwitchDoc(_param){  
842 - if(!_mcu.connected){  
843 - loger.warn(GlobalConfig.getCurrentStatus());  
844 - return;  
845 - }  
846 - if(_doc_ape){  
847 - _doc_ape.documentSwitchDoc(_param);  
848 - }  
849 - }  
850 - //操作文档(翻页)  
851 - _sendDocumentSwitchPage(_param){  
852 - if(!_mcu.connected){  
853 - loger.warn(GlobalConfig.getCurrentStatus());  
854 - return;  
855 - }  
856 - if(_doc_ape){  
857 - _doc_ape.documentSwitchPage(_param);  
858 - }  
859 - }  
860 - //操作文档(缩放、滚动...)  
861 - _sendDocumentCommand(_param){  
862 - if(!_mcu.connected){  
863 - loger.warn(GlobalConfig.getCurrentStatus());  
864 - return;  
865 - }  
866 - if(_doc_ape){  
867 - _doc_ape.documentCommand(_param);  
868 - }  
869 - }  
870 - //删除文档  
871 - _sendDocumentDelete(_param){  
872 - if(!_mcu.connected){  
873 - loger.warn(GlobalConfig.getCurrentStatus());  
874 - return;  
875 - }  
876 - if(_doc_ape){  
877 - _doc_ape.documentDelete(_param);  
878 - }  
879 - }  
880 - //删除所有文档  
881 - _documentDeleteAll(_param){  
882 - if(!_mcu.connected){  
883 - loger.warn(GlobalConfig.getCurrentStatus());  
884 - return;  
885 - }  
886 - if(_doc_ape){  
887 - _doc_ape.documentDeleteAll(_param);  
888 - }  
889 - }  
890 -  
891 - //// 文档变更,白板也需要做处理  
892 - docUpdateHandler(_data) {  
893 - if(!_mcu.connected){  
894 - loger.warn(GlobalConfig.getCurrentStatus());  
895 - return;  
896 - }  
897 - loger.log('Doc UpdateId ->');  
898 - console.log(_data);  
899 - if(_whiteboard_ape){  
900 - _whiteboard_ape.docUpdateHandler(_data);  
901 - }  
902 - }  
903 -  
904 - //文档删除,白板也需要做处理  
905 - docDeleteHandler(_data){  
906 - if(_whiteboard_ape){  
907 - _whiteboard_ape.docDeleteHandler(_data);  
908 - }  
909 - }  
910 -  
911 - //文档加入频道成功,同步到MCU服务器上的数据  
912 - docJoinChannelSuccess(){  
913 - loger.log("docJoinChannelSuccess isHost=",GlobalConfig.isHost);  
914 - console.log(GlobalConfig.docListPrepare);  
915 - loger.log("docJoinChannelSuccess docListPrepare=");  
916 - //如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传  
917 - if(GlobalConfig.isHost){  
918 - for (let value of GlobalConfig.docListPrepare){  
919 - if(value){  
920 - /* //提前上传的文档文档信息的结构  
921 - {  
922 - "MD5": "f3feb3fac8cd3a953bded00e07a0c66b",  
923 - "absoluteLocation": "http://101.200.150.192/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",  
924 - "createUserID": "972",  
925 - "createUserIP": "114.241.81.175",  
926 - "createUserName": "base",  
927 - "dynamicPPT": 0,  
928 - "dynamicTransferStatic": "",  
929 - "id": "8ab3b0ed5a00f2fa015a0219a3df016c",  
930 - "meetingNumber": "",  
931 - "name": "McuClient_v.1.0.1_API.pdf",  
932 - "orderStr": "",  
933 - "pdfSize": 5,  
934 - "processEndTime": "2017-02-03 11:54:31",  
935 - "processRate": 0,  
936 - "processStartTime": "2017-02-03 11:54:27",  
937 - "relativeLocation": "/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",  
938 - "siteID": "h5test",  
939 - "size": 360920,  
940 - "status": 3,  
941 - "type": "pdf",  
942 - "uploadEndTime": "2017-02-03 11:54:27",  
943 - "uploadStartTime": "2017-02-03 11:54:27"  
944 - }*/  
945 -  
946 - loger.log("判断是否需要把提前上传的文档上传到mcu",value);  
947 - let paramInfo={  
948 - "pageNum": value.pdfSize,  
949 - "fileName": value.name,  
950 - "fileType": value.type,  
951 - "relativeUrl": value.relativeLocation,  
952 - "url": value.absoluteLocation,  
953 - "creatUserId":value.createUserID,  
954 - "docId": value.id,  
955 - "md5":value.MD5,  
956 - "visible": false  
957 - };  
958 -  
959 - this._sendDocumentUpload(paramInfo);  
960 - }  
961 - }  
962 - }  
963 - } 780 +
  781 + _publishAudio(_param) {
  782 + if (!_mcu.connected) {
  783 + loger.warn(GlobalConfig.getCurrentStatus());
  784 + return;
  785 + }
  786 + if (_audio_ape) {
  787 + return _audio_ape.publishAudio(_param);
  788 + }
  789 + }
  790 +
  791 + _stopPublishAudio(_param) {
  792 + if (!_mcu.connected) {
  793 + loger.warn(GlobalConfig.getCurrentStatus());
  794 + return;
  795 + }
  796 + if (_audio_ape) {
  797 + return _audio_ape.stopPublishAudio(_param);
  798 + }
  799 + }
  800 +
  801 +
  802 + //WhiteBoardApe
  803 + // 添加标注,发送信息
  804 + _sendInsertAnnotaion(_param) {
  805 + if (!_mcu.connected) {
  806 + loger.warn(GlobalConfig.getCurrentStatus());
  807 + return;
  808 + }
  809 + if (_whiteboard_ape) {
  810 + _whiteboard_ape.sendInsetAnnotaion(_param);
  811 + }
  812 + }
  813 +
  814 + //删除标注,发送信息
  815 + _sendDeleteAnnotaion(_param) {
  816 + if (!_mcu.connected) {
  817 + loger.warn(GlobalConfig.getCurrentStatus());
  818 + return;
  819 + }
  820 + if (_whiteboard_ape) {
  821 + _whiteboard_ape.sendDeleteAnnotaion(_param);
  822 + }
  823 + }
  824 +
  825 + //删除当前页面上的所有标注
  826 + _sendDeleteCurPageAnnotation(_param) {
  827 + if (!_mcu.connected) {
  828 + loger.warn(GlobalConfig.getCurrentStatus());
  829 + return;
  830 + }
  831 + if (_whiteboard_ape) {
  832 + _whiteboard_ape.sendDeleteCurPageAnnotation(_param);
  833 + }
  834 + }
  835 +
  836 + //删除所有标注
  837 + _sendDeleteAllAnnotation(_param) {
  838 + if (!_mcu.connected) {
  839 + loger.warn(GlobalConfig.getCurrentStatus());
  840 + return;
  841 + }
  842 + if (_whiteboard_ape) {
  843 + _whiteboard_ape.sendDeleteAllAnnotation(_param);
  844 + }
  845 + }
  846 +
  847 + //返回上一步标注
  848 + _sendGotoPrev(_param) {
  849 + if (_whiteboard_ape) {
  850 + _whiteboard_ape.sendGotoPrev(_param);
  851 + }
  852 + }
  853 +
  854 +
  855 + //DocApe
  856 + //获取文档完整路径
  857 + _getDocImageFullPath(_param) {
  858 + if (_doc_ape) {
  859 + return _doc_ape.getDocImageFullPath(_param);
  860 + } else {
  861 + loger.error("文档模块还没有创建,无法获取");
  862 + return [];
  863 + }
  864 + }
  865 +
  866 + _getDocPDFFullPath(_param) {
  867 + if (_doc_ape) {
  868 + return _doc_ape.getDocPDFFullPath(_param);
  869 + } else {
  870 + loger.error("文档模块还没有创建,无法获取");
  871 + return [];
  872 + }
  873 + }
  874 +
  875 + //上传文档
  876 + _sendDocumentUpload(_param) {
  877 + if (!_mcu.connected) {
  878 + loger.warn(GlobalConfig.getCurrentStatus());
  879 + return;
  880 + }
  881 + if (_doc_ape) {
  882 + _doc_ape.documentUpload(_param);
  883 + }
  884 + }
  885 +
  886 + //切换文档
  887 + _sendDocumentSwitchDoc(_param) {
  888 + if (!_mcu.connected) {
  889 + loger.warn(GlobalConfig.getCurrentStatus());
  890 + return;
  891 + }
  892 + if (_doc_ape) {
  893 + _doc_ape.documentSwitchDoc(_param);
  894 + }
  895 + }
  896 +
  897 + //操作文档(翻页)
  898 + _sendDocumentSwitchPage(_param) {
  899 + if (!_mcu.connected) {
  900 + loger.warn(GlobalConfig.getCurrentStatus());
  901 + return;
  902 + }
  903 + if (_doc_ape) {
  904 + _doc_ape.documentSwitchPage(_param);
  905 + }
  906 + }
  907 +
  908 + //操作文档(缩放、滚动...)
  909 + _sendDocumentCommand(_param) {
  910 + if (!_mcu.connected) {
  911 + loger.warn(GlobalConfig.getCurrentStatus());
  912 + return;
  913 + }
  914 + if (_doc_ape) {
  915 + _doc_ape.documentCommand(_param);
  916 + }
  917 + }
  918 +
  919 + //删除文档
  920 + _sendDocumentDelete(_param) {
  921 + if (!_mcu.connected) {
  922 + loger.warn(GlobalConfig.getCurrentStatus());
  923 + return;
  924 + }
  925 + if (_doc_ape) {
  926 + _doc_ape.documentDelete(_param);
  927 + }
  928 + }
  929 +
  930 + //删除所有文档
  931 + _documentDeleteAll(_param) {
  932 + if (!_mcu.connected) {
  933 + loger.warn(GlobalConfig.getCurrentStatus());
  934 + return;
  935 + }
  936 + if (_doc_ape) {
  937 + _doc_ape.documentDeleteAll(_param);
  938 + }
  939 + }
  940 +
  941 + //// 文档变更,白板也需要做处理
  942 + docUpdateHandler(_data) {
  943 + if (!_mcu.connected) {
  944 + loger.warn(GlobalConfig.getCurrentStatus());
  945 + return;
  946 + }
  947 + loger.log('Doc UpdateId ->');
  948 + console.log(_data);
  949 + if (_whiteboard_ape) {
  950 + _whiteboard_ape.docUpdateHandler(_data);
  951 + }
  952 + }
  953 +
  954 + //文档删除,白板也需要做处理
  955 + docDeleteHandler(_data) {
  956 + if (_whiteboard_ape) {
  957 + _whiteboard_ape.docDeleteHandler(_data);
  958 + }
  959 + }
  960 +
  961 + //文档加入频道成功,同步到MCU服务器上的数据
  962 + docJoinChannelSuccess() {
  963 + loger.log("docJoinChannelSuccess isHost=", GlobalConfig.isHost);
  964 + console.log(GlobalConfig.docListPrepare);
  965 + loger.log("docJoinChannelSuccess docListPrepare=");
  966 + //如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传
  967 + if (GlobalConfig.isHost) {
  968 + for (let value of GlobalConfig.docListPrepare) {
  969 + if (value) {
  970 + /* //提前上传的文档文档信息的结构
  971 + {
  972 + "MD5": "f3feb3fac8cd3a953bded00e07a0c66b",
  973 + "absoluteLocation": "http://101.200.150.192/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
  974 + "createUserID": "972",
  975 + "createUserIP": "114.241.81.175",
  976 + "createUserName": "base",
  977 + "dynamicPPT": 0,
  978 + "dynamicTransferStatic": "",
  979 + "id": "8ab3b0ed5a00f2fa015a0219a3df016c",
  980 + "meetingNumber": "",
  981 + "name": "McuClient_v.1.0.1_API.pdf",
  982 + "orderStr": "",
  983 + "pdfSize": 5,
  984 + "processEndTime": "2017-02-03 11:54:31",
  985 + "processRate": 0,
  986 + "processStartTime": "2017-02-03 11:54:27",
  987 + "relativeLocation": "/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
  988 + "siteID": "h5test",
  989 + "size": 360920,
  990 + "status": 3,
  991 + "type": "pdf",
  992 + "uploadEndTime": "2017-02-03 11:54:27",
  993 + "uploadStartTime": "2017-02-03 11:54:27"
  994 + }*/
  995 +
  996 + loger.log("判断是否需要把提前上传的文档上传到mcu", value);
  997 + let paramInfo = {
  998 + "pageNum": value.pdfSize,
  999 + "fileName": value.name,
  1000 + "fileType": value.type,
  1001 + "relativeUrl": value.relativeLocation,
  1002 + "url": value.absoluteLocation,
  1003 + "creatUserId": value.createUserID,
  1004 + "docId": value.id,
  1005 + "md5": value.MD5,
  1006 + "visible": false
  1007 + };
  1008 +
  1009 + this._sendDocumentUpload(paramInfo);
  1010 + }
  1011 + }
  1012 + }
  1013 + }
  1014 +
  1015 + //录制回放相关的处理------------------------------------------------
  1016 + //录制回放初始化
  1017 + _initRecordPlayback(_param){
  1018 + //{"classId":"1653304953","portal":"112.126.80.182:80","userRole":"normal","userId":0}
  1019 + if (_param == null) {
  1020 + loger.error('录制回放初始化失败,参数错误');
  1021 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED);
  1022 + return;
  1023 + }
  1024 + //判断必要的参数字段值
  1025 + if (_param.classId == null || isNaN(_param.classId) || _param.portal == null || _param.portal == "") {
  1026 + loger.error('录制回放初始化失败', _param);
  1027 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED);
  1028 + return;
  1029 + }
  1030 + loger.log('录制回放', _param);
  1031 +
  1032 + //保存参数
  1033 + GlobalConfig.isRecordPlayBack=true;//设置为录制回放状态
  1034 + GlobalConfig.classId = parseInt(_param.classId);
  1035 + GlobalConfig.portal = _param.portal;
  1036 + GlobalConfig.userRole =ApeConsts.normal;//*************很重要,录制回放的时候,身份模式是普通人********
  1037 + GlobalConfig.userId = _param.userId || "0";
  1038 + GlobalConfig.userName = _param.userName || "";
  1039 +
  1040 + //获取课堂最完整的数据,录制回放需要获取课堂数据
  1041 + if (_sass) {
  1042 + _sass.getClassParam();
  1043 + }
  1044 + }
  1045 +
  1046 + //开始录制回放
  1047 + _startRecordPlayback(_param) {
  1048 + if (_parseBuf) {
  1049 + _parseBuf.startRecordPlayback(_param);
  1050 + }
  1051 + }
  1052 + //停止录制回放
  1053 + _stopRecordPlayback(_param) {
  1054 + if (_parseBuf) {
  1055 + _parseBuf.stopRecordPlayback(_param);
  1056 + }
  1057 + }
  1058 + //暂停录制回放
  1059 + _pauseRecordPlayback(_param) {
  1060 + if (_parseBuf) {
  1061 + _parseBuf.pauseRecordPlayback(_param);
  1062 + }
  1063 + }
  1064 + //seek录制回放
  1065 + _seekRecordPlayback(_param) {
  1066 + if (_parseBuf) {
  1067 + _parseBuf.seekRecordPlayback(_param);
  1068 + }
  1069 + }
  1070 +
  1071 + _writeBuffer(_param) {
  1072 + if (_parseBuf) {
  1073 + _parseBuf.writeBuffer(_param);
  1074 + }
  1075 + }
  1076 +
  1077 + _addBuffer(_arrayBuffer) {
  1078 + if (_parseBuf) {
  1079 + _parseBuf.addBuffer(_arrayBuffer);
  1080 + }
  1081 + }
  1082 +
  1083 + _read(_param) {
  1084 + if (_parseBuf) {
  1085 + _parseBuf.read(_param);
  1086 + }
  1087 + }
  1088 + // MCU 课堂成功
  1089 + _joinRecordPlaybackSuccessHandler(_data) {
  1090 + loger.log('加入录制回放成功.');
  1091 + GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);
  1092 +
  1093 + //返回给客户端初始化成功的数据
  1094 + let joinClassSuccessCallBackData = {};
  1095 +
  1096 + joinClassSuccessCallBackData.isRecordPlayBack=GlobalConfig.isRecordPlayBack;
  1097 +
  1098 + joinClassSuccessCallBackData.DOCServerIP = GlobalConfig.DOCServerIP;
  1099 + joinClassSuccessCallBackData.DOCServerPort = GlobalConfig.DOCServerPort;
  1100 +
  1101 + joinClassSuccessCallBackData.classId = GlobalConfig.classId;
  1102 + joinClassSuccessCallBackData.className = GlobalConfig.className;
  1103 + joinClassSuccessCallBackData.h5Module = GlobalConfig.h5Module;
  1104 + joinClassSuccessCallBackData.isHost = GlobalConfig.isHost;//
  1105 + joinClassSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;
  1106 + joinClassSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;
  1107 + joinClassSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;
  1108 +
  1109 + joinClassSuccessCallBackData.msType = GlobalConfig.msType;
  1110 + joinClassSuccessCallBackData.nodeId = GlobalConfig.nodeId;
  1111 + joinClassSuccessCallBackData.password = GlobalConfig.password;
  1112 + joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;// 老师的默认是true
  1113 + //GlobalConfig.passwordRequired 老师的默认是true
  1114 + //GlobalConfig.portal=_data.portal;
  1115 + joinClassSuccessCallBackData.role = GlobalConfig.role;
  1116 + joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
  1117 + joinClassSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;
  1118 + joinClassSuccessCallBackData.userId = GlobalConfig.userId;
  1119 + joinClassSuccessCallBackData.userName = GlobalConfig.userName;
  1120 + joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
  1121 + joinClassSuccessCallBackData.userType = GlobalConfig.userType;
  1122 +
  1123 + joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
  1124 + joinClassSuccessCallBackData.classId = GlobalConfig.classId;
  1125 + joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
  1126 + joinClassSuccessCallBackData.userId = GlobalConfig.userId;
  1127 + joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
  1128 + joinClassSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_INTERACT;
  1129 +
  1130 + joinClassSuccessCallBackData.country = GlobalConfig.country;//国家
  1131 + joinClassSuccessCallBackData.city = GlobalConfig.city;//城市
  1132 + joinClassSuccessCallBackData.province = GlobalConfig.province;//服务商
  1133 + joinClassSuccessCallBackData.isp = GlobalConfig.isp;//服务商
  1134 +
  1135 + console.log(joinClassSuccessCallBackData);
  1136 + //和加入课堂成功使用同样的消息处理
  1137 + this._emit(MessageTypes.CLASS_JOIN_SUCCESS, joinClassSuccessCallBackData);
  1138 + }
  1139 +
964 } 1140 }
@@ -234,9 +234,9 @@ class GlobalConfig { @@ -234,9 +234,9 @@ class GlobalConfig {
234 } 234 }
235 235
236 GlobalConfig.statusCode_0={"code":0,message:"SDK 未初始化"}; 236 GlobalConfig.statusCode_0={"code":0,message:"SDK 未初始化"};
237 -GlobalConfig.statusCode_1={"code":1,message:"未加入会议"};  
238 -GlobalConfig.statusCode_2={"code":2,message:"已经加入会议"};  
239 -GlobalConfig.statusCode_3={"code":3,message:"已经离开会议"}; 237 +GlobalConfig.statusCode_1={"code":1,message:"未加入课堂"};
  238 +GlobalConfig.statusCode_2={"code":2,message:"已经加入课堂"};
  239 +GlobalConfig.statusCode_3={"code":3,message:"已经离开课堂"};
240 GlobalConfig.statusCode_4={"code":4,message:"未知状态"}; 240 GlobalConfig.statusCode_4={"code":4,message:"未知状态"};
241 241
242 GlobalConfig.md5=""; 242 GlobalConfig.md5="";
@@ -303,7 +303,7 @@ GlobalConfig.recordFileName="";//录制的文件名,如 果为空就创建一个 @@ -303,7 +303,7 @@ GlobalConfig.recordFileName="";//录制的文件名,如 果为空就创建一个
303 GlobalConfig.recordDownloadUrl="";//下载地址 303 GlobalConfig.recordDownloadUrl="";//下载地址
304 GlobalConfig.recordReplaytickValues={}; // 滚动条关键点,用于快进快退 304 GlobalConfig.recordReplaytickValues={}; // 滚动条关键点,用于快进快退
305 305
306 -GlobalConfig.updateClassInfoDelay=30;//(秒),每隔30秒同步一次会议状态的并保存到Sass 306 +GlobalConfig.updateClassInfoDelay=30;//(秒),每隔30秒同步一次课堂状态的并保存到Sass
307 //GlobalConfig.serverTimestamp=0;//当前的系统时间戳 用get set 获取 307 //GlobalConfig.serverTimestamp=0;//当前的系统时间戳 用get set 获取
308 308
309 309
@@ -313,7 +313,7 @@ GlobalConfig.activeDocCurPage=1;//当前激活的文档的当前页 @@ -313,7 +313,7 @@ GlobalConfig.activeDocCurPage=1;//当前激活的文档的当前页
313 313
314 314
315 315
316 -GlobalConfig.classAllParam={};//Sass直接返回的所有会议信息(最全) 316 +GlobalConfig.classAllParam={};//Sass直接返回的所有课堂信息(最全)
317 GlobalConfig.classDetail={};//Sass直接返回的当前课堂基本信息 317 GlobalConfig.classDetail={};//Sass直接返回的当前课堂基本信息
318 318
319 GlobalConfig.docListPrepare=[]; // 已经提前上传的文档,进入课堂后需要自动加载 319 GlobalConfig.docListPrepare=[]; // 已经提前上传的文档,进入课堂后需要自动加载
@@ -331,4 +331,6 @@ GlobalConfig.city ="";//城市 @@ -331,4 +331,6 @@ GlobalConfig.city ="";//城市
331 GlobalConfig.province = "";//服务商 331 GlobalConfig.province = "";//服务商
332 GlobalConfig.isp ="";//服务商 332 GlobalConfig.isp ="";//服务商
333 333
  334 +GlobalConfig.isRecordPlayBack=false;//是否是录制回放,默认是否
  335 +
334 export default GlobalConfig; 336 export default GlobalConfig;
@@ -9,11 +9,11 @@ function MessageTypes() {} @@ -9,11 +9,11 @@ function MessageTypes() {}
9 MessageTypes.CLASS_INIT_SUCCESS="class_init_success";//'class.init.success';//初始化成功 9 MessageTypes.CLASS_INIT_SUCCESS="class_init_success";//'class.init.success';//初始化成功
10 //MessageTypes.CLASS_INIT_FAILED='class.init.failed';//初始化失败 10 //MessageTypes.CLASS_INIT_FAILED='class.init.failed';//初始化失败
11 11
12 -//加入会议相关事件定义 12 +//加入课堂相关事件定义
13 MessageTypes.CLASS_JOIN_MCU_SUCCESS ="class_join_mcu_success"// 'join.mcu.success'; 13 MessageTypes.CLASS_JOIN_MCU_SUCCESS ="class_join_mcu_success"// 'join.mcu.success';
14 //MessageTypes.CLASS_JOIN_FAILED = 'join.class.failed'; 14 //MessageTypes.CLASS_JOIN_FAILED = 'join.class.failed';
15 15
16 -//会议信息和操作事件定义 16 +//课堂信息和操作事件定义
17 //MessageTypes.CLASS_SHOW_DETAIL = 'class_detail.message'; 17 //MessageTypes.CLASS_SHOW_DETAIL = 'class_detail.message';
18 MessageTypes.CLASS_JOIN_SUCCESS ="class_join_success"// 'join.class.success'; 18 MessageTypes.CLASS_JOIN_SUCCESS ="class_join_success"// 'join.class.success';
19 MessageTypes.CLASS_UPDATE_ROSTER_NUM ="class_update_roster_num";// 'roster_num.message'; 19 MessageTypes.CLASS_UPDATE_ROSTER_NUM ="class_update_roster_num";// 'roster_num.message';
@@ -21,9 +21,9 @@ MessageTypes.CLASS_INSERT_ROSTER ="class_insert_roster";// 'roster.insert.messag @@ -21,9 +21,9 @@ MessageTypes.CLASS_INSERT_ROSTER ="class_insert_roster";// 'roster.insert.messag
21 MessageTypes.CLASS_DELETE_ROSTER ="class_delete_roster"// 'roster.delete.message'; 21 MessageTypes.CLASS_DELETE_ROSTER ="class_delete_roster"// 'roster.delete.message';
22 MessageTypes.CLASS_NONENTITY_ROSTER ="class_nonenetity_roster";// 'roster.nonentity.message'; 22 MessageTypes.CLASS_NONENTITY_ROSTER ="class_nonenetity_roster";// 'roster.nonentity.message';
23 23
24 -MessageTypes.CLASS_EXIT ="class_exit";// 'class.exit';//退出 关闭会议  
25 -MessageTypes.CLASS_UPTATE_STATUS ="class_update_status";// 'class.update.status';//更新会议状态信息  
26 -MessageTypes.CLASS_STATUS_INFO_CHANGE="class_status_info_change";// 'class.status.info.change';//会议状态信息发生改变,需要保存数据到sass和同步MCU 24 +MessageTypes.CLASS_EXIT ="class_exit";// 'class.exit';//退出 关闭课堂
  25 +MessageTypes.CLASS_UPTATE_STATUS ="class_update_status";// 'class.update.status';//更新课堂状态信息
  26 +MessageTypes.CLASS_STATUS_INFO_CHANGE="class_status_info_change";// 'class.status.info.change';//课堂状态信息发生改变,需要保存数据到sass和同步MCU
27 27
28 MessageTypes.CLASS_UPDATE_TIMER="class_update_timer";//'class.update.timer';//更新当前上课的时间 28 MessageTypes.CLASS_UPDATE_TIMER="class_update_timer";//'class.update.timer';//更新当前上课的时间
29 29
@@ -37,13 +37,13 @@ MessageTypes.CHAT_RECEIVE ="chat_receive_message";// 'chat.receive'; @@ -37,13 +37,13 @@ MessageTypes.CHAT_RECEIVE ="chat_receive_message";// 'chat.receive';
37 //视频模块事件定义 37 //视频模块事件定义
38 MessageTypes.VIDEO_PLAY ="video_play";// 'video.play';//播放视频 38 MessageTypes.VIDEO_PLAY ="video_play";// 'video.play';//播放视频
39 MessageTypes.VIDEO_STOP ="video_stop"; //'video.stop';//停止视频 39 MessageTypes.VIDEO_STOP ="video_stop"; //'video.stop';//停止视频
40 -MessageTypes.VIDEO_UPDATE ="video_update";// //这个监听事件不能删除,需要通知会议模块,检查channel占用(内部使用) 40 +MessageTypes.VIDEO_UPDATE ="video_update";// //这个监听事件不能删除,需要通知课堂模块,检查channel占用(内部使用)
41 MessageTypes.VIDEO_BROADCAST= "video_broadcast";//'video.broadcast'; 41 MessageTypes.VIDEO_BROADCAST= "video_broadcast";//'video.broadcast';
42 42
43 //音频模块事件定义 43 //音频模块事件定义
44 MessageTypes.AUDIO_PLAY ="audio_play";// 'audio.play';//播放 44 MessageTypes.AUDIO_PLAY ="audio_play";// 'audio.play';//播放
45 MessageTypes.AUDIO_STOP = "audio_stop";//'audio.stop';//停止 45 MessageTypes.AUDIO_STOP = "audio_stop";//'audio.stop';//停止
46 -MessageTypes.AUDIO_UPDATE = "audio_update";//这个监听事件不能删除,需要通知会议模块,检查channel占用(内部使用) 46 +MessageTypes.AUDIO_UPDATE = "audio_update";//这个监听事件不能删除,需要通知课堂模块,检查channel占用(内部使用)
47 MessageTypes.AUDIO_BROADCAST= "audio_broadcast";//'audio.broadcast'; 47 MessageTypes.AUDIO_BROADCAST= "audio_broadcast";//'audio.broadcast';
48 48
49 49
@@ -57,15 +57,12 @@ MessageTypes.DOC_UPDATE ="document_update";// 'document.update';//更新文档( @@ -57,15 +57,12 @@ MessageTypes.DOC_UPDATE ="document_update";// 'document.update';//更新文档(
57 //MessageTypes.DOC_DELETE='document.delete';//删除文档 57 //MessageTypes.DOC_DELETE='document.delete';//删除文档
58 //MessageTypes.DOC_ANNOTATION = 'document.annotation';//笔记 58 //MessageTypes.DOC_ANNOTATION = 'document.annotation';//笔记
59 59
60 -  
61 -  
62 //白板笔记事件定义 60 //白板笔记事件定义
63 MessageTypes.WHITEBOARD_ANNOTATION_UPDATE ="whiteboard_annotation_update";// 'whiteboard.annotation.update'; 61 MessageTypes.WHITEBOARD_ANNOTATION_UPDATE ="whiteboard_annotation_update";// 'whiteboard.annotation.update';
64 //MessageTypes.WHITEBOARD_ANNOTAION_INSERT = 'whiteboard.annotation.insert'; 62 //MessageTypes.WHITEBOARD_ANNOTAION_INSERT = 'whiteboard.annotation.insert';
65 //MessageTypes.WHITEBOARD_ANNOTAION_DELETE = 'whiteboard.annotation.delete'; 63 //MessageTypes.WHITEBOARD_ANNOTAION_DELETE = 'whiteboard.annotation.delete';
66 //MessageTypes.WHITEBOARD_ANNOTATION_CLEAR = 'whiteboard.annotation.clear'; 64 //MessageTypes.WHITEBOARD_ANNOTATION_CLEAR = 'whiteboard.annotation.clear';
67 65
68 -  
69 //错误事件定义 66 //错误事件定义
70 MessageTypes.MCU_ERROR ="mcu_error";//"mcuError";//MCU错误(内部使用) 67 MessageTypes.MCU_ERROR ="mcu_error";//"mcuError";//MCU错误(内部使用)
71 MessageTypes.ERROR_EVENT="error_event";//外部监听错误的消息ID(外部使用) 68 MessageTypes.ERROR_EVENT="error_event";//外部监听错误的消息ID(外部使用)
@@ -73,7 +70,7 @@ MessageTypes.ERROR_EVENT="error_event";//外部监听错误的消息ID(外部使 @@ -73,7 +70,7 @@ MessageTypes.ERROR_EVENT="error_event";//外部监听错误的消息ID(外部使
73 70
74 //---------------错误消息 ErrorCode 定义------------------------------------------------- 71 //---------------错误消息 ErrorCode 定义-------------------------------------------------
75 72
76 -//会议初始化失败的几种情况 73 +//课堂初始化失败的几种情况
77 MessageTypes.ERR_CLASS_INIT_PARAM=100;//初始化参数错误 74 MessageTypes.ERR_CLASS_INIT_PARAM=100;//初始化参数错误
78 MessageTypes.ERR_CLASS_INIT_NETWORK=101;//初始化网络错误 75 MessageTypes.ERR_CLASS_INIT_NETWORK=101;//初始化网络错误
79 MessageTypes.ERR_CLASS_INIT_PROTOCOL=102;//初始化协议错误 76 MessageTypes.ERR_CLASS_INIT_PROTOCOL=102;//初始化协议错误
@@ -83,11 +80,11 @@ MessageTypes.ERR_CLASS_INIT_FAILED_2=105;//初始化验证失败,无效的课堂 @@ -83,11 +80,11 @@ MessageTypes.ERR_CLASS_INIT_FAILED_2=105;//初始化验证失败,无效的课堂
83 MessageTypes.ERR_CLASS_INIT_FAILED_3=106;//初始化验证失败,没有对应的站点 80 MessageTypes.ERR_CLASS_INIT_FAILED_3=106;//初始化验证失败,没有对应的站点
84 MessageTypes.ERR_CLASS_INIT_FAILED_4=107;//初始化验证失败,站点已过期 81 MessageTypes.ERR_CLASS_INIT_FAILED_4=107;//初始化验证失败,站点已过期
85 82
86 -//加入会议失败的几种情况  
87 -MessageTypes.ERR_CLASS_JOIN_NETWORK=200;//加入会议网络错误  
88 -MessageTypes.ERR_CLASS_JOIN_PROTOCOL=201;//加入会议化协议错误  
89 -MessageTypes.ERR_CLASS_JOIN_FAILED=202;//加入会议化异常错误  
90 -MessageTypes.ERR_CLASS_JOIN_PARAM=203;//加入会议参数错误 83 +//加入课堂失败的几种情况
  84 +MessageTypes.ERR_CLASS_JOIN_NETWORK=200;//加入课堂网络错误
  85 +MessageTypes.ERR_CLASS_JOIN_PROTOCOL=201;//加入课堂化协议错误
  86 +MessageTypes.ERR_CLASS_JOIN_FAILED=202;//加入课堂化异常错误
  87 +MessageTypes.ERR_CLASS_JOIN_PARAM=203;//加入课堂参数错误
91 MessageTypes.ERR_CLASS_JOIN_FULL=204;//人数已满 88 MessageTypes.ERR_CLASS_JOIN_FULL=204;//人数已满
92 MessageTypes.ERR_CLASS_MD5_WRONG=205;//MD5验证失败 89 MessageTypes.ERR_CLASS_MD5_WRONG=205;//MD5验证失败
93 MessageTypes.ERR_CLASS_PASSWORD_WRONG=206;//密码错误 90 MessageTypes.ERR_CLASS_PASSWORD_WRONG=206;//密码错误
@@ -98,7 +95,7 @@ MessageTypes.ERR_GET_CLASS_DETAIL=300;//获取classDetail失败 @@ -98,7 +95,7 @@ MessageTypes.ERR_GET_CLASS_DETAIL=300;//获取classDetail失败
98 MessageTypes.ERR_GET_CLASS_PARAML=301;//获取ClassParam失败 95 MessageTypes.ERR_GET_CLASS_PARAML=301;//获取ClassParam失败
99 96
100 //APE 97 //APE
101 -MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN=500;//APE在sdk为初始化或未加入会议之前调用发送数据接口 98 +MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN=500;//APE在sdk为初始化或未加入课堂之前调用发送数据接口
102 MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG=501;//APE在接口调用时参数错误 99 MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG=501;//APE在接口调用时参数错误
103 100
104 //DOC 101 //DOC
@@ -110,10 +107,15 @@ MessageTypes.ERR_SDK_FAILED=700;// sdk还没初始化 @@ -110,10 +107,15 @@ MessageTypes.ERR_SDK_FAILED=700;// sdk还没初始化
110 MessageTypes.ERR_INTERFACE_NONE=701;//调用的接口不存在 107 MessageTypes.ERR_INTERFACE_NONE=701;//调用的接口不存在
111 MessageTypes.ERR_INTERFACE_PARAMS_ERROR=702;//调用的接口,传递的参数不正确 108 MessageTypes.ERR_INTERFACE_PARAMS_ERROR=702;//调用的接口,传递的参数不正确
112 109
  110 +
  111 +MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED=910;//初始化录制回放失败
  112 +MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED=911;//获取录制回放数据失败
  113 +
  114 +
113 MessageTypes.ERR_NETWORK=10000;//网络错误 115 MessageTypes.ERR_NETWORK=10000;//网络错误
114 MessageTypes.ERR_UNKNOWN=10001;//未知错误 116 MessageTypes.ERR_UNKNOWN=10001;//未知错误
115 117
116 -MessageTypes.ERR_SOCKET_DISCONNECT=20000;//MCU断开连接,已经离开会议 118 +MessageTypes.ERR_SOCKET_DISCONNECT=20000;//MCU断开连接,已经离开课堂
117 119
118 //---------------错误消息 Error Reson 定义------------------------------------------------- 120 //---------------错误消息 Error Reson 定义-------------------------------------------------
119 MessageTypes.ErrorReson={}; 121 MessageTypes.ErrorReson={};
@@ -128,11 +130,11 @@ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_3]="初始化验证 @@ -128,11 +130,11 @@ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_3]="初始化验证
128 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_4]="初始化验证失败,站点已过期"; 130 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_4]="初始化验证失败,站点已过期";
129 131
130 132
131 -//加入会议失败的几种情况  
132 -MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_NETWORK]="加入会议网络错误";  
133 -MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PROTOCOL]="加入会议化协议错误";  
134 -MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_FAILED]="加入会议化异常错误";  
135 -MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PARAM]="加入会议参数错误"; 133 +//加入课堂失败的几种情况
  134 +MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_NETWORK]="加入课堂网络错误";
  135 +MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PROTOCOL]="加入课堂化协议错误";
  136 +MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_FAILED]="加入课堂化异常错误";
  137 +MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PARAM]="加入课堂参数错误";
136 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_FULL]="人数已满"; 138 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_FULL]="人数已满";
137 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_MD5_WRONG]="MD5验证失败"; 139 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_MD5_WRONG]="MD5验证失败";
138 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_PASSWORD_WRONG]="密码错误"; 140 MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_PASSWORD_WRONG]="密码错误";
@@ -144,7 +146,7 @@ MessageTypes.ErrorReson[MessageTypes.ERR_GET_CLASS_DETAIL]="获取classDetail失 @@ -144,7 +146,7 @@ MessageTypes.ErrorReson[MessageTypes.ERR_GET_CLASS_DETAIL]="获取classDetail失
144 MessageTypes.ErrorReson[MessageTypes.ERR_GET_CLASS_PARAML]="获取ClassParam失败"; 146 MessageTypes.ErrorReson[MessageTypes.ERR_GET_CLASS_PARAML]="获取ClassParam失败";
145 147
146 //APE 148 //APE
147 -MessageTypes.ErrorReson[MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN]="APE在sdk为初始化或未加入会议之前调用发送数据接口"; 149 +MessageTypes.ErrorReson[MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN]="APE在sdk为初始化或未加入课堂之前调用发送数据接口";
148 MessageTypes.ErrorReson[MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG]="APE在接口调用时参数错误"; 150 MessageTypes.ErrorReson[MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG]="APE在接口调用时参数错误";
149 151
150 //DOC 152 //DOC
@@ -155,10 +157,16 @@ MessageTypes.ErrorReson[MessageTypes.ERR_SDK_FAILED]="sdk还没初始化"; @@ -155,10 +157,16 @@ MessageTypes.ErrorReson[MessageTypes.ERR_SDK_FAILED]="sdk还没初始化";
155 MessageTypes.ErrorReson[MessageTypes.ERR_INTERFACE_NONE]="调用的接口不存在"; 157 MessageTypes.ErrorReson[MessageTypes.ERR_INTERFACE_NONE]="调用的接口不存在";
156 MessageTypes.ErrorReson[MessageTypes.ERR_INTERFACE_PARAMS_ERROR]="调用的接口,传递的参数不正确"; 158 MessageTypes.ErrorReson[MessageTypes.ERR_INTERFACE_PARAMS_ERROR]="调用的接口,传递的参数不正确";
157 159
  160 +
  161 +MessageTypes.ErrorReson[MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED]="初始化录制回放失败";
  162 +MessageTypes.ErrorReson[MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED]="获取录制回放数据失败";
  163 +
  164 +
  165 +
158 MessageTypes.ErrorReson[MessageTypes.ERR_NETWORK]="网络错误"; 166 MessageTypes.ErrorReson[MessageTypes.ERR_NETWORK]="网络错误";
159 MessageTypes.ErrorReson[MessageTypes.ERR_UNKNOWN]="未知错误"; 167 MessageTypes.ErrorReson[MessageTypes.ERR_UNKNOWN]="未知错误";
160 168
161 -MessageTypes.ErrorReson[MessageTypes.ERR_SOCKET_DISCONNECT]="MCU断开连接,已经离开会议"; 169 +MessageTypes.ErrorReson[MessageTypes.ERR_SOCKET_DISCONNECT]="MCU断开连接,已经离开课堂";
162 170
163 171
164 172
  1 +import ByteBuffer from 'libs/bytebuffer.min';
  2 +import Emiter from 'Emiter';
  3 +import MessageTypes from 'MessageTypes';
  4 +import Loger from 'Loger';
  5 +
  6 +import pdu from 'pdus/index';
  7 +import PduType from 'pdus/PduType';
  8 +import PduConsts from 'pdus/PduConsts';
  9 +import ApeConsts from 'apes/ApeConsts';
  10 +import ArrayBufferUtil from 'libs/ArrayBufferUtil';
  11 +import Base64 from 'base64-js';
  12 +import GlobalConfig from 'GlobalConfig';
  13 +import EngineUtils from 'EngineUtils';
  14 +
  15 +let parseBuffer;
  16 +
  17 +// 日志对象
  18 +const loger = Loger.getLoger('RecordPlayBackParse');
  19 +
  20 +class RecordPlayBackParse extends Emiter {
  21 + constructor() {
  22 + super();
  23 + loger.log("RecordPlayBackParse");
  24 + parseBuffer = new ByteBuffer( ByteBuffer.DEFAULT_CAPACITY,ByteBuffer.LITTLE_ENDIAN);
  25 + parseBuffer.clear();
  26 + console.log(parseBuffer);
  27 + this._apes = {};
  28 + }
  29 + //method--------------------内部---------------------------------------------
  30 + // 注册Ape
  31 + registerApe(ape) {
  32 + this._apes[ape._session_id] = ape;
  33 + }
  34 +
  35 + // 录制回放EverSocket底层消息处理
  36 + _everSocketMsgReceivedHandler(data) {
  37 + let pduMsg = pdu.decode_pdu(data);
  38 + let pduType = pduMsg.get("type");
  39 + let pduData = pduMsg.get("data");
  40 + //*************非常重要******************
  41 + //客户端发送的所有125消息,MCU收到之后会痛120把消息返回给客户端,
  42 + //所以需要把125消息type转换为120,因为MCU在录制的时候是直接录制客户端发送的消息而不是MCU转换之后的
  43 + if(pduType==PduType.RCPDU_UNIFORM_SEND_DATA_REQUEST){
  44 + pduMsg.type=PduType.RCPDU_SEND_DATA_REQUEST;
  45 + pduType=PduType.RCPDU_SEND_DATA_REQUEST;
  46 + }
  47 + loger.log('pduType',pduType);
  48 + switch (pduType) {
  49 + case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE:
  50 + //加入课堂请求返回数据处理
  51 + let joinConfPdu = pdu['RCConferenceJoinResponsePdu'].decode(pduData);
  52 + let pduResultCode = joinConfPdu.result;
  53 + loger.warn('RCPDU_CONNECT_PROVIDER_RESPONSE ->pduResultCode:' + pduResultCode);
  54 + switch (pduResultCode) {
  55 + case PduConsts.RET_SUCCESS:
  56 + //加入成功
  57 + this._updateMCUConfInfoDescription(joinConfPdu.classDescription);
  58 + this._emit(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this.classInfo);
  59 + break;
  60 + case PduConsts.RET_FULL_CAPACITY:
  61 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FULL);
  62 + break;
  63 + default:
  64 + loger.warn('JoinConfPdu-未知类型-等待处理.', pduResultCode);
  65 + break
  66 + }
  67 + break;
  68 + case PduType.RCPDU_SEND_DATA_REQUEST:
  69 + //先判断当前消息属于哪个APE 根据 sessionId来判断
  70 + let ape = this._apes[pduMsg.sessionId];
  71 + let sessionLabel = ApeConsts(pduMsg.sessionId);
  72 + if (ape) {
  73 + let subTypeLabel = pdu.id2type(pduMsg.subType);
  74 + //loger.log('MCU-SecondLayer封装消息', 'sessionId', sessionLabel, pduMsg.sessionId, 'subtype', subTypeLabel, pduMsg.subType);
  75 + //ape广播事件,只要ape中监听就能收到
  76 + ape._emit(pduMsg.subType, pduMsg.data);
  77 + } else {
  78 + loger.warn(sessionLabel + '尚未注册');
  79 + }
  80 + break;
  81 + default:
  82 + loger.warn('PDU-未知类型-等待处理.', pduType);
  83 + }
  84 + }
  85 +
  86 + //method------------外部接口-------------------------------------
  87 + //加载录制文件
  88 + readyRecordPlay(){
  89 + loger.log("读取回放数据");
  90 + //let url = `http://123.56.73.119:80/h5dev/20170306/1357644520_20170306.rec`;
  91 + let url=`http://${ GlobalConfig.RecordServerIP}:${ GlobalConfig.RecordServerPort}/${GlobalConfig.recordFileName}`;
  92 + console.log(url);
  93 + fetch(url, {
  94 + timeout: 90000
  95 + })
  96 + .then(ret => {
  97 + if (ret.ok) {
  98 + return ret.arrayBuffer();
  99 + } else {
  100 + loger.error(`读取回放数据-网络异常.状态码:${ret.status}`);
  101 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED);
  102 + throw '';
  103 + }
  104 + })
  105 + .then(ret => {
  106 + if (ret) {
  107 + loger.log('读取回放数据-完成');
  108 + this._loadRecordDataSuccess(ret);
  109 + } else {
  110 + loger.warn('读取回放数据-失败.');
  111 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED);
  112 + }
  113 + })
  114 + .catch(err => {
  115 + loger.error(`读取回放数据.状态码:${err}`);
  116 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_RECORD_PLAY_BACK_DATA_FAILED);
  117 + });
  118 + }
  119 +
  120 + _loadRecordDataSuccess(arrayBuffer){
  121 + loger.log("获取录制回放数据的长度",arrayBuffer.byteLength);
  122 + if(parseBuffer){
  123 + parseBuffer.clear();
  124 + parseBuffer.append(arrayBuffer);
  125 + }
  126 + this._emit(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS);
  127 + }
  128 + addArrayBuffer(arrayBuffer) {
  129 + loger.log("addArrayBuffer", arrayBuffer.byteLength);
  130 + parseBuffer.append(arrayBuffer, "binary");
  131 + }
  132 +
  133 + read() {
  134 + //loger.log("readUInt64", parseBuffer.readUInt64(0));
  135 + //loger.log("readUInt32", parseBuffer.readUInt32(8));
  136 + //loger.log("readByte", parseBuffer.readByte(12));
  137 + let byteLength=parseBuffer.offset;
  138 + parseBuffer.byteOffset=0;
  139 + var position = 0;
  140 + while (position<byteLength){
  141 + var time = parseBuffer.readUInt64(position, true);
  142 + position += 8;
  143 + var len = parseBuffer.readUInt32(position, true);
  144 + position += 4;
  145 + var byte = parseBuffer.buffer.slice(position, (position+len));
  146 + position += len;
  147 + console.log(time, len, byte);
  148 + this._everSocketMsgReceivedHandler(byte);
  149 + }
  150 + }
  151 +
  152 + writeBuffer() {
  153 + parseBuffer.writeUint64(123456789, 0).flip();
  154 + parseBuffer.writeUint32(22211122, 8).flip();
  155 + }
  156 +
  157 + startRecordPlayback(_param) {
  158 +
  159 + }
  160 +
  161 + stopRecordPlayback(_param) {
  162 +
  163 + }
  164 +
  165 + pauseRecordPlayback(_param) {
  166 +
  167 + }
  168 +
  169 + seekRecordPlayback(_param) {
  170 +
  171 + }
  172 +}
  173 +
  174 +RecordPlayBackParse.prototype.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS = RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS = 'class_join_recordPlayback_success';//加入录制回放成功
  175 +
  176 +export default new RecordPlayBackParse;
  177 +
@@ -117,7 +117,7 @@ class Sass extends Emiter { @@ -117,7 +117,7 @@ class Sass extends Emiter {
117 } 117 }
118 118
119 let url = `http://${confInfo.portal}/3m/api/meeting/signIn.do?siteId=${confInfo.siteId}&classId=${confInfo.classId}&isTeacher=${isTeacher}&password=${confInfo.password}`; 119 let url = `http://${confInfo.portal}/3m/api/meeting/signIn.do?siteId=${confInfo.siteId}&classId=${confInfo.classId}&isTeacher=${isTeacher}&password=${confInfo.password}`;
120 - loger.log('3.会议密码校验', url); 120 + loger.log('3.课堂密码校验', url);
121 fetch(url, { 121 fetch(url, {
122 timeout: 5000 122 timeout: 5000
123 }) 123 })
@@ -125,7 +125,7 @@ class Sass extends Emiter { @@ -125,7 +125,7 @@ class Sass extends Emiter {
125 if (ret.status === 200) { 125 if (ret.status === 200) {
126 return ret.text(); 126 return ret.text();
127 } else { 127 } else {
128 - loger.error(`会议密码校验-网络异常.状态码:${ret.status}`); 128 + loger.error(`课堂密码校验-网络异常.状态码:${ret.status}`);
129 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_NETWORK); 129 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_NETWORK);
130 throw ''; 130 throw '';
131 } 131 }
@@ -133,20 +133,20 @@ class Sass extends Emiter { @@ -133,20 +133,20 @@ class Sass extends Emiter {
133 .then(ret => { 133 .then(ret => {
134 let rectObj = JSON.parse(ret); 134 let rectObj = JSON.parse(ret);
135 if (rectObj.flag === 'false' || rectObj.flag === false) { 135 if (rectObj.flag === 'false' || rectObj.flag === false) {
136 - loger.error(`会议密码校验-失败.`); 136 + loger.error(`课堂密码校验-失败.`);
137 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_PASSWORD_WRONG); 137 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_PASSWORD_WRONG);
138 return; 138 return;
139 } 139 }
140 if (rectObj.flag === 'true' || rectObj.flag === true) { 140 if (rectObj.flag === 'true' || rectObj.flag === true) {
141 - loger.log(`会议密码校验-成功.`); 141 + loger.log(`课堂密码校验-成功.`);
142 this.sendMD5Checking(); 142 this.sendMD5Checking();
143 return; 143 return;
144 } 144 }
145 - loger.error(`会议密码校验-协议异常.`, rectObj); 145 + loger.error(`课堂密码校验-协议异常.`, rectObj);
146 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PROTOCOL); 146 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PROTOCOL);
147 }) 147 })
148 .catch(err => { 148 .catch(err => {
149 - loger.error(`会议密码校验-异常.状态码:${err}`); 149 + loger.error(`课堂密码校验-异常.状态码:${err}`);
150 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FAILED); 150 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_FAILED);
151 }); 151 });
152 } 152 }
@@ -199,7 +199,7 @@ class Sass extends Emiter { @@ -199,7 +199,7 @@ class Sass extends Emiter {
199 }); 199 });
200 } 200 }
201 201
202 - // 获取会议基本详情------------------------------------------------------------------------------------ 202 + // 获取课堂基本详情------------------------------------------------------------------------------------
203 getClassDetail() { 203 getClassDetail() {
204 let url = `http://${confInfo.portal}/3m/meeting/getClassH5.do?classNumber=${confInfo.classId}`; 204 let url = `http://${confInfo.portal}/3m/meeting/getClassH5.do?classNumber=${confInfo.classId}`;
205 loger.log('获取Class详情.', url); 205 loger.log('获取Class详情.', url);
@@ -230,7 +230,7 @@ class Sass extends Emiter { @@ -230,7 +230,7 @@ class Sass extends Emiter {
230 }); 230 });
231 } 231 }
232 232
233 - //获取课堂会议的完整信息-------------------------------------------------------------------------------- 233 + //获取课堂课堂的完整信息--------------------------------------------------------------------------------
234 getClassParam() { 234 getClassParam() {
235 /* 235 /*
236 参数 (application/x-www-form-urlencoded): 236 参数 (application/x-www-form-urlencoded):
@@ -249,9 +249,9 @@ class Sass extends Emiter { @@ -249,9 +249,9 @@ class Sass extends Emiter {
249 meetingNumber String 课堂号 对应的是classId 249 meetingNumber String 课堂号 对应的是classId
250 */ 250 */
251 var timestamp = new Date().getTime(); 251 var timestamp = new Date().getTime();
252 - var authId = MD5(confInfo.classId + "" + timestamp);//课堂号+时间戳 的字符串,转成MD5  
253 - let url = `http://${confInfo.portal}/3m/api/meeting/detail.do?meetingNumber=${confInfo.classId}&timestamp=${timestamp}&authId=${authId}`;  
254 - loger.log('5.获取课堂会议的完整信息 '); 252 + var authId = MD5(GlobalConfig.classId + "" + timestamp);//课堂号+时间戳 的字符串,转成MD5
  253 + let url = `http://${GlobalConfig.portal}/3m/api/meeting/detail.do?meetingNumber=${GlobalConfig.classId}&timestamp=${timestamp}&authId=${authId}`;
  254 + loger.log('5.获取课堂课堂的完整信息 ');
255 console.log(url); 255 console.log(url);
256 fetch(url, { 256 fetch(url, {
257 timeout: 5000 257 timeout: 5000
@@ -260,7 +260,7 @@ class Sass extends Emiter { @@ -260,7 +260,7 @@ class Sass extends Emiter {
260 if (ret.ok) { 260 if (ret.ok) {
261 return ret.json(); 261 return ret.json();
262 } else { 262 } else {
263 - loger.error(`获取课堂会议的完整信息-网络异常.状态码:${ret.status}`); 263 + loger.error(`获取课堂课堂的完整信息-网络异常.状态码:${ret.status}`);
264 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML); 264 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML);
265 265
266 throw ''; 266 throw '';
@@ -268,15 +268,15 @@ class Sass extends Emiter { @@ -268,15 +268,15 @@ class Sass extends Emiter {
268 }) 268 })
269 .then(ret => { 269 .then(ret => {
270 if (ret.code === 0) { 270 if (ret.code === 0) {
271 - loger.log('获取课堂会议的完整信息完成'); 271 + loger.log('获取课堂课堂的完整信息完成');
272 this._emit(Sass.CLASS_GET_CLASS_PARAM, ret); 272 this._emit(Sass.CLASS_GET_CLASS_PARAM, ret);
273 } else { 273 } else {
274 - loger.warn('获取课堂会议的完整信息 失败.'); 274 + loger.warn('获取课堂课堂的完整信息 失败.');
275 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML); 275 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML);
276 } 276 }
277 }) 277 })
278 .catch(err => { 278 .catch(err => {
279 - loger.error(`获取课堂会议的完整信息异常.状态码:${err}`); 279 + loger.error(`获取课堂课堂的完整信息异常.状态码:${err}`);
280 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML); 280 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_GET_CLASS_PARAML);
281 }); 281 });
282 } 282 }
@@ -294,6 +294,10 @@ class Sass extends Emiter { @@ -294,6 +294,10 @@ class Sass extends Emiter {
294 0 成功, 1 验证信息错误 294 0 成功, 1 验证信息错误
295 */ 295 */
296 sassDeleteDocument(_param) { 296 sassDeleteDocument(_param) {
  297 + if(GlobalConfig.isRecordPlayBack){
  298 + loger.log('录制回放中,能删除文档');
  299 + return;
  300 + }
297 var timestamp = new Date().getTime(); 301 var timestamp = new Date().getTime();
298 var authId = MD5(_param.docId + "" + _param.classId + "" + timestamp);// docId+classId+timestamp的字符串,转成MD5 302 var authId = MD5(_param.docId + "" + _param.classId + "" + timestamp);// docId+classId+timestamp的字符串,转成MD5
299 let url = `http://${confInfo.portal}/3m/api/document/deleteRelation.do?docId=${_param.docId}&classId=${confInfo.classId}&timestamp=${timestamp}&authId=${authId}`; 303 let url = `http://${confInfo.portal}/3m/api/document/deleteRelation.do?docId=${_param.docId}&classId=${confInfo.classId}&timestamp=${timestamp}&authId=${authId}`;
@@ -340,6 +344,10 @@ class Sass extends Emiter { @@ -340,6 +344,10 @@ class Sass extends Emiter {
340 code 0 成功 1 课堂号为空 2 无效的课堂号 3 验证信息错误*/ 344 code 0 成功 1 课堂号为空 2 无效的课堂号 3 验证信息错误*/
341 345
342 saveClassStatusInfo(_param) { 346 saveClassStatusInfo(_param) {
  347 + if(GlobalConfig.isRecordPlayBack){
  348 + loger.log('录制回放中,不需要保存课堂信息');
  349 + return;
  350 + }
343 //{"classStatusInfo":classStatusInfo} 351 //{"classStatusInfo":classStatusInfo}
344 var timestamp = new Date().getTime(); 352 var timestamp = new Date().getTime();
345 var authId = MD5(confInfo.classId + "" + timestamp);// (classId+timestamp)的字符串,转成MD5 353 var authId = MD5(confInfo.classId + "" + timestamp);// (classId+timestamp)的字符串,转成MD5
@@ -386,6 +394,10 @@ class Sass extends Emiter { @@ -386,6 +394,10 @@ class Sass extends Emiter {
386 394
387 //保存录制的信息,主要是录制文件的名称,必须和MCU录制的文件名相同 395 //保存录制的信息,主要是录制文件的名称,必须和MCU录制的文件名相同
388 saveClassRecordContrlInfo(_param) { 396 saveClassRecordContrlInfo(_param) {
  397 + if(GlobalConfig.isRecordPlayBack){
  398 + loger.log('录制回放中,不需要保存');
  399 + return;
  400 + }
389 loger.log('保存开始录制信息'); 401 loger.log('保存开始录制信息');
390 let key = "3mang123A"; 402 let key = "3mang123A";
391 let siteID = GlobalConfig.siteId; 403 let siteID = GlobalConfig.siteId;
@@ -439,8 +451,8 @@ Sass.prototype.CLASS_GET_CLASS_PARAM = Sass.CLASS_GET_CLASS_PARAM = 'sass_class_ @@ -439,8 +451,8 @@ Sass.prototype.CLASS_GET_CLASS_PARAM = Sass.CLASS_GET_CLASS_PARAM = 'sass_class_
439 Sass.prototype.CLASS_GET_CLASS_DETAIL = Sass.CLASS_GET_CLASS_DETAIL = 'sass_class_getClassDetail_message'; 451 Sass.prototype.CLASS_GET_CLASS_DETAIL = Sass.CLASS_GET_CLASS_DETAIL = 'sass_class_getClassDetail_message';
440 Sass.prototype.DELETE_DOCUMENT_SUCCESS = Sass.DELETE_DOCUMENT_SUCCESS = 'sass_class_deleteDocumentSuccess_message';//删除文档成功 452 Sass.prototype.DELETE_DOCUMENT_SUCCESS = Sass.DELETE_DOCUMENT_SUCCESS = 'sass_class_deleteDocumentSuccess_message';//删除文档成功
441 453
442 -Sass.prototype.CLASS_SAVE_STATUS_INFO_SUCCESS = Sass.CLASS_SAVE_STATUS_INFO_SUCCESS = 'sass_class_saveClassStatusInfoSuccess_message';//保存会议状态信息  
443 -Sass.prototype.CLASS_SAVE_RECORD_INFO_SUCCESS = Sass.CLASS_SAVE_RECORD_INFO_SUCCESS = 'sass_class_saveClassRecordInfoSuccess_message';//保存录制会议信息 454 +Sass.prototype.CLASS_SAVE_STATUS_INFO_SUCCESS = Sass.CLASS_SAVE_STATUS_INFO_SUCCESS = 'sass_class_saveClassStatusInfoSuccess_message';//保存课堂状态信息
  455 +Sass.prototype.CLASS_SAVE_RECORD_INFO_SUCCESS = Sass.CLASS_SAVE_RECORD_INFO_SUCCESS = 'sass_class_saveClassRecordInfoSuccess_message';//保存录制课堂信息
444 456
445 457
446 export default new Sass; 458 export default new Sass;
@@ -23,7 +23,7 @@ let tempMsIp=""; @@ -23,7 +23,7 @@ let tempMsIp="";
23 let tempMsPort=""; 23 let tempMsPort="";
24 let msDefaultPort=":1935"; 24 let msDefaultPort=":1935";
25 let mcuDefaultPort="7777"; 25 let mcuDefaultPort="7777";
26 -let speedTestPort = ':6666';//测速端口统一 26 +let speedTestPort = ':5555';//测速端口统一
27 27
28 let checkMcuIpGroup =[];//储存MCU需要查询的ip数组 28 let checkMcuIpGroup =[];//储存MCU需要查询的ip数组
29 let checkMsIpGroup =[];//储存MCU需要查询的ip数组 29 let checkMsIpGroup =[];//储存MCU需要查询的ip数组
@@ -15,367 +15,394 @@ @@ -15,367 +15,394 @@
15 15
16 import pdu from 'pdus'; 16 import pdu from 'pdus';
17 import Emiter from 'Emiter'; 17 import Emiter from 'Emiter';
18 -import mcu from 'mcu'; 18 +import McuObj from 'mcu';
19 import Loger from 'Loger'; 19 import Loger from 'Loger';
20 import MessageTypes from 'MessageTypes'; 20 import MessageTypes from 'MessageTypes';
21 import ApeConsts from './ApeConsts'; 21 import ApeConsts from './ApeConsts';
22 import ArrayBufferUtil from 'libs/ArrayBufferUtil'; 22 import ArrayBufferUtil from 'libs/ArrayBufferUtil';
23 import PduConsts from 'pdus/PduConsts'; 23 import PduConsts from 'pdus/PduConsts';
24 import GlobalConfig from 'GlobalConfig'; 24 import GlobalConfig from 'GlobalConfig';
  25 +import RecordPlayBackParse from 'RecordPlayBackParse';
25 26
26 // 日志对象 27 // 日志对象
27 const loger = Loger.getLoger('Ape'); 28 const loger = Loger.getLoger('Ape');
28 29
29 export default class Ape extends Emiter { 30 export default class Ape extends Emiter {
30 - constructor(  
31 - session_id,  
32 - session_name,  
33 - session_tag  
34 - ) {  
35 - super();  
36 - this._session_id = session_id;  
37 - this._channel_id = session_id; // session_id === channel_id  
38 - this._session_name = session_name;  
39 - this._session_tag = session_tag;  
40 - this._session_channels = {};  
41 - this._adapter_pdu = new pdu['RCAdapterPdu'];  
42 - this._classInfo = null;  
43 - this._rCArrayBufferUtil = ArrayBufferUtil;  
44 - this._apeDelayed = false;  
45 - this._apeDelayedMsgs = [];  
46 - this._apeDelayedTimer = 0;  
47 -  
48 - //Ape 通用消息处理  
49 - this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));  
50 - this.on(pdu.RCPDU_CHANNEL_JOIN_RESPONSE, this._joinChannelHandler.bind(this));  
51 - this.on(pdu.RCPDU_REG_ADAPTER, this._pduMessageHandler.bind(this));  
52 -  
53 - //先收到onJoinSessionHandlerSuccess 后收到 onJoinChannelHandlerSuccess  
54 -  
55 - // 监听底层MCU会议  
56 - this.mcu = mcu;  
57 - this.mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuConferenceJoinSuccessHandler.bind(this));  
58 - this.mcu.registerApe(this);  
59 - }  
60 -  
61 - regResponsePduHandler() {  
62 -  
63 - }  
64 -  
65 - stopApe(){  
66 - loger.log("stopApe==============================");  
67 - }  
68 - // 消息处理  
69 - _pduMessageHandler(regBuffer) {  
70 - //loger.log("RCPDU_REG_ADAPTER==============================");  
71 - if (this._apeDelayed) {  
72 - // this._apeDelayedMsgs.push(regBuffer);  
73 - // this._apeDelayedStart();  
74 - setTimeout(() => {  
75 - this._pduRegAdapterHandler(regBuffer);  
76 - },GlobalConfig.mcuDelay|| 2000);  
77 - return; 31 + constructor(session_id,
  32 + session_name,
  33 + session_tag) {
  34 + super();
  35 + this._session_id = session_id;
  36 + this._channel_id = session_id; // session_id === channel_id
  37 + this._session_name = session_name;
  38 + this._session_tag = session_tag;
  39 + this._session_channels = {};
  40 + this._adapter_pdu = new pdu['RCAdapterPdu'];
  41 + this._classInfo = null;
  42 + this._rCArrayBufferUtil = ArrayBufferUtil;
  43 + this._apeDelayed = false;
  44 + this._apeDelayedMsgs = [];
  45 + this._apeDelayedTimer = 0;
  46 +
  47 + //Ape 通用消息处理
  48 + this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
  49 + this.on(pdu.RCPDU_CHANNEL_JOIN_RESPONSE, this._joinChannelHandler.bind(this));
  50 + this.on(pdu.RCPDU_REG_ADAPTER, this._pduMessageHandler.bind(this));
  51 +
  52 + //先收到onJoinSessionHandlerSuccess 后收到 onJoinChannelHandlerSuccess
  53 +
  54 + loger.log("APE-->registerApe");
  55 + // 监听底层MCU课堂
  56 + this.mcu = McuObj;
  57 + this.mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuConferenceJoinSuccessHandler.bind(this));
  58 + this.mcu.registerApe(this);
  59 +
  60 + //录制回放
  61 + this.recordPlayBackParse = RecordPlayBackParse;
  62 + this.recordPlayBackParse.on(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS, this._joinRecordPlaybackSuccessHandler.bind(this));
  63 + this.recordPlayBackParse.registerApe(this);
  64 +
78 } 65 }
79 - this._pduRegAdapterHandler(regBuffer);  
80 - }  
81 -  
82 - // _apeDelayedStart() {  
83 - // if (this._apeDelayed && !this._apeDelayedTimer) {  
84 - // this._apeDelayedTimer = setInterval(this._delayedMsgHandler.bind(this), this._classInfo['mcuDelay'] || 10000);  
85 - // }  
86 - // }  
87 -  
88 - // _apeDelayedStop() {  
89 - // clearInterval(this._apeDelayedTimer);  
90 - // this._apeDelayedTimer = 0;  
91 - // }  
92 -  
93 - // // 延迟消息处理  
94 - // _delayedMsgHandler() {  
95 - // if (this._apeDelayedMsgs.length) {  
96 - // this._pduRegAdapterHandler(this._apeDelayedMsgs.pop());  
97 - // if (!this._apeDelayedMsgs.length) this._apeDelayedStop();  
98 - // }  
99 - // }  
100 -  
101 - // 数据同步处理  
102 - _pduRegAdapterHandler(regBuffer) {  
103 - let regPdu = pdu['RCAdapterPdu'].decode(regBuffer);  
104 - let regItems = regPdu.item;  
105 - let regItemSize = regItems.length;  
106 - //loger.log(this._session_name + '数据同步消息');  
107 - loger.log(this._session_name + '数据同步消息.同步条数', regItemSize);  
108 - //console.log(regPdu);  
109 -  
110 - for (var i = 0; i < regItemSize; ++i) {  
111 - let regItem = regItems[i];  
112 - let regItemType = regItem.type;  
113 - let regItemData = regItem.itemData;  
114 -  
115 - //根据数据包中的type处理数据是否同步  
116 -  
117 - if (pdu.RCPDU_REG_UPDATE_OBJ !== regItemType) {  
118 - if (pdu.RCPDU_REG_RESPONSE_OBJ == regItemType) {  
119 - let regResponsePdu = pdu['RCRegistryResponseObjPdu'].decode(regItemData);  
120 - this.regResponsePduHandler(regResponsePdu);  
121 - }  
122 - // 只处理两种类型  
123 - continue;  
124 - }  
125 -  
126 - //具体的数据包  
127 - let regUpdatedItem = pdu['RCRegistryUpdateObjPdu'].decode(regItemData);  
128 - let sub_type = regUpdatedItem.subType;  
129 - let object_id = regUpdatedItem.objId;  
130 - let user_data = regUpdatedItem.userData;  
131 -  
132 - loger.log('REG OBJECT EVENT ->', pdu.id2type(sub_type));  
133 - switch (sub_type) {  
134 - case pdu.RCPDU_REG_ROSTER_INSERT_PDU:  
135 - let rosterInsertData = pdu['RCRegstryRosterInsertItemPdu'].decode(user_data);  
136 - let rosterInsertItems = rosterInsertData.items;  
137 - let rosterInsertItemsLen = rosterInsertItems.length;  
138 - for (let i = 0; i < rosterInsertItemsLen; ++i) {  
139 - let record = rosterInsertItems[i];  
140 - let recordId = record.item_id;  
141 - let recordData = pdu['RCNodeInfoRecordPdu'].decode(record.item_data);  
142 - this.rosterInsertHandler(recordId, recordData);  
143 - }  
144 - break;  
145 - case pdu.RCPDU_REG_ROSTER_DELETE_PDU:  
146 - let rosterDelData = pdu['RCRegistryRosterDeleteItemPdu'].decode(user_data);  
147 - this.rosterDelHandler(rosterDelData.nodeId);  
148 - break;  
149 - case pdu.RCPDU_REG_ROSTER_UPDATE_PDU:  
150 - let rosterUpdateData = pdu['RCRegistryRosterUpdateItemPdu'].decode(user_data);  
151 - let rosterUpdateItems = rosterUpdateData.items;  
152 - let rosterUpdateItemsLen = rosterUpdateItems.length;  
153 - for (let i = 0; i < rosterUpdateItemsLen; ++i) {  
154 - let node = rosterUpdateItems[i];  
155 - let nodeId = node.nodeId;  
156 - let nodeData = pdu['RCNodeInfoRecordPdu'].decode(node.nodeData);  
157 - this.rosterUpdateHandler(nodeId, nodeData);  
158 - }  
159 - break;  
160 - case pdu.RCPDU_REG_TABLE_INSERT_PDU:  
161 - let tableInsertData = pdu['RCRegistryTableInsertItemPdu'].decode(user_data);  
162 - let tableInsertItems = tableInsertData.items;  
163 - let tableInsertItemsLen = tableInsertItems.length;  
164 - for (let i = 0; i < tableInsertItemsLen; ++i) {  
165 - let insertItem = tableInsertItems[i];  
166 - //loger.log("insertItem",insertItem);  
167 - this.tableInsertHandler(insertItem.owner, insertItem.itemIdx, insertItem.itemData); 66 +
  67 + regResponsePduHandler() {
  68 +
  69 + }
  70 +
  71 + //停止APE一切操作
  72 + stopApe() {
  73 + loger.log("stopApe==============================");
  74 + }
  75 +
  76 + // 消息处理
  77 + _pduMessageHandler(regBuffer) {
  78 + //loger.log("RCPDU_REG_ADAPTER==============================");
  79 + if (this._apeDelayed) {
  80 + // this._apeDelayedMsgs.push(regBuffer);
  81 + // this._apeDelayedStart();
  82 + setTimeout(() => {
  83 + this._pduRegAdapterHandler(regBuffer);
  84 + }, GlobalConfig.mcuDelay || 2000);
  85 + return;
168 } 86 }
169 - break;  
170 - case pdu.RCPDU_REG_TABLE_DELETE_PDU:  
171 - let tableDeleteData = pdu['RCRegistryTableDeleteItemPdu'].decode(user_data);  
172 - //console.log("tableDeleteData",object_id,tableDeleteData);  
173 - this.tableDeleteHandler(object_id, tableDeleteData);  
174 - break;  
175 - case pdu.RCPDU_REG_TABLE_UPDATE_PDU:  
176 - let tableUpdateData = pdu['RCRegistryTableUpdateItemPdu'].decode(user_data);  
177 - let tableUpdateItems = tableUpdateData.items;  
178 - let tableUpdateItemsLen= tableUpdateItems.length;  
179 - loger.log("RCRegistryTableUpdateItemPdu "+tableUpdateItemsLen);  
180 - console.log(tableUpdateData);  
181 -  
182 - for (let i = 0; i < tableUpdateItemsLen; ++i) {  
183 - let tableItem = tableUpdateItems[i];  
184 - this.tableUpdateHandler(tableItem.owner, tableItem.itemIdx, tableItem.itemData); 87 + this._pduRegAdapterHandler(regBuffer);
  88 + }
  89 +
  90 + // _apeDelayedStart() {
  91 + // if (this._apeDelayed && !this._apeDelayedTimer) {
  92 + // this._apeDelayedTimer = setInterval(this._delayedMsgHandler.bind(this), this._classInfo['mcuDelay'] || 10000);
  93 + // }
  94 + // }
  95 +
  96 + // _apeDelayedStop() {
  97 + // clearInterval(this._apeDelayedTimer);
  98 + // this._apeDelayedTimer = 0;
  99 + // }
  100 +
  101 + // // 延迟消息处理
  102 + // _delayedMsgHandler() {
  103 + // if (this._apeDelayedMsgs.length) {
  104 + // this._pduRegAdapterHandler(this._apeDelayedMsgs.pop());
  105 + // if (!this._apeDelayedMsgs.length) this._apeDelayedStop();
  106 + // }
  107 + // }
  108 +
  109 + // 数据同步处理
  110 + _pduRegAdapterHandler(regBuffer) {
  111 + let regPdu = pdu['RCAdapterPdu'].decode(regBuffer);
  112 + let regItems = regPdu.item;
  113 + let regItemSize = regItems.length;
  114 + //loger.log(this._session_name + '数据同步消息');
  115 + loger.log(this._session_name + '数据同步消息.同步条数', regItemSize);
  116 + //console.log(regPdu);
  117 +
  118 + for (var i = 0; i < regItemSize; ++i) {
  119 + let regItem = regItems[i];
  120 + let regItemType = regItem.type;
  121 + let regItemData = regItem.itemData;
  122 +
  123 + //根据数据包中的type处理数据是否同步
  124 +
  125 + if (pdu.RCPDU_REG_UPDATE_OBJ !== regItemType) {
  126 + if (pdu.RCPDU_REG_RESPONSE_OBJ == regItemType) {
  127 + let regResponsePdu = pdu['RCRegistryResponseObjPdu'].decode(regItemData);
  128 + this.regResponsePduHandler(regResponsePdu);
  129 + }
  130 + // 只处理两种类型
  131 + continue;
  132 + }
  133 +
  134 + //具体的数据包
  135 + let regUpdatedItem = pdu['RCRegistryUpdateObjPdu'].decode(regItemData);
  136 + let sub_type = regUpdatedItem.subType;
  137 + let object_id = regUpdatedItem.objId;
  138 + let user_data = regUpdatedItem.userData;
  139 +
  140 + loger.log('REG OBJECT EVENT ->', pdu.id2type(sub_type));
  141 + switch (sub_type) {
  142 + case pdu.RCPDU_REG_ROSTER_INSERT_PDU:
  143 + let rosterInsertData = pdu['RCRegstryRosterInsertItemPdu'].decode(user_data);
  144 + let rosterInsertItems = rosterInsertData.items;
  145 + let rosterInsertItemsLen = rosterInsertItems.length;
  146 + for (let i = 0; i < rosterInsertItemsLen; ++i) {
  147 + let record = rosterInsertItems[i];
  148 + let recordId = record.item_id;
  149 + let recordData = pdu['RCNodeInfoRecordPdu'].decode(record.item_data);
  150 + this.rosterInsertHandler(recordId, recordData);
  151 + }
  152 + break;
  153 + case pdu.RCPDU_REG_ROSTER_DELETE_PDU:
  154 + let rosterDelData = pdu['RCRegistryRosterDeleteItemPdu'].decode(user_data);
  155 + this.rosterDelHandler(rosterDelData.nodeId);
  156 + break;
  157 + case pdu.RCPDU_REG_ROSTER_UPDATE_PDU:
  158 + let rosterUpdateData = pdu['RCRegistryRosterUpdateItemPdu'].decode(user_data);
  159 + let rosterUpdateItems = rosterUpdateData.items;
  160 + let rosterUpdateItemsLen = rosterUpdateItems.length;
  161 + for (let i = 0; i < rosterUpdateItemsLen; ++i) {
  162 + let node = rosterUpdateItems[i];
  163 + let nodeId = node.nodeId;
  164 + let nodeData = pdu['RCNodeInfoRecordPdu'].decode(node.nodeData);
  165 + this.rosterUpdateHandler(nodeId, nodeData);
  166 + }
  167 + break;
  168 + case pdu.RCPDU_REG_TABLE_INSERT_PDU:
  169 + let tableInsertData = pdu['RCRegistryTableInsertItemPdu'].decode(user_data);
  170 + let tableInsertItems = tableInsertData.items;
  171 + let tableInsertItemsLen = tableInsertItems.length;
  172 + for (let i = 0; i < tableInsertItemsLen; ++i) {
  173 + let insertItem = tableInsertItems[i];
  174 + //loger.log("insertItem",insertItem);
  175 + this.tableInsertHandler(insertItem.owner, insertItem.itemIdx, insertItem.itemData);
  176 + }
  177 + break;
  178 + case pdu.RCPDU_REG_TABLE_DELETE_PDU:
  179 + let tableDeleteData = pdu['RCRegistryTableDeleteItemPdu'].decode(user_data);
  180 + //console.log("tableDeleteData",object_id,tableDeleteData);
  181 + this.tableDeleteHandler(object_id, tableDeleteData);
  182 + break;
  183 + case pdu.RCPDU_REG_TABLE_UPDATE_PDU:
  184 + let tableUpdateData = pdu['RCRegistryTableUpdateItemPdu'].decode(user_data);
  185 + let tableUpdateItems = tableUpdateData.items;
  186 + let tableUpdateItemsLen = tableUpdateItems.length;
  187 + loger.log("RCRegistryTableUpdateItemPdu " + tableUpdateItemsLen);
  188 + console.log(tableUpdateData);
  189 +
  190 + for (let i = 0; i < tableUpdateItemsLen; ++i) {
  191 + let tableItem = tableUpdateItems[i];
  192 + this.tableUpdateHandler(tableItem.owner, tableItem.itemIdx, tableItem.itemData);
  193 + }
  194 + break;
  195 + case pdu.RCPDU_REG_QUEUE_UPDATE_PDU:
  196 + case pdu.RCPDU_REG_QUEUE_DELETE_PDU:
  197 + case pdu.RCPDU_REG_QUEUE_INSERT_PDU:
  198 + loger.warn('REG QUEUE ARE IGNORED');
  199 + break;
  200 +
  201 + }
185 } 202 }
186 - break;  
187 - case pdu.RCPDU_REG_QUEUE_UPDATE_PDU:  
188 - case pdu.RCPDU_REG_QUEUE_DELETE_PDU:  
189 - case pdu.RCPDU_REG_QUEUE_INSERT_PDU:  
190 - loger.warn('REG QUEUE ARE IGNORED');  
191 - break;  
192 -  
193 - }  
194 } 203 }
195 - }  
196 -  
197 - rosterInsertHandler(recordId, recordData) {  
198 - loger.warn(this._session_name + ' rosterInsertHandler 应有子类具体覆盖处理.');  
199 - }  
200 - rosterUpdateHandler(nodeId, nodeData) {  
201 - loger.warn(this._session_name + ' rosterUpdateHandler 应有子类具体覆盖处理.');  
202 - }  
203 - rosterDelHandler(recordData) {  
204 - loger.warn(this._session_name + ' rosterDelHandler 应有子类具体覆盖处理.');  
205 - }  
206 - tableInsertHandler(tableId, record) {  
207 - loger.warn(this._session_name + ' tableInsertHandler 应有子类具体覆盖处理.');  
208 - }  
209 - tableUpdateHandler(ownerId, recordId, recordData) {  
210 - loger.warn(this._session_name + ' tableUpdateHandler 应有子类具体覆盖处理.');  
211 - }  
212 - tableDeleteHandler(tableId, record) {  
213 - loger.warn(this._session_name + ' tableDelHandler 应有子类具体覆盖处理.');  
214 - }  
215 - onJoinChannelHandlerSuccess(){  
216 - loger.warn(this._session_name + ' onJoinChannelHandlerSuccess 应有子类具体覆盖处理.');  
217 - }  
218 - onJoinSessionHandlerSuccess(){  
219 - loger.warn(this._session_name + ' onJoinSessionHandlerSuccess 应有子类具体覆盖处理.');  
220 - }  
221 - // 加入Session处理  
222 - _joinSessionHandler(data) {  
223 - loger.log(this._session_name, ' -> 加入Session');  
224 - this.onJoinSessionHandlerSuccess();  
225 - }  
226 -  
227 - // 加入Channel处理  
228 - _joinChannelHandler(data) {  
229 - let joinedChannel = pdu['RCChannelJoinResponsePdu'].decode(data);  
230 - if (joinedChannel.result === pdu.RET_SUCCESS) {  
231 - loger.log(this._session_name, ' -> 加入Channel成功. ChannelId', joinedChannel.requestedChannelId);  
232 - this._session_channels[joinedChannel.requestedChannelId] = ApeConsts.CJS_JOINNED;  
233 - this.onJoinChannelHandlerSuccess();  
234 - } else {  
235 - loger.log(this._session_name, ' -> 加入Channel失败.', joinedChannel); 204 +
  205 + rosterInsertHandler(recordId, recordData) {
  206 + loger.warn(this._session_name + ' rosterInsertHandler 应有子类具体覆盖处理.');
  207 + }
  208 +
  209 + rosterUpdateHandler(nodeId, nodeData) {
  210 + loger.warn(this._session_name + ' rosterUpdateHandler 应有子类具体覆盖处理.');
  211 + }
  212 +
  213 + rosterDelHandler(recordData) {
  214 + loger.warn(this._session_name + ' rosterDelHandler 应有子类具体覆盖处理.');
  215 + }
  216 +
  217 + tableInsertHandler(tableId, record) {
  218 + loger.warn(this._session_name + ' tableInsertHandler 应有子类具体覆盖处理.');
  219 + }
  220 +
  221 + tableUpdateHandler(ownerId, recordId, recordData) {
  222 + loger.warn(this._session_name + ' tableUpdateHandler 应有子类具体覆盖处理.');
  223 + }
  224 +
  225 + tableDeleteHandler(tableId, record) {
  226 + loger.warn(this._session_name + ' tableDelHandler 应有子类具体覆盖处理.');
  227 + }
  228 +
  229 + onJoinChannelHandlerSuccess() {
  230 + loger.warn(this._session_name + ' onJoinChannelHandlerSuccess 应有子类具体覆盖处理.');
  231 + }
  232 +
  233 + onJoinSessionHandlerSuccess() {
  234 + loger.warn(this._session_name + ' onJoinSessionHandlerSuccess 应有子类具体覆盖处理.');
  235 + }
  236 +
  237 + // 加入Session处理
  238 + _joinSessionHandler(data) {
  239 + loger.log(this._session_name, ' -> 加入Session');
  240 + this.onJoinSessionHandlerSuccess();
  241 + }
  242 +
  243 + // 加入Channel处理
  244 + _joinChannelHandler(data) {
  245 + let joinedChannel = pdu['RCChannelJoinResponsePdu'].decode(data);
  246 + if (joinedChannel.result === pdu.RET_SUCCESS) {
  247 + loger.log(this._session_name, ' -> 加入Channel成功. ChannelId', joinedChannel.requestedChannelId);
  248 + this._session_channels[joinedChannel.requestedChannelId] = ApeConsts.CJS_JOINNED;
  249 + this.onJoinChannelHandlerSuccess();
  250 + } else {
  251 + loger.log(this._session_name, ' -> 加入Channel失败.', joinedChannel);
  252 + }
236 } 253 }
237 - }  
238 -  
239 - // 依赖的会议创建完毕 - 发起Ape加入  
240 - _mcuConferenceJoinSuccessHandler(_data) {  
241 - loger.log('创建Ape->',  
242 - 'SessionId',  
243 - this._session_id,  
244 - 'SessionName',  
245 - this._session_name,  
246 - 'SessionTag',  
247 - this._session_tag);  
248 -  
249 - // 会议依赖底层会议信息  
250 - //this._classInfo = classInfo;  
251 - this._classInfo = GlobalConfig.getClassInfo();  
252 -  
253 - var joinSessionPdu = new pdu['RCSessionJoinRequestPdu'];  
254 - joinSessionPdu.id = this._session_id;  
255 - joinSessionPdu.name = this._session_name;  
256 - joinSessionPdu.tag = this._session_tag;  
257 - joinSessionPdu.sessionData = this._adapter_pdu.toArrayBuffer();  
258 - this.sendUniform(joinSessionPdu, true);  
259 -  
260 - var joinChannelPdu = new pdu['RCChannelJoinRequestPdu'];  
261 - joinChannelPdu.initiator = this.mcu.classInfo.nodeId;  
262 - joinChannelPdu.channelId = this._session_id;  
263 - this.send(joinChannelPdu);  
264 - }  
265 -  
266 - // 注册Key对象  
267 - registerKey(id, name, tag, user_data) {  
268 - let adapterItemPdu = new pdu['RCAdapterItemPdu'];  
269 - adapterItemPdu.type = pdu.RCPDU_REG_REGISTER_KEY;  
270 -  
271 - // pack register key pdus  
272 - let registerKeyPdu = new pdu['RCRegistryRegisterKeyPdu'];  
273 - registerKeyPdu.id = id;  
274 - registerKeyPdu.name = name;  
275 - registerKeyPdu.tag = tag;  
276 - if (user_data.length) {  
277 - registerKeyPdu.userData = user_data; 254 +
  255 + // 依赖的课堂创建完毕 - 发起Ape加入
  256 + _mcuConferenceJoinSuccessHandler(_data) {
  257 + loger.log('创建Ape->',
  258 + 'SessionId',
  259 + this._session_id,
  260 + 'SessionName',
  261 + this._session_name,
  262 + 'SessionTag',
  263 + this._session_tag);
  264 +
  265 + // 课堂依赖底层课堂信息
  266 + //this._classInfo = classInfo;
  267 + this._classInfo = GlobalConfig.getClassInfo();
  268 +
  269 + var joinSessionPdu = new pdu['RCSessionJoinRequestPdu'];
  270 + joinSessionPdu.id = this._session_id;
  271 + joinSessionPdu.name = this._session_name;
  272 + joinSessionPdu.tag = this._session_tag;
  273 + joinSessionPdu.sessionData = this._adapter_pdu.toArrayBuffer();
  274 + this.sendUniform(joinSessionPdu, true);
  275 +
  276 + var joinChannelPdu = new pdu['RCChannelJoinRequestPdu'];
  277 + joinChannelPdu.initiator = this.mcu.classInfo.nodeId;
  278 + joinChannelPdu.channelId = this._session_id;
  279 + this.send(joinChannelPdu);
278 } 280 }
279 281
280 - adapterItemPdu.itemData = registerKeyPdu.toArrayBuffer();  
281 - this._adapter_pdu.item.push(adapterItemPdu);  
282 - }  
283 -  
284 - // 注册Object对象 等同于flash中的 RCRegistryOperator  
285 - registerObj(type, id, name, tag, owner, user_data) {  
286 - let adapterItemPdu = new pdu['RCAdapterItemPdu'];  
287 - adapterItemPdu.type = pdu.RCPDU_REG_REGISTER_OBJ;  
288 -  
289 - let registerObjPdu = new pdu['RCRegistryRegisterObjPdu'];  
290 - registerObjPdu.type = type;  
291 - registerObjPdu.objId = id;  
292 - registerObjPdu.name = name;  
293 - registerObjPdu.tag = tag;  
294 - if (owner) {  
295 - registerObjPdu.owner = owner; 282 + // 依赖的录制回放创建完毕 - 发起Ape加入
  283 + _joinRecordPlaybackSuccessHandler(_data) {
  284 + loger.log('录制回放->Ape已经创建完毕->',
  285 + 'SessionId',
  286 + this._session_id,
  287 + 'SessionName',
  288 + this._session_name,
  289 + 'SessionTag',
  290 + this._session_tag);
296 } 291 }
297 - if (user_data.length) {  
298 - registerObjPdu.userData = user_data; 292 +
  293 + // 注册Key对象
  294 + registerKey(id, name, tag, user_data) {
  295 + let adapterItemPdu = new pdu['RCAdapterItemPdu'];
  296 + adapterItemPdu.type = pdu.RCPDU_REG_REGISTER_KEY;
  297 +
  298 + // pack register key pdus
  299 + let registerKeyPdu = new pdu['RCRegistryRegisterKeyPdu'];
  300 + registerKeyPdu.id = id;
  301 + registerKeyPdu.name = name;
  302 + registerKeyPdu.tag = tag;
  303 + if (user_data.length) {
  304 + registerKeyPdu.userData = user_data;
  305 + }
  306 +
  307 + adapterItemPdu.itemData = registerKeyPdu.toArrayBuffer();
  308 + this._adapter_pdu.item.push(adapterItemPdu);
299 } 309 }
300 310
301 - adapterItemPdu.itemData = registerObjPdu.toArrayBuffer();  
302 - this._adapter_pdu.item.push(adapterItemPdu);  
303 - }  
304 -  
305 - send(appPdu) {  
306 - loger.log('Ape发送数据NORMAL PDU');  
307 - console.log(appPdu);  
308 - //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);  
309 - if(GlobalConfig.getCurrentStatus().code==0||GlobalConfig.getCurrentStatus().code==1){  
310 - this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);  
311 - return; 311 + // 注册Object对象 等同于flash中的 RCRegistryOperator
  312 + registerObj(type, id, name, tag, owner, user_data) {
  313 + let adapterItemPdu = new pdu['RCAdapterItemPdu'];
  314 + adapterItemPdu.type = pdu.RCPDU_REG_REGISTER_OBJ;
  315 +
  316 + let registerObjPdu = new pdu['RCRegistryRegisterObjPdu'];
  317 + registerObjPdu.type = type;
  318 + registerObjPdu.objId = id;
  319 + registerObjPdu.name = name;
  320 + registerObjPdu.tag = tag;
  321 + if (owner) {
  322 + registerObjPdu.owner = owner;
  323 + }
  324 + if (user_data.length) {
  325 + registerObjPdu.userData = user_data;
  326 + }
  327 +
  328 + adapterItemPdu.itemData = registerObjPdu.toArrayBuffer();
  329 + this._adapter_pdu.item.push(adapterItemPdu);
312 } 330 }
313 - let normalPdu = pdu.create_normal_pdu(  
314 - appPdu.type,  
315 - this._classInfo.nodeId,  
316 - this._classInfo.classId,  
317 - this._session_id,  
318 - this._channel_id,  
319 - true,  
320 - true,  
321 - PduConsts.DP_TOP,  
322 - this._classInfo.topNodeID,  
323 - PduConsts.SEG_ONCE  
324 - );  
325 - normalPdu.data = appPdu.toArrayBuffer();  
326 - // Mcu发送  
327 - this.mcu.send(normalPdu);  
328 - }  
329 -  
330 - // 发送当前APE(session uniform包)  
331 - sendUniform(appPdu, top) {  
332 - loger.log('Ape发送数据UNIFORM PDU');  
333 - console.log(appPdu);  
334 - //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);  
335 - if(GlobalConfig.getCurrentStatus().code==0||GlobalConfig.getCurrentStatus().code==1){  
336 - this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);  
337 - return; 331 +
  332 + send(appPdu) {
  333 + loger.log('Ape发送数据NORMAL PDU');
  334 + console.log(appPdu);
  335 + //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
  336 + if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
  337 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
  338 + return;
  339 + }
  340 + let normalPdu = pdu.create_normal_pdu(
  341 + appPdu.type,
  342 + this._classInfo.nodeId,
  343 + this._classInfo.classId,
  344 + this._session_id,
  345 + this._channel_id,
  346 + true,
  347 + true,
  348 + PduConsts.DP_TOP,
  349 + this._classInfo.topNodeID,
  350 + PduConsts.SEG_ONCE
  351 + );
  352 + normalPdu.data = appPdu.toArrayBuffer();
  353 + // Mcu发送
  354 + this.mcu.send(normalPdu);
338 } 355 }
339 356
340 - let uniformPdu = pdu.create_uniform_pdu(  
341 - appPdu.type,  
342 - this._classInfo.nodeId,  
343 - this._classInfo.classId,  
344 - this._session_id,  
345 - top ? ApeConsts.BROADCAST_CHANNEL_ID : this._channel_id,  
346 - true,  
347 - PduConsts.DP_TOP,  
348 - top ? this._classInfo.topNodeID : (appPdu.peer || 0),  
349 - PduConsts.SEG_ONCE  
350 - );  
351 - uniformPdu.data = appPdu.toArrayBuffer();  
352 - // Mcu发送  
353 - this.mcu.send(uniformPdu);  
354 - }  
355 -  
356 - sendChatUniform(appPdu, top) {  
357 - loger.log('Ape发送数据UNIFORM PDU');  
358 - console.log(appPdu);  
359 - //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);  
360 - if(GlobalConfig.getCurrentStatus().code==0||GlobalConfig.getCurrentStatus().code==1){  
361 - this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);  
362 - return; 357 + // 发送当前APE(session uniform包)
  358 + sendUniform(appPdu, top) {
  359 + loger.log('Ape发送数据UNIFORM PDU');
  360 + console.log(appPdu);
  361 + //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
  362 + if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
  363 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
  364 + return;
  365 + }
  366 +
  367 + let uniformPdu = pdu.create_uniform_pdu(
  368 + appPdu.type,
  369 + this._classInfo.nodeId,
  370 + this._classInfo.classId,
  371 + this._session_id,
  372 + top ? ApeConsts.BROADCAST_CHANNEL_ID : this._channel_id,
  373 + true,
  374 + PduConsts.DP_TOP,
  375 + top ? this._classInfo.topNodeID : (appPdu.peer || 0),
  376 + PduConsts.SEG_ONCE
  377 + );
  378 + uniformPdu.data = appPdu.toArrayBuffer();
  379 + // Mcu发送
  380 + this.mcu.send(uniformPdu);
363 } 381 }
364 382
365 - let uniformPdu = pdu.create_uniform_pdu(  
366 - appPdu.type,  
367 - this._classInfo.nodeId,  
368 - this._classInfo.classId,  
369 - this._session_id,  
370 - top ? ApeConsts.BROADCAST_CHANNEL_ID : this._channel_id,  
371 - true,  
372 - PduConsts.DP_TOP,  
373 - 0,//flash中这个值设置为0  
374 - PduConsts.SEG_ONCE  
375 - );  
376 - uniformPdu.data = appPdu.toArrayBuffer();  
377 - // Mcu发送  
378 - this.mcu.send(uniformPdu);  
379 - } 383 + sendChatUniform(appPdu, top) {
  384 + loger.log('Ape发送数据UNIFORM PDU');
  385 + console.log(appPdu);
  386 + //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
  387 + if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
  388 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
  389 + return;
  390 + }
  391 +
  392 + let uniformPdu = pdu.create_uniform_pdu(
  393 + appPdu.type,
  394 + this._classInfo.nodeId,
  395 + this._classInfo.classId,
  396 + this._session_id,
  397 + top ? ApeConsts.BROADCAST_CHANNEL_ID : this._channel_id,
  398 + true,
  399 + PduConsts.DP_TOP,
  400 + 0,//flash中这个值设置为0
  401 + PduConsts.SEG_ONCE
  402 + );
  403 + uniformPdu.data = appPdu.toArrayBuffer();
  404 + // Mcu发送
  405 + this.mcu.send(uniformPdu);
  406 + }
380 } 407 }
381 408
@@ -11,7 +11,7 @@ export default function ApeConsts(id) { @@ -11,7 +11,7 @@ export default function ApeConsts(id) {
11 ApeConsts.CLASS_STATUS_WAIT= 0;//课堂还未开始 11 ApeConsts.CLASS_STATUS_WAIT= 0;//课堂还未开始
12 ApeConsts.CLASS_STATUS_STARTED= 1;//直播中 12 ApeConsts.CLASS_STATUS_STARTED= 1;//直播中
13 ApeConsts.CLASS_STATUS_PAUSE= 2;//暂停 13 ApeConsts.CLASS_STATUS_PAUSE= 2;//暂停
14 -ApeConsts.CLASS_STATUS_CLOSE= 3;//结束//这个是点击结束会议,把所有人踢出课堂,然后把状态值还原为0************* 14 +ApeConsts.CLASS_STATUS_CLOSE= 3;//结束//这个是点击结束课堂,把所有人踢出课堂,然后把状态值还原为0*************
15 ApeConsts.CLASS_STATUS_UPTATE= 4;//更新课堂状态信息 15 ApeConsts.CLASS_STATUS_UPTATE= 4;//更新课堂状态信息
16 16
17 ApeConsts.CLASS_WAIT_START = "class.wait.start";//课堂还未开始 17 ApeConsts.CLASS_WAIT_START = "class.wait.start";//课堂还未开始
@@ -22,7 +22,7 @@ ApeConsts.CLASS_PAUSING = "class.update";//更新当前的状态信息 @@ -22,7 +22,7 @@ ApeConsts.CLASS_PAUSING = "class.update";//更新当前的状态信息
22 22
23 23
24 //课堂控制 24 //课堂控制
25 -ApeConsts.CLASS_ACTION_CLOSE_ALL=1;//所有人关闭会议 25 +ApeConsts.CLASS_ACTION_CLOSE_ALL=1;//所有人关闭课堂
26 26
27 //课堂类型 27 //课堂类型
28 ApeConsts.CLASS_TYPE_INTERACT= 1; // 互动课堂,通过MS转发音视频,不能进行H5观看 28 ApeConsts.CLASS_TYPE_INTERACT= 1; // 互动课堂,通过MS转发音视频,不能进行H5观看
1 // ////////////////////////////////////////////////////////////////////////////// 1 // //////////////////////////////////////////////////////////////////////////////
2 -//会议控制APE 2 +//课堂控制APE
3 // ////////////////////////////////////////////////////////////////////////////// 3 // //////////////////////////////////////////////////////////////////////////////
4 4
5 import Ape from './Ape'; 5 import Ape from './Ape';
@@ -56,11 +56,11 @@ class ConferApe extends Ape { @@ -56,11 +56,11 @@ class ConferApe extends Ape {
56 56
57 this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this)); 57 this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
58 58
59 - this.on(pdu.RCPDU_SEND_CONFERENCE_DATA_REQUEST, this.conferMsgComingHandler.bind(this));//这个是会议消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理 59 + this.on(pdu.RCPDU_SEND_CONFERENCE_DATA_REQUEST, this.conferMsgComingHandler.bind(this));//这个是课堂消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理
60 this.on(pdu.RCPDU_CONFERENCE_RECORD_REQUEST, this.onSendConferRecordRequestHandler.bind(this));//发送录制和停止录制消息 60 this.on(pdu.RCPDU_CONFERENCE_RECORD_REQUEST, this.onSendConferRecordRequestHandler.bind(this));//发送录制和停止录制消息
61 } 61 }
62 62
63 - //加入会议 63 + //加入课堂
64 _joinSessionHandler(_data) { 64 _joinSessionHandler(_data) {
65 let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self; 65 let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
66 loger.log("_joinSessionHandler nodeInfoRecordPdu="); 66 loger.log("_joinSessionHandler nodeInfoRecordPdu=");
@@ -98,7 +98,7 @@ class ConferApe extends Ape { @@ -98,7 +98,7 @@ class ConferApe extends Ape {
98 98
99 sendConferMsg(_messageInfo) { 99 sendConferMsg(_messageInfo) {
100 if (this._classInfo == null || EngineUtils.isEmptyObject(this._classInfo)) { 100 if (this._classInfo == null || EngineUtils.isEmptyObject(this._classInfo)) {
101 - loger.log('不能发送会议消息.McuClient还未初始化数据!'); 101 + loger.log('不能发送课堂消息.McuClient还未初始化数据!');
102 if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) { 102 if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
103 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN); 103 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
104 return; 104 return;
@@ -107,7 +107,7 @@ class ConferApe extends Ape { @@ -107,7 +107,7 @@ class ConferApe extends Ape {
107 } 107 }
108 108
109 // to, message 109 // to, message
110 - loger.log('发送会议消息.', _messageInfo); 110 + loger.log('发送课堂消息.', _messageInfo);
111 111
112 /* message RCConferenceSendDataRequestPdu { 112 /* message RCConferenceSendDataRequestPdu {
113 optional uint32 initiator = 1; 113 optional uint32 initiator = 1;
@@ -129,11 +129,11 @@ class ConferApe extends Ape { @@ -129,11 +129,11 @@ class ConferApe extends Ape {
129 // if (!(conferSendPdu.isPublic || 0 === conferSendPdu.peer)) { 129 // if (!(conferSendPdu.isPublic || 0 === conferSendPdu.peer)) {
130 if (!conferSendPdu.isPublic && 0 != conferSendPdu.peer) { 130 if (!conferSendPdu.isPublic && 0 != conferSendPdu.peer) {
131 //发送给制定的人 131 //发送给制定的人
132 - loger.log('发送私聊会议消息.'); 132 + loger.log('发送私聊课堂消息.');
133 this.send(conferSendPdu); 133 this.send(conferSendPdu);
134 } else { 134 } else {
135 //发送给所有人 135 //发送给所有人
136 - loger.log('发送公聊会议消息.'); 136 + loger.log('发送公聊课堂消息.');
137 this.sendChatUniform(conferSendPdu); 137 this.sendChatUniform(conferSendPdu);
138 } 138 }
139 } 139 }
@@ -182,7 +182,7 @@ class ConferApe extends Ape { @@ -182,7 +182,7 @@ class ConferApe extends Ape {
182 GlobalConfig.classStopTime = EngineUtils.creatTimestampStr(); 182 GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
183 this.sendConferRecordMsg({"recordStatus": true}); 183 this.sendConferRecordMsg({"recordStatus": true});
184 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 184 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
185 - this._emit(MessageTypes.CLASS_RECORD_START);//会议开始录制 185 + this._emit(MessageTypes.CLASS_RECORD_START);//课堂开始录制
186 } 186 }
187 } 187 }
188 188
@@ -198,7 +198,7 @@ class ConferApe extends Ape { @@ -198,7 +198,7 @@ class ConferApe extends Ape {
198 } 198 }
199 199
200 200
201 - //主动离开会议,发送通知到服务器 201 + //主动离开课堂,发送通知到服务器
202 leaveClass() { 202 leaveClass() {
203 let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self; 203 let nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
204 let userDataPdu = new pdu['RCNodeInfoUserDataPdu']; 204 let userDataPdu = new pdu['RCNodeInfoUserDataPdu'];
@@ -264,9 +264,9 @@ class ConferApe extends Ape { @@ -264,9 +264,9 @@ class ConferApe extends Ape {
264 GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_STARTED; 264 GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_STARTED;
265 //开始录制 265 //开始录制
266 this.startRecord(); 266 this.startRecord();
267 - //会议状态改变 267 + //课堂状态改变
268 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 268 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
269 - //同步会议状态 269 + //同步课堂状态
270 this.sendUpdaterClassStatusInfo({"actionType": 1}); 270 this.sendUpdaterClassStatusInfo({"actionType": 1});
271 271
272 //开始计时 272 //开始计时
@@ -302,11 +302,11 @@ class ConferApe extends Ape { @@ -302,11 +302,11 @@ class ConferApe extends Ape {
302 this.stopTimerCounter(); 302 this.stopTimerCounter();
303 this.restorClass(); 303 this.restorClass();
304 //把所有人都踢出课堂 304 //把所有人都踢出课堂
305 - this.sendConferMsg({"to": 0, "message": "所有人退出会议", "actionType": ApeConsts.CLASS_ACTION_CLOSE_ALL}); 305 + this.sendConferMsg({"to": 0, "message": "所有人退出课堂", "actionType": ApeConsts.CLASS_ACTION_CLOSE_ALL});
306 } 306 }
307 307
308 308
309 - //更新会议信息 309 + //更新课堂信息
310 sendUpdaterClassStatusInfo(_param) { 310 sendUpdaterClassStatusInfo(_param) {
311 loger.log('sendUpdaterClassStatusInfo'); 311 loger.log('sendUpdaterClassStatusInfo');
312 if (_param == null || EngineUtils.isEmptyObject(_param)) { 312 if (_param == null || EngineUtils.isEmptyObject(_param)) {
@@ -354,7 +354,7 @@ class ConferApe extends Ape { @@ -354,7 +354,7 @@ class ConferApe extends Ape {
354 adapterPdu.type = pdu.RCPDU_REG_ADAPTER; 354 adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
355 adapterPdu.item.push(adapterItemPdu); 355 adapterPdu.item.push(adapterItemPdu);
356 356
357 - console.log("会议发送更新数据============"); 357 + console.log("课堂发送更新数据============");
358 this.sendUniform(adapterPdu, true); 358 this.sendUniform(adapterPdu, true);
359 } 359 }
360 360
@@ -364,7 +364,7 @@ class ConferApe extends Ape { @@ -364,7 +364,7 @@ class ConferApe extends Ape {
364 onJoinChannelHandlerSuccess() { 364 onJoinChannelHandlerSuccess() {
365 loger.log('ConferApe.onJoinChannelHandlerSuccess', GlobalConfig.classStatus); 365 loger.log('ConferApe.onJoinChannelHandlerSuccess', GlobalConfig.classStatus);
366 this.timerCounter.addTimerCallBack(this.timerCounterUptate.bind(this), 1); 366 this.timerCounter.addTimerCallBack(this.timerCounterUptate.bind(this), 1);
367 - //如果当前会议正在进行中,开启计时器 367 + //如果当前课堂正在进行中,开启计时器
368 if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) { 368 if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
369 //开始计时 369 //开始计时
370 this.startTimerCounter(); 370 this.startTimerCounter();
@@ -416,11 +416,11 @@ class ConferApe extends Ape { @@ -416,11 +416,11 @@ class ConferApe extends Ape {
416 loger.log('tableUpdateHandler'); 416 loger.log('tableUpdateHandler');
417 console.log(model); 417 console.log(model);
418 418
419 - //处理会议更新的信息 419 + //处理课堂更新的信息
420 if (model && model.classStatusInfo) { 420 if (model && model.classStatusInfo) {
421 GlobalConfig.setClassStatusInfo(model.classStatusInfo); 421 GlobalConfig.setClassStatusInfo(model.classStatusInfo);
422 } 422 }
423 - //通知应用层更新会议状态 423 + //通知应用层更新课堂状态
424 this._emit(MessageTypes.CLASS_UPTATE_STATUS, GlobalConfig.classStatusInfo); 424 this._emit(MessageTypes.CLASS_UPTATE_STATUS, GlobalConfig.classStatusInfo);
425 425
426 //如果MCU已经断开连接,停止计时器 426 //如果MCU已经断开连接,停止计时器
@@ -431,7 +431,7 @@ class ConferApe extends Ape { @@ -431,7 +431,7 @@ class ConferApe extends Ape {
431 } 431 }
432 432
433 if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) { 433 if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
434 - //如果会议在进行中,开始计时器 434 + //如果课堂在进行中,开始计时器
435 this.startTimerCounter(); 435 this.startTimerCounter();
436 } else { 436 } else {
437 //停止计时 437 //停止计时
@@ -460,7 +460,7 @@ class ConferApe extends Ape { @@ -460,7 +460,7 @@ class ConferApe extends Ape {
460 switch (chatMsg.actionType) { 460 switch (chatMsg.actionType) {
461 case ApeConsts.CLASS_ACTION_CLOSE_ALL: 461 case ApeConsts.CLASS_ACTION_CLOSE_ALL:
462 loger.log(chatMsg.message); 462 loger.log(chatMsg.message);
463 - //收到会议关闭,所有人都退出,执行自己关闭的流程 463 + //收到课堂关闭,所有人都退出,执行自己关闭的流程
464 this._emit(MessageTypes.CLASS_EXIT); 464 this._emit(MessageTypes.CLASS_EXIT);
465 break; 465 break;
466 default: 466 default:
@@ -596,7 +596,7 @@ class ConferApe extends Ape { @@ -596,7 +596,7 @@ class ConferApe extends Ape {
596 596
597 ///////数据的封包和解包///////////////////////////////////////// 597 ///////数据的封包和解包/////////////////////////////////////////
598 packPdu(_param, _itemIdx) { 598 packPdu(_param, _itemIdx) {
599 - loger.log("会议===packPdu "); 599 + loger.log("课堂===packPdu ");
600 //验证坐标点集合数组是否合法 600 //验证坐标点集合数组是否合法
601 if (_param == null || _itemIdx == null) { 601 if (_param == null || _itemIdx == null) {
602 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); 602 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
@@ -644,7 +644,7 @@ class ConferApe extends Ape { @@ -644,7 +644,7 @@ class ConferApe extends Ape {
644 } 644 }
645 645
646 unPackPdu(owner, itemIdx, itemData) { 646 unPackPdu(owner, itemIdx, itemData) {
647 - loger.log("会议===unPackPdu "); 647 + loger.log("课堂===unPackPdu ");
648 if (owner == null || itemIdx == null || itemData == null) { 648 if (owner == null || itemIdx == null || itemData == null) {
649 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); 649 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
650 return null; 650 return null;
@@ -654,7 +654,7 @@ class ConferApe extends Ape { @@ -654,7 +654,7 @@ class ConferApe extends Ape {
654 let modelPdu = pdu['RCClassSendDataModelPdu'].decode(itemData); 654 let modelPdu = pdu['RCClassSendDataModelPdu'].decode(itemData);
655 return modelPdu; 655 return modelPdu;
656 } catch (err) { 656 } catch (err) {
657 - loger.log("会议收到数据 unPackPdu Pdu解析错误,itemIdx=" + itemIdx + " err:" + err.message); 657 + loger.log("课堂收到数据 unPackPdu Pdu解析错误,itemIdx=" + itemIdx + " err:" + err.message);
658 } 658 }
659 return null; 659 return null;
660 } 660 }
@@ -504,7 +504,7 @@ class DocApe extends Ape { @@ -504,7 +504,7 @@ class DocApe extends Ape {
504 docModelPdu.pageNum = _param.pageNum||1; 504 docModelPdu.pageNum = _param.pageNum||1;
505 docModelPdu.fileType=_param.fileType||""; 505 docModelPdu.fileType=_param.fileType||"";
506 docModelPdu.creatUserId=_param.creatUserId||"0"; 506 docModelPdu.creatUserId=_param.creatUserId||"0";
507 - docModelPdu.url =_param.url||"";//"http://101.200.150.192/DocSharing/data/h5test/20170206-171100025/7e9c4178cac1133e0dd9d5b583439122.jpg"; 507 + docModelPdu.url ="";//这个地址没用到,数据太长占用资源 暂停使用//"http://101.200.150.192/DocSharing/data/h5test/20170206-171100025/7e9c4178cac1133e0dd9d5b583439122.jpg";
508 docModelPdu.relativeUrl=_param.relativeUrl||"";//"/DocSharing/data/h5test/20170206-171100025/7e9c4178cac1133e0dd9d5b583439122.jpg"; 508 docModelPdu.relativeUrl=_param.relativeUrl||"";//"/DocSharing/data/h5test/20170206-171100025/7e9c4178cac1133e0dd9d5b583439122.jpg";
509 docModelPdu.curV=_param.curV||0; 509 docModelPdu.curV=_param.curV||0;
510 docModelPdu.curH=_param.curH||0; 510 docModelPdu.curH=_param.curH||0;
@@ -52,7 +52,7 @@ class WhiteBoardApe extends Ape { @@ -52,7 +52,7 @@ class WhiteBoardApe extends Ape {
52 52
53 // ape listeners 53 // ape listeners
54 this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this)); 54 this.on(pdu.RCPDU_SESSION_JOIN_RESPONSE, this._joinSessionHandler.bind(this));
55 - //this.on(pdu.RCPDU_CONFERENCE_SEND_DATA_REQUEST, this.whiteboardMsgComingHandler.bind(this));//这个是会议消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理 55 + //this.on(pdu.RCPDU_CONFERENCE_SEND_DATA_REQUEST, this.whiteboardMsgComingHandler.bind(this));//这个是课堂消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理
56 } 56 }
57 57
58 _joinSessionHandler(_data) { 58 _joinSessionHandler(_data) {
  1 +/*
  2 + bytebuffer.js (c) 2015 Daniel Wirtz <dcode@dcode.io>
  3 + Backing buffer: ArrayBuffer, Accessor: Uint8Array
  4 + Released under the Apache License, Version 2.0
  5 + see: https://github.com/dcodeIO/bytebuffer.js for details
  6 +*/
  7 +(function(k,m){if("function"===typeof define&&define.amd)define(["long"],m);else if("function"===typeof require&&"object"===typeof module&&module&&module.exports){var r=module,s;try{s=require("long")}catch(u){}s=m(s);r.exports=s}else(k.dcodeIO=k.dcodeIO||{}).ByteBuffer=m(k.dcodeIO.Long)})(this,function(k){function m(a){var b=0;return function(){return b<a.length?a.charCodeAt(b++):null}}function r(){var a=[],b=[];return function(){if(0===arguments.length)return b.join("")+w.apply(String,a);1024<a.length+
  8 +arguments.length&&(b.push(w.apply(String,a)),a.length=0);Array.prototype.push.apply(a,arguments)}}function s(a,b,c,d,f){var l;l=8*f-d-1;var g=(1<<l)-1,e=g>>1,h=-7;f=c?f-1:0;var k=c?-1:1,p=a[b+f];f+=k;c=p&(1<<-h)-1;p>>=-h;for(h+=l;0<h;c=256*c+a[b+f],f+=k,h-=8);l=c&(1<<-h)-1;c>>=-h;for(h+=d;0<h;l=256*l+a[b+f],f+=k,h-=8);if(0===c)c=1-e;else{if(c===g)return l?NaN:Infinity*(p?-1:1);l+=Math.pow(2,d);c-=e}return(p?-1:1)*l*Math.pow(2,c-d)}function u(a,b,c,d,f,l){var g,e=8*l-f-1,h=(1<<e)-1,k=h>>1,p=23===f?
  9 +Math.pow(2,-24)-Math.pow(2,-77):0;l=d?0:l-1;var m=d?1:-1,n=0>b||0===b&&0>1/b?1:0;b=Math.abs(b);isNaN(b)||Infinity===b?(b=isNaN(b)?1:0,d=h):(d=Math.floor(Math.log(b)/Math.LN2),1>b*(g=Math.pow(2,-d))&&(d--,g*=2),b=1<=d+k?b+p/g:b+p*Math.pow(2,1-k),2<=b*g&&(d++,g/=2),d+k>=h?(b=0,d=h):1<=d+k?(b=(b*g-1)*Math.pow(2,f),d+=k):(b=b*Math.pow(2,k-1)*Math.pow(2,f),d=0));for(;8<=f;a[c+l]=b&255,l+=m,b/=256,f-=8);d=d<<f|b;for(e+=f;0<e;a[c+l]=d&255,l+=m,d/=256,e-=8);a[c+l-m]|=128*n}var h=function(a,b,c){"undefined"===
  10 +typeof a&&(a=h.DEFAULT_CAPACITY);"undefined"===typeof b&&(b=h.DEFAULT_ENDIAN);"undefined"===typeof c&&(c=h.DEFAULT_NOASSERT);if(!c){a|=0;if(0>a)throw RangeError("Illegal capacity");b=!!b;c=!!c}this.buffer=0===a?v:new ArrayBuffer(a);this.view=0===a?null:new Uint8Array(this.buffer);this.offset=0;this.markedOffset=-1;this.limit=a;this.littleEndian=b;this.noAssert=c};h.VERSION="5.0.1";h.LITTLE_ENDIAN=!0;h.BIG_ENDIAN=!1;h.DEFAULT_CAPACITY=16;h.DEFAULT_ENDIAN=h.BIG_ENDIAN;h.DEFAULT_NOASSERT=!1;h.Long=k||
  11 +null;var e=h.prototype;Object.defineProperty(e,"__isByteBuffer__",{value:!0,enumerable:!1,configurable:!1});var v=new ArrayBuffer(0),w=String.fromCharCode;h.accessor=function(){return Uint8Array};h.allocate=function(a,b,c){return new h(a,b,c)};h.concat=function(a,b,c,d){if("boolean"===typeof b||"string"!==typeof b)d=c,c=b,b=void 0;for(var f=0,l=0,g=a.length,e;l<g;++l)h.isByteBuffer(a[l])||(a[l]=h.wrap(a[l],b)),e=a[l].limit-a[l].offset,0<e&&(f+=e);if(0===f)return new h(0,c,d);b=new h(f,c,d);for(l=
  12 +0;l<g;)c=a[l++],e=c.limit-c.offset,0>=e||(b.view.set(c.view.subarray(c.offset,c.limit),b.offset),b.offset+=e);b.limit=b.offset;b.offset=0;return b};h.isByteBuffer=function(a){return!0===(a&&a.__isByteBuffer__)};h.type=function(){return ArrayBuffer};h.wrap=function(a,b,c,d){"string"!==typeof b&&(d=c,c=b,b=void 0);if("string"===typeof a)switch("undefined"===typeof b&&(b="utf8"),b){case "base64":return h.fromBase64(a,c);case "hex":return h.fromHex(a,c);case "binary":return h.fromBinary(a,c);case "utf8":return h.fromUTF8(a,
  13 +c);case "debug":return h.fromDebug(a,c);default:throw Error("Unsupported encoding: "+b);}if(null===a||"object"!==typeof a)throw TypeError("Illegal buffer");if(h.isByteBuffer(a))return b=e.clone.call(a),b.markedOffset=-1,b;if(a instanceof Uint8Array)b=new h(0,c,d),0<a.length&&(b.buffer=a.buffer,b.offset=a.byteOffset,b.limit=a.byteOffset+a.byteLength,b.view=new Uint8Array(a.buffer));else if(a instanceof ArrayBuffer)b=new h(0,c,d),0<a.byteLength&&(b.buffer=a,b.offset=0,b.limit=a.byteLength,b.view=0<
  14 +a.byteLength?new Uint8Array(a):null);else if("[object Array]"===Object.prototype.toString.call(a))for(b=new h(a.length,c,d),b.limit=a.length,c=0;c<a.length;++c)b.view[c]=a[c];else throw TypeError("Illegal buffer");return b};e.writeBitSet=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if(!(a instanceof Array))throw TypeError("Illegal BitSet: Not an array");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>
  15 +this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}var d=b,f=a.length,e=f>>3,g=0,h;for(b+=this.writeVarint32(f,b);e--;)h=!!a[g++]&1|(!!a[g++]&1)<<1|(!!a[g++]&1)<<2|(!!a[g++]&1)<<3|(!!a[g++]&1)<<4|(!!a[g++]&1)<<5|(!!a[g++]&1)<<6|(!!a[g++]&1)<<7,this.writeByte(h,b++);if(g<f){for(h=e=0;g<f;)h|=(!!a[g++]&1)<<e++;this.writeByte(h,b++)}return c?(this.offset=b,this):b-d};e.readBitSet=function(a){var b="undefined"===typeof a;b&&(a=this.offset);var c=this.readVarint32(a),
  16 +d=c.value,f=d>>3,e=0,g=[];for(a+=c.length;f--;)c=this.readByte(a++),g[e++]=!!(c&1),g[e++]=!!(c&2),g[e++]=!!(c&4),g[e++]=!!(c&8),g[e++]=!!(c&16),g[e++]=!!(c&32),g[e++]=!!(c&64),g[e++]=!!(c&128);if(e<d)for(f=0,c=this.readByte(a++);e<d;)g[e++]=!!(c>>f++&1);b&&(this.offset=a);return g};e.readBytes=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+a>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+
  17 +b+" (+"+a+") <= "+this.buffer.byteLength);}var d=this.slice(b,b+a);c&&(this.offset+=a);return d};e.writeBytes=e.append;e.writeInt8=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a|=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);
  18 +}b+=1;var d=this.buffer.byteLength;b>d&&this.resize((d*=2)>b?d:b);this.view[b-1]=a;c&&(this.offset+=1);return this};e.writeByte=e.writeInt8;e.readInt8=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}a=this.view[a];128===(a&128)&&(a=-(255-a+1));b&&(this.offset+=
  19 +1);return a};e.readByte=e.readInt8;e.writeUint8=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=1;var d=this.buffer.byteLength;b>d&&this.resize((d*=2)>b?d:b);
  20 +this.view[b-1]=a;c&&(this.offset+=1);return this};e.writeUInt8=e.writeUint8;e.readUint8=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}a=this.view[a];b&&(this.offset+=1);return a};e.readUInt8=e.readUint8;e.writeInt16=function(a,b){var c="undefined"===typeof b;
  21 +c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a|=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=2;var d=this.buffer.byteLength;b>d&&this.resize((d*=2)>b?d:b);b-=2;this.littleEndian?(this.view[b+1]=(a&65280)>>>8,this.view[b]=a&255):(this.view[b]=(a&65280)>>>
  22 +8,this.view[b+1]=a&255);c&&(this.offset+=2);return this};e.writeShort=e.writeInt16;e.readInt16=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+2>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+2) <= "+this.buffer.byteLength);}var c=0;this.littleEndian?(c=this.view[a],c|=this.view[a+1]<<8):(c=this.view[a]<<8,c|=this.view[a+1]);32768===(c&32768)&&
  23 +(c=-(65535-c+1));b&&(this.offset+=2);return c};e.readShort=e.readInt16;e.writeUint16=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=2;var d=this.buffer.byteLength;
  24 +b>d&&this.resize((d*=2)>b?d:b);b-=2;this.littleEndian?(this.view[b+1]=(a&65280)>>>8,this.view[b]=a&255):(this.view[b]=(a&65280)>>>8,this.view[b+1]=a&255);c&&(this.offset+=2);return this};e.writeUInt16=e.writeUint16;e.readUint16=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+2>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+2) <= "+this.buffer.byteLength);
  25 +}var c=0;this.littleEndian?(c=this.view[a],c|=this.view[a+1]<<8):(c=this.view[a]<<8,c|=this.view[a+1]);b&&(this.offset+=2);return c};e.readUInt16=e.readUint16;e.writeInt32=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a|=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+
  26 +b+" (+0) <= "+this.buffer.byteLength);}b+=4;var d=this.buffer.byteLength;b>d&&this.resize((d*=2)>b?d:b);b-=4;this.littleEndian?(this.view[b+3]=a>>>24&255,this.view[b+2]=a>>>16&255,this.view[b+1]=a>>>8&255,this.view[b]=a&255):(this.view[b]=a>>>24&255,this.view[b+1]=a>>>16&255,this.view[b+2]=a>>>8&255,this.view[b+3]=a&255);c&&(this.offset+=4);return this};e.writeInt=e.writeInt32;e.readInt32=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%
  27 +1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+4) <= "+this.buffer.byteLength);}var c=0;this.littleEndian?(c=this.view[a+2]<<16,c|=this.view[a+1]<<8,c|=this.view[a],c+=this.view[a+3]<<24>>>0):(c=this.view[a+1]<<16,c|=this.view[a+2]<<8,c|=this.view[a+3],c+=this.view[a]<<24>>>0);b&&(this.offset+=4);return c|0};e.readInt=e.readInt32;e.writeUint32=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);
  28 +if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=4;var d=this.buffer.byteLength;b>d&&this.resize((d*=2)>b?d:b);b-=4;this.littleEndian?(this.view[b+3]=a>>>24&255,this.view[b+2]=a>>>16&255,this.view[b+1]=a>>>8&255,this.view[b]=
  29 +a&255):(this.view[b]=a>>>24&255,this.view[b+1]=a>>>16&255,this.view[b+2]=a>>>8&255,this.view[b+3]=a&255);c&&(this.offset+=4);return this};e.writeUInt32=e.writeUint32;e.readUint32=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+4) <= "+this.buffer.byteLength);}var c=0;this.littleEndian?(c=this.view[a+
  30 +2]<<16,c|=this.view[a+1]<<8,c|=this.view[a],c+=this.view[a+3]<<24>>>0):(c=this.view[a+1]<<16,c|=this.view[a+2]<<8,c|=this.view[a+3],c+=this.view[a]<<24>>>0);b&&(this.offset+=4);return c};e.readUInt32=e.readUint32;k&&(e.writeInt64=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"===typeof a)a=k.fromNumber(a);else if("string"===typeof a)a=k.fromString(a);else if(!(a&&a instanceof k))throw TypeError("Illegal value: "+a+" (not an integer or Long)");if("number"!==
  31 +typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}"number"===typeof a?a=k.fromNumber(a):"string"===typeof a&&(a=k.fromString(a));b+=8;var d=this.buffer.byteLength;b>d&&this.resize((d*=2)>b?d:b);b-=8;var d=a.low,f=a.high;this.littleEndian?(this.view[b+3]=d>>>24&255,this.view[b+2]=d>>>16&255,this.view[b+1]=d>>>8&255,this.view[b]=d&255,b+=4,this.view[b+3]=
  32 +f>>>24&255,this.view[b+2]=f>>>16&255,this.view[b+1]=f>>>8&255,this.view[b]=f&255):(this.view[b]=f>>>24&255,this.view[b+1]=f>>>16&255,this.view[b+2]=f>>>8&255,this.view[b+3]=f&255,b+=4,this.view[b]=d>>>24&255,this.view[b+1]=d>>>16&255,this.view[b+2]=d>>>8&255,this.view[b+3]=d&255);c&&(this.offset+=8);return this},e.writeLong=e.writeInt64,e.readInt64=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");
  33 +a>>>=0;if(0>a||a+8>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+8) <= "+this.buffer.byteLength);}var c=0,d=0;this.littleEndian?(c=this.view[a+2]<<16,c|=this.view[a+1]<<8,c|=this.view[a],c+=this.view[a+3]<<24>>>0,a+=4,d=this.view[a+2]<<16,d|=this.view[a+1]<<8,d|=this.view[a],d+=this.view[a+3]<<24>>>0):(d=this.view[a+1]<<16,d|=this.view[a+2]<<8,d|=this.view[a+3],d+=this.view[a]<<24>>>0,a+=4,c=this.view[a+1]<<16,c|=this.view[a+2]<<8,c|=this.view[a+3],c+=this.view[a]<<24>>>0);
  34 +a=new k(c,d,!1);b&&(this.offset+=8);return a},e.readLong=e.readInt64,e.writeUint64=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"===typeof a)a=k.fromNumber(a);else if("string"===typeof a)a=k.fromString(a);else if(!(a&&a instanceof k))throw TypeError("Illegal value: "+a+" (not an integer or Long)");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+
  35 +b+" (+0) <= "+this.buffer.byteLength);}"number"===typeof a?a=k.fromNumber(a):"string"===typeof a&&(a=k.fromString(a));b+=8;var d=this.buffer.byteLength;b>d&&this.resize((d*=2)>b?d:b);b-=8;var d=a.low,f=a.high;this.littleEndian?(this.view[b+3]=d>>>24&255,this.view[b+2]=d>>>16&255,this.view[b+1]=d>>>8&255,this.view[b]=d&255,b+=4,this.view[b+3]=f>>>24&255,this.view[b+2]=f>>>16&255,this.view[b+1]=f>>>8&255,this.view[b]=f&255):(this.view[b]=f>>>24&255,this.view[b+1]=f>>>16&255,this.view[b+2]=f>>>8&255,
  36 +this.view[b+3]=f&255,b+=4,this.view[b]=d>>>24&255,this.view[b+1]=d>>>16&255,this.view[b+2]=d>>>8&255,this.view[b+3]=d&255);c&&(this.offset+=8);return this},e.writeUInt64=e.writeUint64,e.readUint64=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+8>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+8) <= "+this.buffer.byteLength);}var c=0,d=0;this.littleEndian?
  37 +(c=this.view[a+2]<<16,c|=this.view[a+1]<<8,c|=this.view[a],c+=this.view[a+3]<<24>>>0,a+=4,d=this.view[a+2]<<16,d|=this.view[a+1]<<8,d|=this.view[a],d+=this.view[a+3]<<24>>>0):(d=this.view[a+1]<<16,d|=this.view[a+2]<<8,d|=this.view[a+3],d+=this.view[a]<<24>>>0,a+=4,c=this.view[a+1]<<16,c|=this.view[a+2]<<8,c|=this.view[a+3],c+=this.view[a]<<24>>>0);a=new k(c,d,!0);b&&(this.offset+=8);return a},e.readUInt64=e.readUint64);e.writeFloat32=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==
  38 +typeof a)throw TypeError("Illegal value: "+a+" (not a number)");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=4;var d=this.buffer.byteLength;b>d&&this.resize((d*=2)>b?d:b);u(this.view,a,b-4,this.littleEndian,23,4);c&&(this.offset+=4);return this};e.writeFloat=e.writeFloat32;e.readFloat32=function(a){var b="undefined"===typeof a;b&&
  39 +(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+4) <= "+this.buffer.byteLength);}a=s(this.view,a,this.littleEndian,23,4);b&&(this.offset+=4);return a};e.readFloat=e.readFloat32;e.writeFloat64=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a)throw TypeError("Illegal value: "+a+" (not a number)");
  40 +if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}b+=8;var d=this.buffer.byteLength;b>d&&this.resize((d*=2)>b?d:b);u(this.view,a,b-8,this.littleEndian,52,8);c&&(this.offset+=8);return this};e.writeDouble=e.writeFloat64;e.readFloat64=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==
  41 +a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+8>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+8) <= "+this.buffer.byteLength);}a=s(this.view,a,this.littleEndian,52,8);b&&(this.offset+=8);return a};e.readDouble=e.readFloat64;h.MAX_VARINT32_BYTES=5;h.calculateVarint32=function(a){a>>>=0;return 128>a?1:16384>a?2:2097152>a?3:268435456>a?4:5};h.zigZagEncode32=function(a){return((a|=0)<<1^a>>31)>>>0};h.zigZagDecode32=function(a){return a>>>1^-(a&
  42 +1)|0};e.writeVarint32=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a|=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}var d=h.calculateVarint32(a),f;b+=d;f=this.buffer.byteLength;b>f&&this.resize((f*=2)>b?f:b);
  43 +b-=d;for(a>>>=0;128<=a;)f=a&127|128,this.view[b++]=f,a>>>=7;this.view[b++]=a;return c?(this.offset=b,this):d};e.writeVarint32ZigZag=function(a,b){return this.writeVarint32(h.zigZagEncode32(a),b)};e.readVarint32=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);
  44 +}var c=0,d=0,f;do{if(!this.noAssert&&a>this.limit)throw a=Error("Truncated"),a.truncated=!0,a;f=this.view[a++];5>c&&(d|=(f&127)<<7*c);++c}while(0!==(f&128));d|=0;return b?(this.offset=a,d):{value:d,length:c}};e.readVarint32ZigZag=function(a){a=this.readVarint32(a);"object"===typeof a?a.value=h.zigZagDecode32(a.value):a=h.zigZagDecode32(a);return a};k&&(h.MAX_VARINT64_BYTES=10,h.calculateVarint64=function(a){"number"===typeof a?a=k.fromNumber(a):"string"===typeof a&&(a=k.fromString(a));var b=a.toInt()>>>
  45 +0,c=a.shiftRightUnsigned(28).toInt()>>>0;a=a.shiftRightUnsigned(56).toInt()>>>0;return 0==a?0==c?16384>b?128>b?1:2:2097152>b?3:4:16384>c?128>c?5:6:2097152>c?7:8:128>a?9:10},h.zigZagEncode64=function(a){"number"===typeof a?a=k.fromNumber(a,!1):"string"===typeof a?a=k.fromString(a,!1):!1!==a.unsigned&&(a=a.toSigned());return a.shiftLeft(1).xor(a.shiftRight(63)).toUnsigned()},h.zigZagDecode64=function(a){"number"===typeof a?a=k.fromNumber(a,!1):"string"===typeof a?a=k.fromString(a,!1):!1!==a.unsigned&&
  46 +(a=a.toSigned());return a.shiftRightUnsigned(1).xor(a.and(k.ONE).toSigned().negate()).toSigned()},e.writeVarint64=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"===typeof a)a=k.fromNumber(a);else if("string"===typeof a)a=k.fromString(a);else if(!(a&&a instanceof k))throw TypeError("Illegal value: "+a+" (not an integer or Long)");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+
  47 +b+" (+0) <= "+this.buffer.byteLength);}"number"===typeof a?a=k.fromNumber(a,!1):"string"===typeof a?a=k.fromString(a,!1):!1!==a.unsigned&&(a=a.toSigned());var d=h.calculateVarint64(a),f=a.toInt()>>>0,e=a.shiftRightUnsigned(28).toInt()>>>0,g=a.shiftRightUnsigned(56).toInt()>>>0;b+=d;var t=this.buffer.byteLength;b>t&&this.resize((t*=2)>b?t:b);b-=d;switch(d){case 10:this.view[b+9]=g>>>7&1;case 9:this.view[b+8]=9!==d?g|128:g&127;case 8:this.view[b+7]=8!==d?e>>>21|128:e>>>21&127;case 7:this.view[b+6]=
  48 +7!==d?e>>>14|128:e>>>14&127;case 6:this.view[b+5]=6!==d?e>>>7|128:e>>>7&127;case 5:this.view[b+4]=5!==d?e|128:e&127;case 4:this.view[b+3]=4!==d?f>>>21|128:f>>>21&127;case 3:this.view[b+2]=3!==d?f>>>14|128:f>>>14&127;case 2:this.view[b+1]=2!==d?f>>>7|128:f>>>7&127;case 1:this.view[b]=1!==d?f|128:f&127}return c?(this.offset+=d,this):d},e.writeVarint64ZigZag=function(a,b){return this.writeVarint64(h.zigZagEncode64(a),b)},e.readVarint64=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==
  49 +typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}var c=a,d=0,f=0,e=0,g=0,g=this.view[a++],d=g&127;if(g&128&&(g=this.view[a++],d|=(g&127)<<7,g&128||this.noAssert&&"undefined"===typeof g)&&(g=this.view[a++],d|=(g&127)<<14,g&128||this.noAssert&&"undefined"===typeof g)&&(g=this.view[a++],d|=(g&127)<<21,g&128||this.noAssert&&"undefined"===typeof g)&&(g=this.view[a++],
  50 +f=g&127,g&128||this.noAssert&&"undefined"===typeof g)&&(g=this.view[a++],f|=(g&127)<<7,g&128||this.noAssert&&"undefined"===typeof g)&&(g=this.view[a++],f|=(g&127)<<14,g&128||this.noAssert&&"undefined"===typeof g)&&(g=this.view[a++],f|=(g&127)<<21,g&128||this.noAssert&&"undefined"===typeof g)&&(g=this.view[a++],e=g&127,g&128||this.noAssert&&"undefined"===typeof g)&&(g=this.view[a++],e|=(g&127)<<7,g&128||this.noAssert&&"undefined"===typeof g))throw Error("Buffer overrun");d=k.fromBits(d|f<<28,f>>>4|
  51 +e<<24,!1);return b?(this.offset=a,d):{value:d,length:a-c}},e.readVarint64ZigZag=function(a){(a=this.readVarint64(a))&&a.value instanceof k?a.value=h.zigZagDecode64(a.value):a=h.zigZagDecode64(a);return a});e.writeCString=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);var d,f=a.length;if(!this.noAssert){if("string"!==typeof a)throw TypeError("Illegal str: Not a string");for(d=0;d<f;++d)if(0===a.charCodeAt(d))throw RangeError("Illegal str: Contains NULL-characters");if("number"!==typeof b||
  52 +0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}f=n.calculateUTF16asUTF8(m(a))[1];b+=f+1;d=this.buffer.byteLength;b>d&&this.resize((d*=2)>b?d:b);b-=f+1;n.encodeUTF16toUTF8(m(a),function(a){this.view[b++]=a}.bind(this));this.view[b++]=0;return c?(this.offset=b,this):f};e.readCString=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==
  53 +typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}var c=a,d,f=-1;n.decodeUTF8toUTF16(function(){if(0===f)return null;if(a>=this.limit)throw RangeError("Illegal range: Truncated data, "+a+" < "+this.limit);f=this.view[a++];return 0===f?null:f}.bind(this),d=r(),!0);return b?(this.offset=a,d()):{string:d(),length:a-c}};e.writeIString=function(a,b){var c=
  54 +"undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("string"!==typeof a)throw TypeError("Illegal str: Not a string");if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}var d=b,f;f=n.calculateUTF16asUTF8(m(a),this.noAssert)[1];b+=4+f;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);b-=4+f;this.littleEndian?(this.view[b+
  55 +3]=f>>>24&255,this.view[b+2]=f>>>16&255,this.view[b+1]=f>>>8&255,this.view[b]=f&255):(this.view[b]=f>>>24&255,this.view[b+1]=f>>>16&255,this.view[b+2]=f>>>8&255,this.view[b+3]=f&255);b+=4;n.encodeUTF16toUTF8(m(a),function(a){this.view[b++]=a}.bind(this));if(b!==d+4+f)throw RangeError("Illegal range: Truncated data, "+b+" == "+(b+4+f));return c?(this.offset=b,this):b-d};e.readIString=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+
  56 +a+" (not an integer)");a>>>=0;if(0>a||a+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+4) <= "+this.buffer.byteLength);}var c=a,d=this.readUint32(a),d=this.readUTF8String(d,h.METRICS_BYTES,a+=4);a+=d.length;return b?(this.offset=a,d.string):{string:d.string,length:a-c}};h.METRICS_CHARS="c";h.METRICS_BYTES="b";e.writeUTF8String=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+
  57 +b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}var d,f=b;d=n.calculateUTF16asUTF8(m(a))[1];b+=d;var e=this.buffer.byteLength;b>e&&this.resize((e*=2)>b?e:b);b-=d;n.encodeUTF16toUTF8(m(a),function(a){this.view[b++]=a}.bind(this));return c?(this.offset=b,this):b-f};e.writeString=e.writeUTF8String;h.calculateUTF8Chars=function(a){return n.calculateUTF16asUTF8(m(a))[0]};h.calculateUTF8Bytes=function(a){return n.calculateUTF16asUTF8(m(a))[1]};
  58 +h.calculateString=h.calculateUTF8Bytes;e.readUTF8String=function(a,b,c){"number"===typeof b&&(c=b,b=void 0);var d="undefined"===typeof c;d&&(c=this.offset);"undefined"===typeof b&&(b=h.METRICS_CHARS);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal length: "+a+" (not an integer)");a|=0;if("number"!==typeof c||0!==c%1)throw TypeError("Illegal offset: "+c+" (not an integer)");c>>>=0;if(0>c||c+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+c+" (+0) <= "+
  59 +this.buffer.byteLength);}var f=0,e=c,g;if(b===h.METRICS_CHARS){g=r();n.decodeUTF8(function(){return f<a&&c<this.limit?this.view[c++]:null}.bind(this),function(a){++f;n.UTF8toUTF16(a,g)});if(f!==a)throw RangeError("Illegal range: Truncated data, "+f+" == "+a);return d?(this.offset=c,g()):{string:g(),length:c-e}}if(b===h.METRICS_BYTES){if(!this.noAssert){if("number"!==typeof c||0!==c%1)throw TypeError("Illegal offset: "+c+" (not an integer)");c>>>=0;if(0>c||c+a>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+
  60 +c+" (+"+a+") <= "+this.buffer.byteLength);}var k=c+a;n.decodeUTF8toUTF16(function(){return c<k?this.view[c++]:null}.bind(this),g=r(),this.noAssert);if(c!==k)throw RangeError("Illegal range: Truncated data, "+c+" == "+k);return d?(this.offset=c,g()):{string:g(),length:c-e}}throw TypeError("Unsupported metrics: "+b);};e.readString=e.readUTF8String;e.writeVString=function(a,b){var c="undefined"===typeof b;c&&(b=this.offset);if(!this.noAssert){if("string"!==typeof a)throw TypeError("Illegal str: Not a string");
  61 +if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: "+b+" (not an integer)");b>>>=0;if(0>b||b+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+b+" (+0) <= "+this.buffer.byteLength);}var d=b,f,e;f=n.calculateUTF16asUTF8(m(a),this.noAssert)[1];e=h.calculateVarint32(f);b+=e+f;var g=this.buffer.byteLength;b>g&&this.resize((g*=2)>b?g:b);b-=e+f;b+=this.writeVarint32(f,b);n.encodeUTF16toUTF8(m(a),function(a){this.view[b++]=a}.bind(this));if(b!==d+f+e)throw RangeError("Illegal range: Truncated data, "+
  62 +b+" == "+(b+f+e));return c?(this.offset=b,this):b-d};e.readVString=function(a){var b="undefined"===typeof a;b&&(a=this.offset);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+1) <= "+this.buffer.byteLength);}var c=a,d=this.readVarint32(a),d=this.readUTF8String(d.value,h.METRICS_BYTES,a+=d.length);a+=d.length;return b?(this.offset=a,d.string):{string:d.string,
  63 +length:a-c}};e.append=function(a,b,c){if("number"===typeof b||"string"!==typeof b)c=b,b=void 0;var d="undefined"===typeof c;d&&(c=this.offset);if(!this.noAssert){if("number"!==typeof c||0!==c%1)throw TypeError("Illegal offset: "+c+" (not an integer)");c>>>=0;if(0>c||c+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+c+" (+0) <= "+this.buffer.byteLength);}a instanceof h||(a=h.wrap(a,b));b=a.limit-a.offset;if(0>=b)return this;c+=b;var f=this.buffer.byteLength;c>f&&this.resize((f*=2)>
  64 +c?f:c);c-=b;this.view.set(a.view.subarray(a.offset,a.limit),c);a.offset+=b;d&&(this.offset+=b);return this};e.appendTo=function(a,b){a.append(this,b);return this};e.assert=function(a){this.noAssert=!a;return this};e.capacity=function(){return this.buffer.byteLength};e.clear=function(){this.offset=0;this.limit=this.buffer.byteLength;this.markedOffset=-1;return this};e.clone=function(a){var b=new h(0,this.littleEndian,this.noAssert);a?(b.buffer=new ArrayBuffer(this.buffer.byteLength),b.view=new Uint8Array(b.buffer)):
  65 +(b.buffer=this.buffer,b.view=this.view);b.offset=this.offset;b.markedOffset=this.markedOffset;b.limit=this.limit;return b};e.compact=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+
  66 +b+" <= "+this.buffer.byteLength);}if(0===a&&b===this.buffer.byteLength)return this;var c=b-a;if(0===c)return this.buffer=v,this.view=null,0<=this.markedOffset&&(this.markedOffset-=a),this.limit=this.offset=0,this;var d=new ArrayBuffer(c),f=new Uint8Array(d);f.set(this.view.subarray(a,b));this.buffer=d;this.view=f;0<=this.markedOffset&&(this.markedOffset-=a);this.offset=0;this.limit=c;return this};e.copy=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);if(!this.noAssert){if("number"!==
  67 +typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+b+" <= "+this.buffer.byteLength);}if(a===b)return new h(0,this.littleEndian,this.noAssert);var c=b-a,d=new h(c,this.littleEndian,this.noAssert);d.offset=0;d.limit=c;0<=d.markedOffset&&(d.markedOffset-=a);this.copyTo(d,0,a,b);return d};e.copyTo=function(a,
  68 +b,c,d){var f,e;if(!this.noAssert&&!h.isByteBuffer(a))throw TypeError("Illegal target: Not a ByteBuffer");b=(e="undefined"===typeof b)?a.offset:b|0;c=(f="undefined"===typeof c)?this.offset:c|0;d="undefined"===typeof d?this.limit:d|0;if(0>b||b>a.buffer.byteLength)throw RangeError("Illegal target range: 0 <= "+b+" <= "+a.buffer.byteLength);if(0>c||d>this.buffer.byteLength)throw RangeError("Illegal source range: 0 <= "+c+" <= "+this.buffer.byteLength);var g=d-c;if(0===g)return a;a.ensureCapacity(b+g);
  69 +a.view.set(this.view.subarray(c,d),b);f&&(this.offset+=g);e&&(a.offset+=g);return this};e.ensureCapacity=function(a){var b=this.buffer.byteLength;return b<a?this.resize((b*=2)>a?b:a):this};e.fill=function(a,b,c){var d="undefined"===typeof b;d&&(b=this.offset);"string"===typeof a&&0<a.length&&(a=a.charCodeAt(0));"undefined"===typeof b&&(b=this.offset);"undefined"===typeof c&&(c=this.limit);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal value: "+a+" (not an integer)");a|=
  70 +0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal begin: Not an integer");b>>>=0;if("number"!==typeof c||0!==c%1)throw TypeError("Illegal end: Not an integer");c>>>=0;if(0>b||b>c||c>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+b+" <= "+c+" <= "+this.buffer.byteLength);}if(b>=c)return this;for(;b<c;)this.view[b++]=a;d&&(this.offset=b);return this};e.flip=function(){this.limit=this.offset;this.offset=0;return this};e.mark=function(a){a="undefined"===typeof a?this.offset:a;
  71 +if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal offset: "+a+" (not an integer)");a>>>=0;if(0>a||a+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+a+" (+0) <= "+this.buffer.byteLength);}this.markedOffset=a;return this};e.order=function(a){if(!this.noAssert&&"boolean"!==typeof a)throw TypeError("Illegal littleEndian: Not a boolean");this.littleEndian=!!a;return this};e.LE=function(a){this.littleEndian="undefined"!==typeof a?!!a:!0;return this};e.BE=function(a){this.littleEndian=
  72 +"undefined"!==typeof a?!a:!1;return this};e.prepend=function(a,b,c){if("number"===typeof b||"string"!==typeof b)c=b,b=void 0;var d="undefined"===typeof c;d&&(c=this.offset);if(!this.noAssert){if("number"!==typeof c||0!==c%1)throw TypeError("Illegal offset: "+c+" (not an integer)");c>>>=0;if(0>c||c+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+c+" (+0) <= "+this.buffer.byteLength);}a instanceof h||(a=h.wrap(a,b));b=a.limit-a.offset;if(0>=b)return this;var f=b-c;if(0<f){var e=new ArrayBuffer(this.buffer.byteLength+
  73 +f),g=new Uint8Array(e);g.set(this.view.subarray(c,this.buffer.byteLength),b);this.buffer=e;this.view=g;this.offset+=f;0<=this.markedOffset&&(this.markedOffset+=f);this.limit+=f;c+=f}else new Uint8Array(this.buffer);this.view.set(a.view.subarray(a.offset,a.limit),c-b);a.offset=a.limit;d&&(this.offset-=b);return this};e.prependTo=function(a,b){a.prepend(this,b);return this};e.printDebug=function(a){"function"!==typeof a&&(a=console.log.bind(console));a(this.toString()+"\n-------------------------------------------------------------------\n"+
  74 +this.toDebug(!0))};e.remaining=function(){return this.limit-this.offset};e.reset=function(){0<=this.markedOffset?(this.offset=this.markedOffset,this.markedOffset=-1):this.offset=0;return this};e.resize=function(a){if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal capacity: "+a+" (not an integer)");a|=0;if(0>a)throw RangeError("Illegal capacity: 0 <= "+a);}if(this.buffer.byteLength<a){a=new ArrayBuffer(a);var b=new Uint8Array(a);b.set(this.view);this.buffer=a;this.view=b}return this};
  75 +e.reverse=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+b+" <= "+this.buffer.byteLength);}if(a===b)return this;Array.prototype.reverse.call(this.view.subarray(a,b));return this};
  76 +e.skip=function(a){if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal length: "+a+" (not an integer)");a|=0}var b=this.offset+a;if(!this.noAssert&&(0>b||b>this.buffer.byteLength))throw RangeError("Illegal length: 0 <= "+this.offset+" + "+a+" <= "+this.buffer.byteLength);this.offset=b;return this};e.slice=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer");
  77 +a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+b+" <= "+this.buffer.byteLength);}var c=this.clone();c.offset=a;c.limit=b;return c};e.toBuffer=function(a){var b=this.offset,c=this.limit;if(!this.noAssert){if("number"!==typeof b||0!==b%1)throw TypeError("Illegal offset: Not an integer");b>>>=0;if("number"!==typeof c||0!==c%1)throw TypeError("Illegal limit: Not an integer");
  78 +c>>>=0;if(0>b||b>c||c>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+b+" <= "+c+" <= "+this.buffer.byteLength);}if(!a&&0===b&&c===this.buffer.byteLength)return this.buffer;if(b===c)return v;a=new ArrayBuffer(c-b);(new Uint8Array(a)).set((new Uint8Array(this.buffer)).subarray(b,c),0);return a};e.toArrayBuffer=e.toBuffer;e.toString=function(a,b,c){if("undefined"===typeof a)return"ByteBufferAB(offset="+this.offset+",markedOffset="+this.markedOffset+",limit="+this.limit+",capacity="+this.capacity()+
  79 +")";"number"===typeof a&&(c=b=a="utf8");switch(a){case "utf8":return this.toUTF8(b,c);case "base64":return this.toBase64(b,c);case "hex":return this.toHex(b,c);case "binary":return this.toBinary(b,c);case "debug":return this.toDebug();case "columns":return this.toColumns();default:throw Error("Unsupported encoding: "+a);}};var x=function(){for(var a={},b=[65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,
  80 +114,115,116,117,118,119,120,121,122,48,49,50,51,52,53,54,55,56,57,43,47],c=[],d=0,f=b.length;d<f;++d)c[b[d]]=d;a.encode=function(a,c){for(var d,f;null!==(d=a());)c(b[d>>2&63]),f=(d&3)<<4,null!==(d=a())?(f|=d>>4&15,c(b[(f|d>>4&15)&63]),f=(d&15)<<2,null!==(d=a())?(c(b[(f|d>>6&3)&63]),c(b[d&63])):(c(b[f&63]),c(61))):(c(b[f&63]),c(61),c(61))};a.decode=function(a,b){function d(a){throw Error("Illegal character code: "+a);}for(var f,e,h;null!==(f=a());)if(e=c[f],"undefined"===typeof e&&d(f),null!==(f=a())&&
  81 +(h=c[f],"undefined"===typeof h&&d(f),b(e<<2>>>0|(h&48)>>4),null!==(f=a()))){e=c[f];if("undefined"===typeof e)if(61===f)break;else d(f);b((h&15)<<4>>>0|(e&60)>>2);if(null!==(f=a())){h=c[f];if("undefined"===typeof h)if(61===f)break;else d(f);b((e&3)<<6>>>0|h)}}};a.test=function(a){return/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(a)};return a}();e.toBase64=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);a|=0;b|=0;if(0>a||b>this.capacity||
  82 +a>b)throw RangeError("begin, end");var c;x.encode(function(){return a<b?this.view[a++]:null}.bind(this),c=r());return c()};h.fromBase64=function(a,b){if("string"!==typeof a)throw TypeError("str");var c=new h(a.length/4*3,b),d=0;x.decode(m(a),function(a){c.view[d++]=a});c.limit=d;return c};h.btoa=function(a){return h.fromBinary(a).toBase64()};h.atob=function(a){return h.fromBase64(a).toBinary()};e.toBinary=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);
  83 +a|=0;b|=0;if(0>a||b>this.capacity()||a>b)throw RangeError("begin, end");if(a===b)return"";for(var c=[],d=[];a<b;)c.push(this.view[a++]),1024<=c.length&&(d.push(String.fromCharCode.apply(String,c)),c=[]);return d.join("")+String.fromCharCode.apply(String,c)};h.fromBinary=function(a,b){if("string"!==typeof a)throw TypeError("str");for(var c=0,d=a.length,f,e=new h(d,b);c<d;){f=a.charCodeAt(c);if(255<f)throw RangeError("illegal char code: "+f);e.view[c++]=f}e.limit=d;return e};e.toDebug=function(a){for(var b=
  84 +-1,c=this.buffer.byteLength,d,f="",e="",g="";b<c;){-1!==b&&(d=this.view[b],f=16>d?f+("0"+d.toString(16).toUpperCase()):f+d.toString(16).toUpperCase(),a&&(e+=32<d&&127>d?String.fromCharCode(d):"."));++b;if(a&&0<b&&0===b%16&&b!==c){for(;51>f.length;)f+=" ";g+=f+e+"\n";f=e=""}f=b===this.offset&&b===this.limit?f+(b===this.markedOffset?"!":"|"):b===this.offset?f+(b===this.markedOffset?"[":"<"):b===this.limit?f+(b===this.markedOffset?"]":">"):f+(b===this.markedOffset?"'":a||0!==b&&b!==c?" ":"")}if(a&&" "!==
  85 +f){for(;51>f.length;)f+=" ";g+=f+e+"\n"}return a?g:f};h.fromDebug=function(a,b,c){var d=a.length;b=new h((d+1)/3|0,b,c);for(var f=0,e=0,g,k=!1,m=!1,n=!1,p=!1,q=!1;f<d;){switch(g=a.charAt(f++)){case "!":if(!c){if(m||n||p){q=!0;break}m=n=p=!0}b.offset=b.markedOffset=b.limit=e;k=!1;break;case "|":if(!c){if(m||p){q=!0;break}m=p=!0}b.offset=b.limit=e;k=!1;break;case "[":if(!c){if(m||n){q=!0;break}m=n=!0}b.offset=b.markedOffset=e;k=!1;break;case "<":if(!c){if(m){q=!0;break}m=!0}b.offset=e;k=!1;break;case "]":if(!c){if(p||
  86 +n){q=!0;break}p=n=!0}b.limit=b.markedOffset=e;k=!1;break;case ">":if(!c){if(p){q=!0;break}p=!0}b.limit=e;k=!1;break;case "'":if(!c){if(n){q=!0;break}n=!0}b.markedOffset=e;k=!1;break;case " ":k=!1;break;default:if(!c&&k){q=!0;break}g=parseInt(g+a.charAt(f++),16);if(!c&&(isNaN(g)||0>g||255<g))throw TypeError("Illegal str: Not a debug encoded string");b.view[e++]=g;k=!0}if(q)throw TypeError("Illegal str: Invalid symbol at "+f);}if(!c){if(!m||!p)throw TypeError("Illegal str: Missing offset or limit");
  87 +if(e<b.buffer.byteLength)throw TypeError("Illegal str: Not a debug encoded string (is it hex?) "+e+" < "+d);}return b};e.toHex=function(a,b){a="undefined"===typeof a?this.offset:a;b="undefined"===typeof b?this.limit:b;if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+a+" <= "+b+" <= "+
  88 +this.buffer.byteLength);}for(var c=Array(b-a),d;a<b;)d=this.view[a++],16>d?c.push("0",d.toString(16)):c.push(d.toString(16));return c.join("")};h.fromHex=function(a,b,c){if(!c){if("string"!==typeof a)throw TypeError("Illegal str: Not a string");if(0!==a.length%2)throw TypeError("Illegal str: Length not a multiple of 2");}var d=a.length;b=new h(d/2|0,b);for(var f,e=0,g=0;e<d;e+=2){f=parseInt(a.substring(e,e+2),16);if(!c&&(!isFinite(f)||0>f||255<f))throw TypeError("Illegal str: Contains non-hex characters");
  89 +b.view[g++]=f}b.limit=g;return b};var n=function(){var a={MAX_CODEPOINT:1114111,encodeUTF8:function(a,c){var d=null;"number"===typeof a&&(d=a,a=function(){return null});for(;null!==d||null!==(d=a());)128>d?c(d&127):(2048>d?c(d>>6&31|192):(65536>d?c(d>>12&15|224):(c(d>>18&7|240),c(d>>12&63|128)),c(d>>6&63|128)),c(d&63|128)),d=null},decodeUTF8:function(a,c){for(var d,f,e,g,h=function(a){a=a.slice(0,a.indexOf(null));var b=Error(a.toString());b.name="TruncatedError";b.bytes=a;throw b;};null!==(d=a());)if(0===
  90 +(d&128))c(d);else if(192===(d&224))null===(f=a())&&h([d,f]),c((d&31)<<6|f&63);else if(224===(d&240))null!==(f=a())&&null!==(e=a())||h([d,f,e]),c((d&15)<<12|(f&63)<<6|e&63);else if(240===(d&248))null!==(f=a())&&null!==(e=a())&&null!==(g=a())||h([d,f,e,g]),c((d&7)<<18|(f&63)<<12|(e&63)<<6|g&63);else throw RangeError("Illegal starting byte: "+d);},UTF16toUTF8:function(a,c){for(var d,e=null;null!==(d=null!==e?e:a());)55296<=d&&57343>=d&&null!==(e=a())&&56320<=e&&57343>=e?(c(1024*(d-55296)+e-56320+65536),
  91 +e=null):c(d);null!==e&&c(e)},UTF8toUTF16:function(a,c){var d=null;"number"===typeof a&&(d=a,a=function(){return null});for(;null!==d||null!==(d=a());)65535>=d?c(d):(d-=65536,c((d>>10)+55296),c(d%1024+56320)),d=null},encodeUTF16toUTF8:function(b,c){a.UTF16toUTF8(b,function(b){a.encodeUTF8(b,c)})},decodeUTF8toUTF16:function(b,c){a.decodeUTF8(b,function(b){a.UTF8toUTF16(b,c)})},calculateCodePoint:function(a){return 128>a?1:2048>a?2:65536>a?3:4},calculateUTF8:function(a){for(var c,d=0;null!==(c=a());)d+=
  92 +128>c?1:2048>c?2:65536>c?3:4;return d},calculateUTF16asUTF8:function(b){var c=0,d=0;a.UTF16toUTF8(b,function(a){++c;d+=128>a?1:2048>a?2:65536>a?3:4});return[c,d]}};return a}();e.toUTF8=function(a,b){"undefined"===typeof a&&(a=this.offset);"undefined"===typeof b&&(b=this.limit);if(!this.noAssert){if("number"!==typeof a||0!==a%1)throw TypeError("Illegal begin: Not an integer");a>>>=0;if("number"!==typeof b||0!==b%1)throw TypeError("Illegal end: Not an integer");b>>>=0;if(0>a||a>b||b>this.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+
  93 +a+" <= "+b+" <= "+this.buffer.byteLength);}var c;try{n.decodeUTF8toUTF16(function(){return a<b?this.view[a++]:null}.bind(this),c=r())}catch(d){if(a!==b)throw RangeError("Illegal range: Truncated data, "+a+" != "+b);}return c()};h.fromUTF8=function(a,b,c){if(!c&&"string"!==typeof a)throw TypeError("Illegal str: Not a string");var d=new h(n.calculateUTF16asUTF8(m(a),!0)[1],b,c),e=0;n.encodeUTF16toUTF8(m(a),function(a){d.view[e++]=a});d.limit=e;return d};return h});
@@ -42,10 +42,10 @@ class MCU extends Emiter { @@ -42,10 +42,10 @@ class MCU extends Emiter {
42 } 42 }
43 43
44 44
45 - //MCU-发送加入会议请求 45 + //MCU-发送加入课堂请求
46 _sendJoinClassRequest(){ 46 _sendJoinClassRequest(){
47 //const classInfo = this.classInfo; 47 //const classInfo = this.classInfo;
48 - loger.log('MCU-发送加入会议请求.'); 48 + loger.log('MCU-发送加入课堂请求.');
49 console.log(this.classInfo); 49 console.log(this.classInfo);
50 var descriptorPdu = new pdu['RCConferenceDescriptorPdu']; 50 var descriptorPdu = new pdu['RCConferenceDescriptorPdu'];
51 descriptorPdu.id = this.classInfo.classId; 51 descriptorPdu.id = this.classInfo.classId;
@@ -90,7 +90,7 @@ class MCU extends Emiter { @@ -90,7 +90,7 @@ class MCU extends Emiter {
90 //loger.log('MCU-FirstLayer封装消息', 'type', pdu.id2type(pduMsg.type), pduMsg.type, 'sessionId', ApeConsts(pduMsg.sessionId), pduMsg.sessionId); 90 //loger.log('MCU-FirstLayer封装消息', 'type', pdu.id2type(pduMsg.type), pduMsg.type, 'sessionId', ApeConsts(pduMsg.sessionId), pduMsg.sessionId);
91 switch (pduType) { 91 switch (pduType) {
92 case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE: 92 case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE:
93 - //加入会议请求返回数据处理 93 + //加入课堂请求返回数据处理
94 let joinConfPdu = pdu['RCConferenceJoinResponsePdu'].decode(pduData); 94 let joinConfPdu = pdu['RCConferenceJoinResponsePdu'].decode(pduData);
95 let pduResultCode = joinConfPdu.result; 95 let pduResultCode = joinConfPdu.result;
96 loger.warn( 'RCPDU_CONNECT_PROVIDER_RESPONSE ->pduResultCode:'+pduResultCode); 96 loger.warn( 'RCPDU_CONNECT_PROVIDER_RESPONSE ->pduResultCode:'+pduResultCode);
@@ -146,13 +146,13 @@ class MCU extends Emiter { @@ -146,13 +146,13 @@ class MCU extends Emiter {
146 return false; 146 return false;
147 } 147 }
148 148
149 - // 会议发送消息 -- 消息同意序列号 149 + // 课堂发送消息 -- 消息同意序列号
150 send(msg) { 150 send(msg) {
151 if (this.connected) { 151 if (this.connected) {
152 - loger.log('MCU-发送会议数据....'); 152 + loger.log('MCU-发送课堂数据....');
153 this._everSocket.send(msg.toArrayBuffer()); 153 this._everSocket.send(msg.toArrayBuffer());
154 } else { 154 } else {
155 - loger.log('MCU-发送会议数据失败,MCU底层通道不可用'); 155 + loger.log('MCU-发送课堂数据失败,MCU底层通道不可用');
156 this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_SOCKET_DISCONNECT); 156 this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_SOCKET_DISCONNECT);
157 } 157 }
158 } 158 }
1 export default function RCPduPackage(targe_type_id) {}; 1 export default function RCPduPackage(targe_type_id) {};
2 2
3 -RCPduPackage.RCPDU_CONNECT_PROVIDER_REQUEST = 0;//加入MCU会议的请求  
4 -RCPduPackage.RCPDU_CONNECT_PROVIDER_RESPONSE = 1;//返回MCU会议请求结果 3 +RCPduPackage.RCPDU_CONNECT_PROVIDER_REQUEST = 0;//加入MCU课堂的请求
  4 +RCPduPackage.RCPDU_CONNECT_PROVIDER_RESPONSE = 1;//返回MCU课堂请求结果
5 5
6 //下面两个是在入会成功之后,创建pdu包时设置的type值 6 //下面两个是在入会成功之后,创建pdu包时设置的type值
7 RCPduPackage.RCPDU_UNIFORM_SEND_DATA_REQUEST = 125;//发送uniform_pdu 7 RCPduPackage.RCPDU_UNIFORM_SEND_DATA_REQUEST = 125;//发送uniform_pdu