李勇

修改开启录制和停止录制的逻辑,课堂开启录制之后只有课堂内主动调用停止或课堂内10分钟没有人的时候才会停止

@@ -58,7 +58,7 @@ export default class MessageEntrance extends Emiter { @@ -58,7 +58,7 @@ export default class MessageEntrance extends Emiter {
58 constructor() { 58 constructor() {
59 super(); 59 super();
60 //sdk 信息 60 //sdk 信息
61 - GlobalConfig.sdkVersion = "v1.80.1.20170823"; 61 + GlobalConfig.sdkVersion = "v1.81.1.20170824";
62 loger.warn("sdkVersion:" + GlobalConfig.sdkVersion); 62 loger.warn("sdkVersion:" + GlobalConfig.sdkVersion);
63 63
64 //设置 64 //设置
@@ -127,8 +127,10 @@ export default class MessageEntrance extends Emiter { @@ -127,8 +127,10 @@ export default class MessageEntrance extends Emiter {
127 _confer_ape.on(MessageTypes.CLASS_STATUS_INFO_CHANGE, this._onClassStatusInfoChange.bind(this)); //当前课堂状态信息发生改变 127 _confer_ape.on(MessageTypes.CLASS_STATUS_INFO_CHANGE, this._onClassStatusInfoChange.bind(this)); //当前课堂状态信息发生改变
128 _confer_ape.on(MessageTypes.CLASS_DELETE_ROSTER, this._onClassDeleteRoster.bind(this)); //当前课堂人员离开 128 _confer_ape.on(MessageTypes.CLASS_DELETE_ROSTER, this._onClassDeleteRoster.bind(this)); //当前课堂人员离开
129 _confer_ape.on(MessageTypes.CLASS_NONENTITY_ROSTER, this._onClassNonentityRoster.bind(this)); //当前课堂中视频或音频占用channel的nodeId ,在人员列表中不存在 129 _confer_ape.on(MessageTypes.CLASS_NONENTITY_ROSTER, this._onClassNonentityRoster.bind(this)); //当前课堂中视频或音频占用channel的nodeId ,在人员列表中不存在
  130 +
130 _confer_ape.on(MessageTypes.CLASS_RECORD_START, this._onClassRecordStart.bind(this)); //课堂开始录制 131 _confer_ape.on(MessageTypes.CLASS_RECORD_START, this._onClassRecordStart.bind(this)); //课堂开始录制
131 _confer_ape.on(MessageTypes.CLASS_RECORD_SUCCESS, this._onClassRecordSuccess.bind(this)); //课堂开启录制成功 132 _confer_ape.on(MessageTypes.CLASS_RECORD_SUCCESS, this._onClassRecordSuccess.bind(this)); //课堂开启录制成功
  133 +
132 _confer_ape.on(MessageTypes.SWITCH_MS_IP, this._switchMsIpHandler.bind(this)); //MS动态选点 134 _confer_ape.on(MessageTypes.SWITCH_MS_IP, this._switchMsIpHandler.bind(this)); //MS动态选点
133 //_confer_ape.on(MessageTypes.SWITCH_RTMP_PULL_IP, this._switchRtmpPullIpHandler.bind(this)); //MS 拉流地址动态选点 135 //_confer_ape.on(MessageTypes.SWITCH_RTMP_PULL_IP, this._switchRtmpPullIpHandler.bind(this)); //MS 拉流地址动态选点
134 //_confer_ape.on(MessageTypes.SWITCH_HLS_IP, this._switchHlsIpHandler.bind(this)); //MS HLS动态选点 136 //_confer_ape.on(MessageTypes.SWITCH_HLS_IP, this._switchHlsIpHandler.bind(this)); //MS HLS动态选点
@@ -406,7 +408,7 @@ export default class MessageEntrance extends Emiter { @@ -406,7 +408,7 @@ export default class MessageEntrance extends Emiter {
406 408
407 //如果是第一次点击开始上课,需要创建录制时的文件名 409 //如果是第一次点击开始上课,需要创建录制时的文件名
408 _onClassRecordStart(_param) { 410 _onClassRecordStart(_param) {
409 - if (GlobalConfig.getCurrentStatus().code != GlobalConfig.statusCode_2.code) { 411 + if (!_mcu||!_mcu.connected) {
410 loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus()); 412 loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());
411 return; 413 return;
412 } 414 }
@@ -1355,6 +1357,9 @@ export default class MessageEntrance extends Emiter { @@ -1355,6 +1357,9 @@ export default class MessageEntrance extends Emiter {
1355 } 1357 }
1356 1358
1357 if (_confer_ape) { 1359 if (_confer_ape) {
  1360 + //开始录制
  1361 + _confer_ape.startRecord();
  1362 + //开始上课
1358 _confer_ape.startClass(_param); 1363 _confer_ape.startClass(_param);
1359 } 1364 }
1360 } 1365 }
@@ -1476,7 +1481,7 @@ export default class MessageEntrance extends Emiter { @@ -1476,7 +1481,7 @@ export default class MessageEntrance extends Emiter {
1476 1481
1477 //停止上课 1482 //停止上课
1478 _sendCloseClass(_param) { 1483 _sendCloseClass(_param) {
1479 - if (!_mcu.connected) { 1484 + if (!_mcu||!_mcu.connected) {
1480 loger.warn(GlobalConfig.getCurrentStatus()); 1485 loger.warn(GlobalConfig.getCurrentStatus());
1481 return {"code": ApeConsts.RETURN_FAILED, "data": ""}; 1486 return {"code": ApeConsts.RETURN_FAILED, "data": ""};
1482 } 1487 }
@@ -1502,7 +1507,7 @@ export default class MessageEntrance extends Emiter { @@ -1502,7 +1507,7 @@ export default class MessageEntrance extends Emiter {
1502 } 1507 }
1503 //离开课堂 1508 //离开课堂
1504 if (_confer_ape) { 1509 if (_confer_ape) {
1505 - _confer_ape.stopRecord(); 1510 + //_confer_ape.stopRecord();//不主动调用停止录制
1506 _confer_ape.leaveClass(); 1511 _confer_ape.leaveClass();
1507 } 1512 }
1508 1513
@@ -1618,11 +1623,13 @@ export default class MessageEntrance extends Emiter { @@ -1618,11 +1623,13 @@ export default class MessageEntrance extends Emiter {
1618 //存储Sass数据到本地 1623 //存储Sass数据到本地
1619 if (_data.currentInfo) { 1624 if (_data.currentInfo) {
1620 //根据从Sass获取的数据信息,同步最后一次保存的课堂状态信息 1625 //根据从Sass获取的数据信息,同步最后一次保存的课堂状态信息
  1626 + loger.log("从Saas返回的课堂状态信息数据",_data.currentInfo);
1621 try { 1627 try {
1622 - GlobalConfig.setClassStatusInfo(JSON.parse(_data.currentInfo)); 1628 + let dataObj=JSON.parse(_data.currentInfo);
  1629 + dataObj.recordStatus=false;
  1630 + GlobalConfig.setClassStatusInfo(dataObj);
1623 } catch (err) { 1631 } catch (err) {
1624 loger.warn("从Sass获取的课堂数据JSON转换失败->"); 1632 loger.warn("从Sass获取的课堂数据JSON转换失败->");
1625 - console.log("currentInfo", _data.currentInfo);  
1626 GlobalConfig.setClassStatusInfo(_data.currentInfo); 1633 GlobalConfig.setClassStatusInfo(_data.currentInfo);
1627 } 1634 }
1628 loger.log(GlobalConfig.classStatusInfo); 1635 loger.log(GlobalConfig.classStatusInfo);
1 -require('es6-promise').polyfill();  
2 -require('whatwg-fetch');  
3 -require('jquery-touchswipe');  
4 -require('string.fromcodepoint');  
5 -//require('messenger');  
6 -  
7 -import Emiter from './Emiter';  
8 -import Sass from 'Sass';  
9 -import IpManager from 'IpManager';  
10 -import RecordPlayBackParse from 'RecordPlayBackParse';  
11 -import MD5 from "md5";  
12 -import Mcu from 'mcu';  
13 -import MessageTypes from 'MessageTypes';  
14 -import Loger from 'Loger';  
15 -import ConferApe from 'apes/ConferApe';  
16 -import ChatApe from 'apes/ChatApe';  
17 -import VideoApe from 'apes/VideoApe';  
18 -import AudioApe from 'apes/AudioApe';  
19 -import DocApe from 'apes/DocApe';  
20 -import WhiteBoardApe from 'apes/WhiteBoardApe';  
21 -import CursorApe from 'apes/CursorApe';  
22 -  
23 -import EngineUtils from "EngineUtils";  
24 -import GlobalConfig from 'GlobalConfig';  
25 -import SystemConfig from 'SystemConfig';  
26 -  
27 -import ApeConsts from 'apes/ApeConsts';  
28 -import Base64 from 'base64-js';  
29 -import ArrayBufferUtil from 'libs/ArrayBufferUtil';  
30 -import Server from "config/Server";  
31 -import MediaModule from 'apes/MediaModule';  
32 -import MediaSharedApe from 'apes/MediaSharedApe';  
33 -import MusicSharedApe from 'apes/MusicSharedApe';  
34 -import QuestionApe from 'apes/QuestionApe';  
35 -import UTF8 from 'utf-8';  
36 -  
37 -let loger = Loger.getLoger('McuClient');  
38 -let _sdkInfo = {"version": "v1.55.1.20170727", "author": "www.3mang.com"};  
39 -  
40 -//APE  
41 -let _sass;  
42 -let _ipManager;  
43 -let _mcu;  
44 -let _confer_ape;  
45 -let _chat_ape;  
46 -let _video_ape;  
47 -let _audio_ape;  
48 -let _doc_ape;  
49 -let _whiteboard_ape;  
50 -let _cursor_ape;  
51 -let _recordPlayback;  
52 -let _mediaShareApe;  
53 -let _musicShareApe;  
54 -let _questionApe;  
55 -  
56 -//MCUClient 外部实例化主类  
57 -export default class EngineEntranceOld extends Emiter {  
58 - constructor() {  
59 - super();  
60 - //sdk 信息  
61 - this.sdkInfo = _sdkInfo;  
62 - loger.warn(this.sdkInfo);  
63 - //获取设备和系统信息  
64 - SystemConfig.getSystemInfo();  
65 -  
66 - this.classRecordStatusUpdateTimer = 0; //课堂录制状态发生改变后同步当前所有模块数据的计时器  
67 - //初始化状态  
68 - this.isGetUserIpCallback = false; //是否获取IP信息返回  
69 - this.isGetFastestMcuCallback = false; //是否MCU测速结束  
70 - this.isGetFastestMsCallback = false; //是否MS测速结束  
71 - this.isGetFastestRtmpPullCallback = false; //是否RTMP拉流地址测试结束  
72 - this.isGetFastestHlsPullCallback = false; //是否HLS拉流地址测试结束  
73 - this.isGetFastestRsCallback = false; //是否录制回放HLS拉流地址测试结束  
74 -  
75 - //全局的Error处理  
76 - this.on(MessageTypes.MCU_ERROR, this._mcuErrorHandler.bind(this));  
77 -  
78 - // Sass平台层  
79 - _sass = Sass;  
80 - _sass.on('*', (type, data) => this._emit(type, data));  
81 - _sass.on(_sass.SUCCESS, this._sassJoinSuccessHandler.bind(this)); //通过SASS平台验证(密码和MD5)  
82 - _sass.on(_sass.CLASS_INIT_SUCCESS, this._sassInitSuccessHandler.bind(this)); //获取课堂初始化信息  
83 - //_sass.on(_sass.CLASS_GET_CLASS_DETAIL, this._sassGetClassDetailSuccessHandler.bind(this));//获取课堂的基本信息  
84 - _sass.on(_sass.CLASS_GET_CLASS_PARAM, this._sassGetClassParamSuccessHandler.bind(this)); //获取课堂的最全信息和历史保存的数据  
85 -  
86 - _sass.on(_sass.CLASS_SAVE_STATUS_INFO_SUCCESS, this._sassSaveClassStatusInfoSuccessHandler.bind(this)); //保存课堂状态信息  
87 - _sass.on(_sass.CLASS_SAVE_RECORD_INFO_SUCCESS, this._sassSaveClassRecordInfoSuccessHandler.bind(this)); //保存课堂录制信息  
88 - _sass.on(_sass.DELETE_DOCUMENT_SUCCESS, this._sassDeleteDocumentSuccess.bind(this)); //sass删除文档成功  
89 - _sass.on(_sass.DELETE_MEDIASHARE_SUCCESS, this._sassDeleteMediaShareSuccess.bind(this)); //sass删除媒体文件成功  
90 - _sass.on(_sass.DELETE_MUSICSHARE_SUCCESS, this._sassDeleteMusicShareSuccess.bind(this)); //sass删除MUSIC文件成功  
91 -  
92 - //选点模块  
93 - _ipManager = new IpManager();  
94 -  
95 - // 底层MCU消息层  
96 - _mcu = Mcu;  
97 - _mcu.on('*', (type, data) => this._emit(type, data));  
98 - _mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuJoinMCUClassSuccessHandler.bind(this)); //加入MCU课堂完成  
99 - _mcu.on(MessageTypes.SWITCH_MCU_IP, this._switchMcuIpHandler.bind(this)); //切换MCU,重新选点  
100 -  
101 - //录制回放  
102 - _recordPlayback = RecordPlayBackParse;  
103 - _recordPlayback.on('*', (type, data) => this._emit(type, data));  
104 - _recordPlayback.on(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS, this._joinRecordPlaybackSuccessHandler.bind(this)); //加入录制回放完成  
105 - _recordPlayback.on(RecordPlayBackParse.RECORD_PLAYBACK_CLEAR_DATA, this._recordPlaybackClearDataHandler.bind(this)); //录制回放状态更新  
106 -  
107 - // 注册所有应用Ape  
108 - _confer_ape = new ConferApe();  
109 - _confer_ape.on('*', (type, data) => this._emit(type, data));  
110 - _confer_ape.on(MessageTypes.CLASS_RUN_EXIT, this._runClassExit.bind(this)); //监听自己的关闭事件  
111 - _confer_ape.on(MessageTypes.CLASS_STATUS_INFO_CHANGE, this._onClassStatusInfoChange.bind(this)); //当前课堂状态信息发生改变  
112 - _confer_ape.on(MessageTypes.CLASS_DELETE_ROSTER, this._onClassDeleteRoster.bind(this)); //当前课堂人员离开  
113 - _confer_ape.on(MessageTypes.CLASS_NONENTITY_ROSTER, this._onClassNonentityRoster.bind(this)); //当前课堂中视频或音频占用channel的nodeId ,在人员列表中不存在  
114 - _confer_ape.on(MessageTypes.CLASS_RECORD_START, this._onClassRecordStart.bind(this)); //课堂开始录制  
115 - _confer_ape.on(MessageTypes.CLASS_RECORD_SUCCESS, this._onClassRecordSuccess.bind(this)); //课堂开启录制成功  
116 - _confer_ape.on(MessageTypes.SWITCH_MS_IP, this._switchMsIpHandler.bind(this)); //MS动态选点  
117 - //_confer_ape.on(MessageTypes.SWITCH_RTMP_PULL_IP, this._switchRtmpPullIpHandler.bind(this)); //MS 拉流地址动态选点  
118 - //_confer_ape.on(MessageTypes.SWITCH_HLS_IP, this._switchHlsIpHandler.bind(this)); //MS HLS动态选点  
119 - _confer_ape.on(MessageTypes.STOP_ALL_MEDIA_PUBLISH, this._stopAllMediaPublishHandler.bind(this)); //课堂状态发生改变,需要停止当前的所有推流  
120 -  
121 - _chat_ape = new ChatApe();  
122 - _chat_ape.on('*', (type, data) => this._emit(type, data));  
123 -  
124 - _video_ape = new VideoApe();  
125 - _video_ape.on('*', (type, data) => this._emit(type, data));  
126 - _video_ape.on(MessageTypes.VIDEO_UPDATE, this.videoUpdate.bind(this)); //这个监听事件不能删除,需要通知课堂模块,检查channel占用  
127 - _video_ape.on(MessageTypes.USER_DEVICE_STATUS_CHAANGE, this.userDeviecStatusChange.bind(this)); //监听摄像头和麦克风的开启状态  
128 -  
129 - _audio_ape = new AudioApe();  
130 - _audio_ape.on('*', (type, data) => this._emit(type, data));  
131 - _audio_ape.on(MessageTypes.AUDIO_UPDATE, this.audioUpdate.bind(this)); //这个监听事件不能删除,需要通知课堂模块,检查channel占用  
132 - _audio_ape.on(MessageTypes.USER_DEVICE_STATUS_CHAANGE, this.userDeviecStatusChange.bind(this)); //监听摄像头和麦克风的开启状态  
133 -  
134 - _mediaShareApe = new MediaSharedApe();  
135 - _mediaShareApe.on('*', (type, data) => this._emit(type, data));  
136 - _mediaShareApe.on(MediaSharedApe.MEDIASHARED_JOIN_CHANNEL_SUCCESS, this.mediaShareApeJoinChannelSuccess.bind(this));  
137 -  
138 - _musicShareApe = new MusicSharedApe();  
139 - _musicShareApe.on('*', (type, data) => this._emit(type, data));  
140 - _musicShareApe.on(MusicSharedApe.MUSICSHARED_JOIN_CHANNEL_SUCCESS, this.musicShareApeJoinChannelSuccess.bind(this));  
141 -  
142 - _whiteboard_ape = new WhiteBoardApe();  
143 - _whiteboard_ape.on('*', (type, data) => this._emit(type, data));  
144 -  
145 - _cursor_ape = new CursorApe();  
146 - _cursor_ape.on('*', (type, data) => this._emit(type, data));  
147 -  
148 - _doc_ape = new DocApe();  
149 - _doc_ape.on('*', (type, data) => this._emit(type, data));  
150 - _doc_ape.on(MessageTypes.DOC_UPDATE, this.docUpdateHandler.bind(this));  
151 - _doc_ape.on(MessageTypes.DOC_DELETE, this.docDeleteHandler.bind(this));  
152 - _doc_ape.on(DocApe.DOC_JOIN_CHANNEL_SUCCESS, this.docJoinChannelSuccess.bind(this));  
153 -  
154 - _questionApe = new QuestionApe();  
155 - _questionApe.on('*', (type, data) => this._emit(type, data));  
156 -  
157 - //公开外部调用的方法  
158 - //class  
159 - this.init = this._init.bind(this);  
160 - this.joinClass = this._joinClass.bind(this);  
161 - this.leaveClass = this._leaveClass.bind(this);  
162 - this.getMcuClientStatus = this._getMcuClientStatus.bind(this);  
163 - this.getClassStatusInfo = this._getClassStatusInfo.bind(this);  
164 - this.sendStartClass = this._sendStartClass.bind(this);  
165 - this.silenceClass = this._silenceClass.bind(this);  
166 - this.sendPauseClass = this._sendPauseClass.bind(this);  
167 - this.sendCloseClass = this._sendCloseClass.bind(this);  
168 - this.changeHandUpStatus = this._changeHandUpStatus.bind(this); //自己切换举手状态  
169 - this.controlHandUpStatus = this._controlHandUpStatus.bind(this); //控制别人的举手状态  
170 - this.controlSilenceStatus = this._controlSilenceStatus.bind(this); //改变禁言状态  
171 -  
172 - this.sceneTableChange = this._sceneTableChange.bind(this); //切换模块显示  
173 -  
174 - this.kickOutRosterFormNodeId = this._kickOutRosterFormNodeId.bind(this); //把指定nodeId的人踢出课堂  
175 -  
176 - this.sendThridChannelMessage = this._sendThridChannelMessage.bind(this);//通道第三方消息通道发送消息  
177 -  
178 - //录制回放  
179 - this.initRecordPlayback = this._initRecordPlayback.bind(this);  
180 - this.startRecordPlayback = this._startRecordPlayback.bind(this);  
181 - this.stopRecordPlayback = this._stopRecordPlayback.bind(this);  
182 - this.pauseRecordPlayback = this._pauseRecordPlayback.bind(this);  
183 - this.seekRecordPlayback = this._seekRecordPlayback.bind(this);  
184 -  
185 - //chatApe  
186 - this.sendChatMsg = this._sendChatMsg.bind(this);  
187 -  
188 - //屏幕共享  
189 - this.publishScreenShare = this._publishScreenShare.bind(this);  
190 - this.stopPublishScreenShare = this._stopPublishScreenShare.bind(this);  
191 -  
192 - //videoApe  
193 - //this.getVideoPlayPath = this._getVideoPlayPath.bind(this);  
194 - this.getVideoPublishPath = this._getVideoPublishPath.bind(this);  
195 - this.getVideoAllChannelInfo = this._getVideoAllChannelInfo.bind(this);  
196 - this.publishVideo = this._publishVideo.bind(this);  
197 - this.stopPublishVideo = this.unPublishVideo = this._stopPublishVideo.bind(this);  
198 - this.sendVideoBroadcastMsg = this._sendVideoBroadcastMsg.bind(this);  
199 -  
200 - //audioApe  
201 - //this.getAudioPlayPath = this._getPlayAudioPath.bind(this);  
202 - this.getAudioPublishPath = this._getPublishAudioPath.bind(this);  
203 - this.getAudioAllChannelInfo = this._getAudioAllChannelInfo.bind(this);  
204 - this.publishAudio = this._publishAudio.bind(this);  
205 - this.stopPublishAudio = this.unPublishAudio = this._stopPublishAudio.bind(this);  
206 - this.sendAudioBroadcastMsg = this.sendAudioCommandMsg.bind(this);  
207 -  
208 - //whiteBoradApe  
209 - this.sendInsertAnnotaion = this._sendInsertAnnotaion.bind(this); //添加标注  
210 - this.sendDeleteAllAnnotation = this._sendDeleteAllAnnotation.bind(this); //删除所有标注  
211 - this.sendDeleteCurPageAnnotation = this._sendDeleteCurPageAnnotation.bind(this); //删除当前页的所有标注  
212 - this.sendGotoPrev = this._sendGotoPrev.bind(this); //当前页撤销上一步  
213 -  
214 - // CursorApe  
215 - this.sendInsertCursor = this._sendInsertCursor.bind(this); //添加鼠标同步  
216 -  
217 - //DocApe  
218 - this.sendDocumentUpload = this._sendDocumentUpload.bind(this); //上传文档  
219 - this.sendDocumentSwitchDoc = this._sendDocumentSwitchDoc.bind(this); //切换文档  
220 - this.sendDocumentSwitchPage = this._sendDocumentSwitchPage.bind(this); //翻页  
221 - this.sendDocumentSwitchAnimation = this._sendDocumentSwitchAnimation.bind(this); //切换当前页码的动画步骤  
222 - this.sendDocumentDelete = this._sassDeleteDocument.bind(this);  
223 - this.sendDocBroadcastMsg = this._sendDocBroadcastMsg.bind(this);  
224 - //删除文档,先通过Sass删除,sass删除成功之后再同步mcu  
225 - //this.sendDocumentDeleteAll= this._documentDeleteAll;//删除所有文档  
226 - this.sendDocumentCommand = this._sendDocumentCommand.bind(this);  
227 - //操作文档(翻页、缩放、滚动...)  
228 - this.getDocImageFullPath = this._getDocImageFullPath.bind(this);  
229 - //获取文档图片的完整路径  
230 - this.getDocPDFFullPath = this._getDocPDFFullPath.bind(this); //获取文档的完整路径  
231 - this.getDocFullAddress = this._getDocFullAddress.bind(this); //获取文档资源地址  
232 -  
233 - //媒体共享模块  
234 - this.mediaSharedUpload = this._sendMediaSharedUpload.bind(this); //上传  
235 - this.mediaSharedDelete = this._sassDeletMediaShare.bind(this); //删除,先通过Sass删除,删除成功之后才删除MCU的  
236 -  
237 - this.mediaSharedPlay = this._sendMediaSharedPlay.bind(this); //播放  
238 - this.mediaSharedStop = this._sendMediaSharedStop.bind(this); //停止  
239 - this.mediaSharedUpdate = this._sendMediaSharedUpdate.bind(this); //更新媒体的状态  
240 -  
241 - //音频共享模块  
242 - this.musicSharedUpload = this._sendMusicSharedUpload.bind(this); //上传  
243 - this.musicSharedDelete = this._sassDeletMusicShare.bind(this); //删除,先通过Sass删除,删除成功之后才删除MCU的  
244 -  
245 - this.musicSharedPlay = this._sendMusicSharedPlay.bind(this); //Music播放  
246 - this.musicSharedStop = this._sendMusicSharedStop.bind(this); //Music停止  
247 - this.musicSharedUpdate = this._sendMusicSharedUpdate.bind(this); //Music更新媒体的状态  
248 -  
249 - //答题卡  
250 - this.creatQuestion = this._creatQuestion.bind(this);  
251 - this.getQuestion = this._getQuestion.bind(this);  
252 - this.getQuestionResult = this._getQuestionResult.bind(this);  
253 - this.sendAnswer = this._sendAnswer.bind(this);  
254 - this.stopQuestion = this._stopQuestion.bind(this);  
255 -  
256 - this.setDeviceInfo = this._setDeviceInfo.bind(this); //设置设备信息(麦克风,摄像头等等.....)  
257 - this.setMessageDelay = this._setMessageDelay.bind(this); //设置是否延迟消息  
258 - this.switchServer = this._switchMcuIpHandler.bind(this); //切换mcu服务器  
259 - this.switchMediaServer = this._switchMediaServer.bind(this); //手动切换ms服务器  
260 - this.setDebugInfo = this._setDebugInfo.bind(this); //设置debug信息  
261 - }  
262 -  
263 - _setDebugInfo(_data) {  
264 - loger.log("设置debug信息-->", _data);  
265 - if (_data) {  
266 - Loger.setLogDebug(_data.isDebug);  
267 - }  
268 - }  
269 -  
270 - //设置设备信息  
271 - _setDeviceInfo(_data) {  
272 - loger.log("设置设备信息-->", _data);  
273 - if (_data) {  
274 - GlobalConfig.cameras = _data.cameras || [];  
275 - GlobalConfig.microphones = _data.microphones || [];  
276 - GlobalConfig.videoQuality = parseInt(_data.videoQuality);  
277 - GlobalConfig.curVideoQuality = parseInt(_data.curVideoQuality);  
278 - GlobalConfig.micGain = _data.micGain || 50;  
279 - GlobalConfig.speakerVolume = _data.speakerVolume || 50;  
280 - GlobalConfig.micCode = _data.micCode || 0;  
281 - GlobalConfig.curCamera = _data.curCamera || '';  
282 - GlobalConfig.curMicrophone = _data.curMicrophone || '';  
283 -  
284 - if (!GlobalConfig.curCamera && GlobalConfig.cameras.length > 0) {  
285 - GlobalConfig.curCamera = GlobalConfig.cameras[0];  
286 - }  
287 - if (!GlobalConfig.curMicrophone && GlobalConfig.microphones.length > 0) {  
288 - GlobalConfig.curMicrophone = GlobalConfig.microphones[0];  
289 - }  
290 - this._updateDeviceInfo();  
291 - }  
292 - }  
293 -  
294 - //设置消息延迟  
295 - _setMessageDelay(_data) {  
296 - loger.warn("延迟消息-->", _data);  
297 - if (_data) {  
298 - GlobalConfig.messageDelay = _data.messageDelay || false;  
299 - }  
300 - }  
301 -  
302 - //mcu异常监听  
303 - _mcuErrorHandler(_data, _option) {  
304 - let option = _option || "";  
305 - let errorMessage = {"code": _data, "reson": MessageTypes.ErrorReson[_data] + " " + option};  
306 - this._emit(MessageTypes.ERROR_EVENT, errorMessage);  
307 - loger.error("MCU_ERROR", errorMessage);  
308 - }  
309 -  
310 - //获取当前的状态  
311 - _getMcuClientStatus() {  
312 - return GlobalConfig.getCurrentStatus();  
313 - }  
314 -  
315 - //获取课堂信息  
316 - _getClassDetail() {  
317 - return GlobalConfig.getClassDetail();  
318 - }  
319 -  
320 - //获取当前课堂的状态信息  
321 - _getClassStatusInfo() {  
322 - return GlobalConfig.classStatusInfo;  
323 - }  
324 -  
325 - //执行离开课堂断开连接的流程  
326 - _runClassExit(_type) {  
327 - this._leaveClass(_type);  
328 - }  
329 -  
330 - //当前的课堂状态信息发生改变,需要保存课堂状态到Sass  
331 - _onClassStatusInfoChange(_param) {  
332 - //如果MCU连接已经断开,不发送  
333 - if (GlobalConfig.getCurrentStatus().code != GlobalConfig.statusCode_2.code) {  
334 - loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());  
335 - return;  
336 - }  
337 - this._sassSaveClassStatusInfo(_param);  
338 - }  
339 -  
340 - //如果是第一次点击开始上课,需要创建录制时的文件名  
341 - _onClassRecordStart(_param) {  
342 - if (GlobalConfig.getCurrentStatus().code != GlobalConfig.statusCode_2.code) {  
343 - loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());  
344 - return;  
345 - }  
346 - if (_sass) {  
347 - _sass.saveClassRecordContrlInfo(_param);  
348 - }  
349 - }  
350 -  
351 - //开启录制成功  
352 - _onClassRecordSuccess(_param) {  
353 - clearTimeout(this.classRecordStatusUpdateTimer);  
354 - let _this = this;  
355 - this.classRecordStatusUpdateTimer = setTimeout(function () {  
356 - clearTimeout(this.classRecordStatusUpdateTimer);  
357 - _this.updaterRecordAllApeStatus(_param);  
358 - }, 2000);  
359 -  
360 - }  
361 -  
362 - //录制状态发送改变,更新所有模块的当前数据发送到MCU  
363 - updaterRecordAllApeStatus(_param) {  
364 - //老师身份和非录制回放的时候执行,录制状态发送改变,需要更新当前的数据,否则已有的消息会录制不上  
365 - if (GlobalConfig.isHost && !GlobalConfig.isRecordPlayBack) {  
366 - loger.warn('录制状态发送改变->更新所有模块的当前数据发送到MCU');  
367 - //目前录制的模块[文档模块、白板模块、视频模块(包含屏幕共享)、音频模块、媒体共享,聊天模块]  
368 - if (_doc_ape) {  
369 - _doc_ape.updaterRecordApeStatus();  
370 - }  
371 - if (_whiteboard_ape) {  
372 - _whiteboard_ape.updaterRecordApeStatus();  
373 - }  
374 - if (_video_ape) {  
375 - _video_ape.updaterRecordApeStatus();  
376 - }  
377 - if (_audio_ape) {  
378 - _audio_ape.updaterRecordApeStatus();  
379 - }  
380 - if (_mediaShareApe) {  
381 - _mediaShareApe.updaterRecordApeStatus();  
382 - }  
383 - //聊天模块不需要更新  
384 - }  
385 - }  
386 -  
387 - //有人员离开  
388 - _onClassDeleteRoster(_data) {  
389 -  
390 - }  
391 -  
392 - //当前课堂中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel  
393 - //的占用状态导致,对于这种情况,需要释放掉  
394 - _onClassNonentityRoster(_param) {  
395 - if (GlobalConfig.isRecordPlayBack) {  
396 - loger.warn("录制回放中,不处理")  
397 - return;  
398 - }  
399 -  
400 - if (_param == null || _param.nodeId == null) {  
401 - loger.warn("onClassNonentityRoster.参数错误")  
402 - return;  
403 - }  
404 - let data = {"nodeId": _param.nodeId};  
405 - if (_video_ape) {  
406 - _video_ape.stopPublishVideo(data);  
407 -  
408 - //停止屏幕共享  
409 - if (GlobalConfig.nodeId == data.nodeId) {  
410 - _video_ape.stopPublishScreenShare(data);  
411 - }  
412 - }  
413 - if (_audio_ape) {  
414 - _audio_ape.stopPublishAudio(data);  
415 - }  
416 - }  
417 -  
418 - //Sass  
419 - //初始化  
420 - _init(_param) {  
421 - //{"classId":"1653304953","portal":"112.126.80.182:80","userRole":"normal","userId":0,isH5:false}  
422 - //判断传入的参数是否存在  
423 - if (_param == null || EngineUtils.isEmptyObject(_param)) {  
424 - loger.error('初始化课堂失败->参数错误', _param);  
425 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);  
426 - return;  
427 - }  
428 - //判断必要的参数字段值  
429 - if (_param.classId == null || isNaN(_param.classId) || _param.portal == null || _param.portal == "") {  
430 - loger.error('初始化课堂失败->参数错误', _param);  
431 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_INIT_PARAM);  
432 - return;  
433 - }  
434 - loger.log('初始化课堂->', _param);  
435 -  
436 - //保存参数  
437 - GlobalConfig.isRecordPlayBack = false; //设置为非录制回放状态  
438 - GlobalConfig.classId = parseInt(_param.classId);  
439 - GlobalConfig.portal = _param.portal;  
440 -  
441 - //H5处理  
442 - GlobalConfig.isH5 = _param.isH5 || false;//外部传入的参数,是否是H5  
443 - if (GlobalConfig.isH5 == true) {  
444 - GlobalConfig.platform = "H5";  
445 - GlobalConfig.deviceType = 3//3是H5  
446 - loger.warn("设备类型是H5");  
447 - }  
448 -  
449 - //IOS 安卓处理,需要外部传入摄像头和麦克风信息  
450 - if (GlobalConfig.isMobile) {  
451 - GlobalConfig.cameras = _param.cameras || [];  
452 - GlobalConfig.microphones = _param.microphones || [];  
453 - }  
454 -  
455 - //如果没有名字,随机起一个名字  
456 - GlobalConfig.userName = _param.userName || "user_" + (new Date().getTime() % 1000000);  
457 -  
458 - //如果没有userId或者为"0",随机生成  
459 - if (!GlobalConfig.userId || GlobalConfig.userId == "0") {  
460 - GlobalConfig.userId = "user_" + (new Date().getTime() % 1000000);  
461 - }  
462 - //设置角色身份  
463 - GlobalConfig.userRole = _param.userRole || ApeConsts.normal;  
464 - if (GlobalConfig.userRole != ApeConsts.host &&  
465 - GlobalConfig.userRole != ApeConsts.presenter &&  
466 - GlobalConfig.userRole != ApeConsts.assistant &&  
467 - GlobalConfig.userRole != ApeConsts.record &&  
468 - GlobalConfig.userRole != ApeConsts.invisible) {  
469 - GlobalConfig.userRole = ApeConsts.normal;  
470 - }  
471 - //客户端决定是否延迟接收消息  
472 - GlobalConfig.messageDelay = _param.messageDelay || false;  
473 -  
474 - //最长允许录制的时间  
475 - if (_param.allowRecordMaxTime) {  
476 - GlobalConfig.allowRecordMaxTime = parseInt(_param.allowRecordMaxTime);  
477 - }  
478 -  
479 - //获取课堂校验信息  
480 - if (_sass) {  
481 - _sass.getJoinParams(GlobalConfig.getClassInfo());  
482 - }  
483 - }  
484 -  
485 - //外部请求加入课堂  
486 - _joinClass(_param) {  
487 - if (_param == null || EngineUtils.isEmptyObject(_param)) {  
488 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);  
489 - loger.log('加入课堂失败->参数错误.', _param);  
490 - return;  
491 - }  
492 - //判断userName  
493 - if (_param.userName == null || _param.userName == "") {  
494 - loger.log('加入课堂失败->参数错误->名字不能为空');  
495 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_CLASS_JOIN_PARAM);  
496 - return;  
497 - }  
498 - //{"userName":"名字","password":"","autoLogin":""}  
499 - GlobalConfig.userName = _param.userName || GlobalConfig.userName; //以登陆时的名字为主,登陆之前可以修改名字  
500 - GlobalConfig.autoLogin = _param.autoLogin || "";  
501 - GlobalConfig.password = _param.password || "";  
502 - GlobalConfig.hasCamera = (typeof _param.hasCamera == "boolean") ? _param.hasCamera : false;  
503 - GlobalConfig.hasMicrophone = (typeof _param.hasMicrophone == "boolean") ? _param.hasMicrophone : false;  
504 -  
505 - //loger.log("autoLoginMd5", GlobalConfig.classId, GlobalConfig.userId, GlobalConfig.userRole);  
506 - let autoLoginMd5 = MD5("" + GlobalConfig.classId + GlobalConfig.userId + GlobalConfig.userRole);  
507 - //loger.log("joinClass-GlobalConfig.autoLogin", GlobalConfig.autoLogin, "autoLoginMd5-", autoLoginMd5);  
508 - if (GlobalConfig.autoLogin && autoLoginMd5 == GlobalConfig.autoLogin) {  
509 - // MD5(classId+userId+userRole)==m  
510 - //自动登录,跳过验证流程  
511 - loger.log("自动登录");  
512 - this._sassJoinSuccessHandler();  
513 - } else {  
514 - //不能自动登录,开始校验  
515 - if (_sass) {  
516 - _sass.passwordAndMd5Checking(GlobalConfig.getClassInfo());  
517 - }  
518 - }  
519 - }  
520 -  
521 - // 用classId向SASS平台获取入会验证信息成功  
522 - _sassInitSuccessHandler(_data) {  
523 - //{"siteId":"h5test","passwordRequired":true,"md5":"de399d5540b3da2fbc1eb0a770d4fd66","code":0,"msType":1}  
524 - //储存数据  
525 - GlobalConfig.md5 = _data.md5 || ""; //这个暂时用假数据,后台接口写完就有数据了  
526 - GlobalConfig.msType = _data.msType || 1;  
527 - GlobalConfig.siteId = _data.siteId || "";  
528 - GlobalConfig.classType = _data.meetingType || ApeConsts.CLASS_TYPE_1;  
529 -  
530 - //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的  
531 - GlobalConfig.passwordRequired = _data.passwordRequired || false; //md5验证的时候需要Sass返回的值,不能更改  
532 - loger.log('初始化课堂验证完成.');  
533 -  
534 - //设置当前的课堂状态  
535 - GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_1);  
536 - //返回给客户端初始化成功的数据  
537 - let initSuccessCallBackData = {};  
538 - initSuccessCallBackData.siteId = GlobalConfig.siteId;  
539 - initSuccessCallBackData.classId = GlobalConfig.classId;  
540 - initSuccessCallBackData.userRole = GlobalConfig.userRole;  
541 - initSuccessCallBackData.userId = GlobalConfig.userId;  
542 - initSuccessCallBackData.userName = GlobalConfig.userName;  
543 - initSuccessCallBackData.classType = GlobalConfig.classType;  
544 -  
545 - //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的  
546 - if (GlobalConfig.userRole == ApeConsts.host) {  
547 - initSuccessCallBackData.passwordRequired = true;  
548 - } else {  
549 - initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;  
550 - }  
551 -  
552 - this._emit(MessageTypes.CLASS_INIT_SUCCESS, initSuccessCallBackData);  
553 - }  
554 -  
555 - // 通过SASS平台验证(密码和MD5)  
556 - _sassJoinSuccessHandler(_data) {  
557 - //获取课堂最完整的数据  
558 - if (_sass) {  
559 - _sass.getClassParam();  
560 - }  
561 - }  
562 -  
563 - //加载本地Server.json文件,UserIp获取ip信息,选点  
564 - loadServerJsonAndgetUserIpInfo() {  
565 - let _this = this;  
566 - if (_ipManager) {  
567 - //先加载本地Server.json文件,然后获取userIp新  
568 - _ipManager.loadServerJosn(function (_data) {  
569 - _ipManager.getUserIpInfo("", GlobalConfig.userIp, _this._getUserIpCallbackHandler.bind(_this), 2000);  
570 - })  
571 - }  
572 - }  
573 -  
574 - //本地JOSN加载完成-获取IP信息完成  
575 - _getUserIpCallbackHandler(_data) {  
576 - //获取IP信息,返回一次就不再处理  
577 - if (this.isGetUserIpCallback) {  
578 - return;  
579 - }  
580 - this.isGetUserIpCallback = true;  
581 - if (_data && _data.ret == "ok") {  
582 - GlobalConfig.country = _data.country; //国家  
583 - GlobalConfig.city = _data.city; //城市  
584 - GlobalConfig.province = _data.province; //服务商  
585 - GlobalConfig.isp = _data.isp; //服务商  
586 - }  
587 -  
588 - //根据用户的userIp信息从sever.json和Sass中选择最终mcu和推流拉流数据列表  
589 - this._choiceMcuAndMsListFromServerAndSass();  
590 - //获取MCU和MS 推流拉流、录制回放的默认地址  
591 - this.getMcuAndMsDefaultServerIp();  
592 -  
593 - loger.warn("加入课堂之前->开始测速->选择默认服务");  
594 - //加入课堂之前开始第一次选点  
595 - let _this = this;  
596 -  
597 -  
598 - //推流地址测速  
599 - this._getFastestIpFromServer(GlobalConfig.msListFinal,  
600 - function (_data) {  
601 - loger.log("推流地址测速->", _data);  
602 - if (_data && _data.ip) {  
603 - GlobalConfig.MS_PUBLISH_IP = _data.ip || "";  
604 - GlobalConfig.MS_PUBLISH_PORT = _data.port || "";  
605 - }  
606 - _this.isGetFastestMsCallback = true;  
607 - _this._startConnectMCU();  
608 - });  
609 -  
610 - //录制回放HLS拉流地址测速  
611 - this._getFastestIpFromServer(GlobalConfig.rsPullListFinal, function (_data) {  
612 - loger.log("录制回放HLS拉流地址测速->", _data);  
613 - if (_data && _data.ip) {  
614 - GlobalConfig.RS_RECORD_PLAY_IP = _data.ip || "";  
615 - GlobalConfig.RS_RECORD_PLAY_PORT = _data.port || "";  
616 - }  
617 - _this.isGetFastestRsCallback = true;  
618 - _this._startConnectMCU();  
619 - });  
620 -  
621 - //HLS和RTMP不参与测速  
622 -/*  
623 -  
624 - //RTMP拉流地址测速  
625 - this._getFastestIpFromServer(GlobalConfig.rtmpPullListFinal, function (_data) {  
626 - loger.log("RTMP拉流地址测速->", _data);  
627 - if (_data && _data.ip) {  
628 - GlobalConfig.MS_PLAY_RTMP_IP = _data.ip || "";  
629 - GlobalConfig.MS_PLAY_RTMP_PORT = _data.port || "";  
630 - }  
631 - _this.isGetFastestRtmpPullCallback = true;  
632 - _this._startConnectMCU();  
633 - });  
634 -  
635 - //HLS拉流地址测速  
636 - this._getFastestIpFromServer(GlobalConfig.hlsListFinal, function (_data) {  
637 - loger.log("HLS拉流地址测速->", _data);  
638 - if (_data && _data.ip) {  
639 - GlobalConfig.MS_PLAY_HLS_IP = _data.ip || "";  
640 - GlobalConfig.MS_PLAY_HLS_PORT = _data.port || "";  
641 - }  
642 - _this.isGetFastestHlsPullCallback = true;  
643 - _this._startConnectMCU();  
644 - });  
645 -*/  
646 -  
647 - //MCU测速  
648 - this._getFastestMcuServer(function (_data) {  
649 - loger.log("MCU测速->", _data);  
650 - if (_data && _data.ip) {  
651 - GlobalConfig.MCUServerIP = _data.ip || "";  
652 - GlobalConfig.MCUServerPort = _data.port || "";  
653 - }  
654 - _this.isGetFastestMcuCallback = true;  
655 - _this._startConnectMCU();  
656 - });  
657 - }  
658 -  
659 -  
660 - /* //本地JOSN加载完成-获取IP信息完成  
661 - _getUserIpCallbackHandler(_data) {  
662 - //获取IP信息,返回一次就不再处理  
663 - if (this.isGetUserIpCallback) {  
664 - return;  
665 - }  
666 - this.isGetUserIpCallback = true;  
667 - if (_data && _data.ret == "ok") {  
668 - GlobalConfig.country = _data.country; //国家  
669 - GlobalConfig.city = _data.city; //城市  
670 - GlobalConfig.province = _data.province; //服务商  
671 - GlobalConfig.isp = _data.isp; //服务商  
672 - }  
673 -  
674 - //合并MCU 、MS的列表  
675 - this._choiceMcuAndMsList();  
676 -  
677 - //开始选点  
678 - let _this = this;  
679 -  
680 - //有一些站点不需要进行MS选点,需要先检查一下  
681 - if (GlobalConfig.siteId_letv == GlobalConfig.siteId) {  
682 - //MS不需要选点  
683 - loger.log("MS不需要选点->siteId->", GlobalConfig.siteId);  
684 - _this.isGetFastestMcuCallback = true;  
685 - _this._startConnectMCU();  
686 - } else {  
687 - this._getFastestMsServer(function (_data) {  
688 - loger.log("MS选点结束->", _data);  
689 - if (_data && _data.ip) {  
690 - GlobalConfig.MS_PUBLISH_IP = _data.ip || "";  
691 - GlobalConfig.MS_PUBLISH_PORT = _data.port || "";  
692 - }  
693 - loger.log("当前使用的MS->", GlobalConfig.MS_PUBLISH_IP, GlobalConfig.MS_PUBLISH_PORT);  
694 - _this.isGetFastestMcuCallback = true;  
695 - _this._startConnectMCU();  
696 - });  
697 - }  
698 -  
699 - this._getFastestMcuServer(function (_data) {  
700 - loger.log("MCU选点结束->", _data);  
701 - if (_data && _data.ip) {  
702 - GlobalConfig.MCUServerIP = _data.ip || "";  
703 - GlobalConfig.MCUServerPort = _data.port || "";  
704 - }  
705 - loger.log("当前使用的MCU->", GlobalConfig.MCUServerIP, GlobalConfig.MCUServerPort);  
706 - _this.isGetFastestMsCallback = true;  
707 - _this._startConnectMCU();  
708 - });  
709 - }*/  
710 -  
711 - //开始连接MCU(所有服务地址测试完成之后开始连接)  
712 - _startConnectMCU() {  
713 - if (this.isGetFastestMcuCallback &&  
714 - this.isGetFastestMsCallback &&  
715 - this.isGetFastestRtmpPullCallback &&  
716 - this.isGetFastestHlsPullCallback &&  
717 - this.isGetFastestRsCallback) {  
718 - //mcu完成  
719 - //ms推流测速完成  
720 - //rtmp拉流测速完成  
721 - //hls拉流测速完成  
722 - //hls录制回放拉流测速完成  
723 - this._joinMCU();  
724 - }  
725 - }  
726 -  
727 - //从Sever和Sass中选择的mcu、ms列表,如果server.json中存在就不使用Sass  
728 - _choiceMcuAndMsListFromServerAndSass() {  
729 - //1.根据user信息获取服务器列表  
730 - if (_ipManager) {  
731 - GlobalConfig.mcuListFromServer = _ipManager.getServerListForUserInfo(  
732 - "MCU",  
733 - GlobalConfig.country,  
734 - GlobalConfig.province,  
735 - GlobalConfig.city,  
736 - GlobalConfig.isp,  
737 - Server.serverList);  
738 -  
739 - GlobalConfig.msListFromServer = _ipManager.getServerListForUserInfo(  
740 - "MS",  
741 - GlobalConfig.country,  
742 - GlobalConfig.province,  
743 - GlobalConfig.city,  
744 - GlobalConfig.isp,  
745 - Server.serverList);  
746 -  
747 - GlobalConfig.rtmpPullListFromServer = _ipManager.getServerListForUserInfo(  
748 - "RTMP_PULL",  
749 - GlobalConfig.country,  
750 - GlobalConfig.province,  
751 - GlobalConfig.city,  
752 - GlobalConfig.isp,  
753 - Server.serverList);  
754 -  
755 - GlobalConfig.rsPullListFromServer = _ipManager.getServerListForUserInfo(  
756 - "RS_PULL",  
757 - GlobalConfig.country,  
758 - GlobalConfig.province,  
759 - GlobalConfig.city,  
760 - GlobalConfig.isp,  
761 - Server.serverList);  
762 -  
763 - GlobalConfig.hlsPullListFromServer = _ipManager.getServerListForUserInfo(  
764 - "HLS_PULL",  
765 - GlobalConfig.country,  
766 - GlobalConfig.province,  
767 - GlobalConfig.city,  
768 - GlobalConfig.isp,  
769 - Server.serverList);  
770 - }  
771 -  
772 - loger.warn("Server中获取的服务器信息;")  
773 - loger.warn(" GlobalConfig.mcuListFromServer", GlobalConfig.mcuListFromServer);  
774 - loger.warn(" GlobalConfig.msListFromServer", GlobalConfig.msListFromServer);  
775 - loger.warn(" GlobalConfig.rtmpPullListFromServer", GlobalConfig.rtmpPullListFromServer);  
776 - loger.warn(" GlobalConfig.hlsPullListFromServer", GlobalConfig.hlsPullListFromServer);  
777 - loger.warn(" GlobalConfig.rsPullListFromServer", GlobalConfig.rsPullListFromServer);  
778 -  
779 -  
780 - //********选择最终使用的MCU、MS 和拉流列表********  
781 - //****优先使用server.json中的数据,如果没有再使用Sass中的数据****  
782 -  
783 - //MCU  
784 - GlobalConfig.mcuListFinal = [];  
785 - if (GlobalConfig.mcuListFromServer.length > 0) {  
786 - //使用server中的MCU数据  
787 - GlobalConfig.mcuListFinal = GlobalConfig.mcuListFromServer;  
788 - } else {  
789 - //使用Sass中的数据  
790 - GlobalConfig.mcuListFinal = GlobalConfig.mcuList;  
791 - }  
792 -  
793 - //MS推流  
794 - GlobalConfig.msListFinal = []  
795 - if (GlobalConfig.msListFromServer.length > 0) {  
796 - GlobalConfig.msListFinal = GlobalConfig.msListFromServer;  
797 - } else {  
798 - GlobalConfig.msListFinal = GlobalConfig.msList;  
799 - }  
800 -  
801 - //RS录制回放HLS拉流  
802 - GlobalConfig.rsPullListFinal = []  
803 - if (GlobalConfig.msListFromServer.length > 0) {  
804 - GlobalConfig.rsPullListFinal = GlobalConfig.rsPullListFromServer;  
805 - } else {  
806 - GlobalConfig.rsPullListFinal = GlobalConfig.rsList;  
807 - }  
808 -  
809 - //RTMP拉流  
810 - GlobalConfig.rtmpPullListFinal = [];  
811 - if (GlobalConfig.rtmpPullListFromServer.length > 0) {  
812 - GlobalConfig.rtmpPullListFinal = GlobalConfig.rtmpPullListFromServer;  
813 - } else {  
814 - GlobalConfig.rtmpPullListFinal = GlobalConfig.rtmpPullList;  
815 - }  
816 -  
817 - //HLS拉流流  
818 - GlobalConfig.hlsPullListFinal = [];  
819 - if (GlobalConfig.hlsPullListFromServer.length > 0) {  
820 - GlobalConfig.hlsPullListFinal = GlobalConfig.hlsPullListFromServer;  
821 - } else {  
822 - GlobalConfig.hlsPullListFinal = GlobalConfig.hlsPullList;  
823 - }  
824 -  
825 - //拉流地址列表的特殊处理,  
826 - // 1.如果RTMP拉流地址没有配置,就默认使用MS推流地址列表  
827 - if (!GlobalConfig.rtmpPullListFinal || GlobalConfig.rtmpPullListFinal.length < 1) {  
828 - GlobalConfig.rtmpPullListFinal = GlobalConfig.msListFinal;  
829 - }  
830 - // 2.如果HLS拉流地址没有配置,就默认使用录制回放RS拉流地址列表中的数据  
831 - if (!GlobalConfig.hlsPullListFinal || GlobalConfig.hlsPullListFinal.length < 1) {  
832 - GlobalConfig.hlsPullListFinal = GlobalConfig.rsPullListFinal;  
833 - ;  
834 - }  
835 -  
836 - loger.warn("课堂最终使用的服务列表->");  
837 - loger.warn(" GlobalConfig.mcuListFinal", GlobalConfig.mcuListFinal);  
838 - loger.warn(" GlobalConfig.msListFinal", GlobalConfig.msListFinal);  
839 - loger.warn(" GlobalConfig.rtmpPullListFinal", GlobalConfig.rtmpPullListFinal);  
840 - loger.warn(" GlobalConfig.hlsListFinal", GlobalConfig.hlsPullListFinal);  
841 - loger.warn(" GlobalConfig.rsListFinal", GlobalConfig.rsPullListFinal);  
842 -  
843 - }  
844 -  
845 - //开始测速  
846 - _getFastestIpFromServer(_dataArr, _callback) {  
847 - if (_ipManager) {  
848 - _ipManager.testFastestIpFromServer(_dataArr, _callback);  
849 - } else {  
850 - if (_callback) {  
851 - _callback({'ip': ""});  
852 - }  
853 - }  
854 - }  
855 -  
856 - //开始MCU选点操作  
857 - _getFastestMcuServer(_callback) {  
858 - if (_ipManager) {  
859 - _ipManager.getFastestMcuServer(GlobalConfig.mcuListFinal, _callback);  
860 - } else {  
861 - if (_callback) {  
862 - _callback({'ip': ""});  
863 - }  
864 - }  
865 - }  
866 -  
867 - //开始MS选点操作  
868 - _getFastestMsServer(_callback) {  
869 - if (_ipManager) {  
870 - _ipManager.getFastestMsServer(GlobalConfig.msListFinal, _callback);  
871 - } else {  
872 - if (_callback) {  
873 - _callback({ip: ""});  
874 - }  
875 - }  
876 - }  
877 -  
878 - //开始MS-PULL选点操作  
879 - _getFastestRtmpPullServer(_callback) {  
880 - if (_ipManager) {  
881 - _ipManager.getFastestMsServer(GlobalConfig.rtmpPullListFinal, _callback);  
882 - } else {  
883 - if (_callback) {  
884 - _callback({ip: ""});  
885 - }  
886 - }  
887 - }  
888 -  
889 - //开始MS-HLS选点操作  
890 - _getFastestHlsServer(_callback) {  
891 - if (_ipManager) {  
892 - _ipManager.getFastestMsServer(GlobalConfig.rtmpPullListFinal, _callback);  
893 - } else {  
894 - if (_callback) {  
895 - _callback({ip: ""});  
896 - }  
897 - }  
898 - }  
899 -  
900 - //保存课堂状态信息  
901 - _sassSaveClassStatusInfo(_param) {  
902 - //{isForce:true} isForce->是否强制提交(true为是)  
903 - //这个是特殊权限  
904 - let isForce = false;  
905 - if (_param && _param.isForce == true) {  
906 - isForce = true;  
907 - }  
908 -  
909 - if (GlobalConfig.isHost || isForce) {  
910 - //只有加入课堂之后才能保存数据  
911 - if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) {  
912 - //POST 保存数据  
913 - _sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo}); //保存课堂状态信息  
914 - } else {  
915 - loger.error("不能保存课堂数据", GlobalConfig.getCurrentStatus());  
916 - }  
917 - } else {  
918 - loger.log("没有保存课堂状态信息的权限->身份", GlobalConfig.userRole);  
919 - }  
920 - }  
921 -  
922 - //保存会态信息成功  
923 - _sassSaveClassStatusInfoSuccessHandler(_data) {  
924 - loger.log('保存课堂状态信息成功.');  
925 - loger.log(_data);  
926 - }  
927 -  
928 - _sassSaveClassRecordInfoSuccessHandler(_data) {  
929 - loger.log('保存课堂录制信息成功.');  
930 - loger.log(_data);  
931 - }  
932 -  
933 - //Sass校验流程结束之后,开始加入MCU  
934 - _joinMCU() {  
935 - loger.log('加入课堂->.');  
936 - loger.warn("最终使用课堂服务信息->");  
937 - loger.warn('MCU服务器地址->mcu->', GlobalConfig.MCUServerIP, GlobalConfig.MCUServerPort);  
938 - loger.warn('推流地址->MS->', GlobalConfig.MS_PUBLISH_IP, GlobalConfig.MS_PUBLISH_PORT);  
939 - loger.warn('RTMP拉流地址->RTMP->', GlobalConfig.MS_PLAY_RTMP_IP, GlobalConfig.MS_PLAY_RTMP_PORT);  
940 - loger.warn('HLS拉流地址->HLS->', GlobalConfig.MS_PLAY_HLS_IP, GlobalConfig.MS_PLAY_HLS_PORT);  
941 - loger.warn('HLS录制回放拉流地址->HLS->', GlobalConfig.RS_RECORD_PLAY_IP, GlobalConfig.RS_RECORD_PLAY_PORT);  
942 -  
943 - if (_mcu) {  
944 - _mcu.joinMCU(GlobalConfig.getClassInfo());  
945 - }  
946 - }  
947 -  
948 - _switchMcuIp() {  
949 - loger.log('切换MCU IP->.');  
950 - if (_mcu) {  
951 - _mcu.switchMCUIp(GlobalConfig.getClassInfo());  
952 - }  
953 - }  
954 -  
955 - // MCU 课堂成功  
956 - _mcuJoinMCUClassSuccessHandler(_data) {  
957 - //loger.log('MCU 课堂成功.');  
958 - GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);  
959 - GlobalConfig.classJoinSuccess = true;  
960 -  
961 - GlobalConfig.screenWidth = window.screen.width;  
962 - GlobalConfig.screenHeight = window.screen.height;  
963 -  
964 - //返回给客户端初始化成功的数据  
965 - let joinClassSuccessCallBackData = {};  
966 -  
967 - joinClassSuccessCallBackData.isRecordPlayBack = GlobalConfig.isRecordPlayBack;  
968 -  
969 - joinClassSuccessCallBackData.DOCServerIP = GlobalConfig.DOCServerIP;  
970 - joinClassSuccessCallBackData.DOCServerPort = GlobalConfig.DOCServerPort;  
971 -  
972 - joinClassSuccessCallBackData.classStatus = GlobalConfig.classStatus;  
973 - joinClassSuccessCallBackData.classId = GlobalConfig.classId;  
974 - joinClassSuccessCallBackData.className = GlobalConfig.className;  
975 - joinClassSuccessCallBackData.h5Module = GlobalConfig.h5Module;  
976 - joinClassSuccessCallBackData.isHost = GlobalConfig.isHost;  
977 - joinClassSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;  
978 - joinClassSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;  
979 - joinClassSuccessCallBackData.maxMediaChannels = GlobalConfig.maxMediaChannels;  
980 - joinClassSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;  
981 -  
982 - joinClassSuccessCallBackData.msType = GlobalConfig.msType;  
983 - joinClassSuccessCallBackData.nodeId = GlobalConfig.nodeId;  
984 - joinClassSuccessCallBackData.password = GlobalConfig.password;  
985 - joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired; // 老师的默认是true  
986 - //GlobalConfig.passwordRequired 老师的默认是true  
987 - //GlobalConfig.portal=_data.portal;  
988 - joinClassSuccessCallBackData.role = GlobalConfig.role;  
989 - joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;  
990 - joinClassSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;  
991 - joinClassSuccessCallBackData.userId = GlobalConfig.userId;  
992 - joinClassSuccessCallBackData.userName = GlobalConfig.userName;  
993 - joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;  
994 - joinClassSuccessCallBackData.userType = GlobalConfig.userType;  
995 -  
996 - joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;  
997 - joinClassSuccessCallBackData.classId = GlobalConfig.classId;  
998 - joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;  
999 - joinClassSuccessCallBackData.userId = GlobalConfig.userId;  
1000 - joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;  
1001 - joinClassSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_1;  
1002 -  
1003 - joinClassSuccessCallBackData.country = GlobalConfig.country; //国家  
1004 - joinClassSuccessCallBackData.city = GlobalConfig.city; //城市  
1005 - joinClassSuccessCallBackData.province = GlobalConfig.province; //服务商  
1006 - joinClassSuccessCallBackData.isp = GlobalConfig.isp; //服务商  
1007 -  
1008 - joinClassSuccessCallBackData.classTimestamp = GlobalConfig.classTimestamp; //课堂进行的累积时间  
1009 - joinClassSuccessCallBackData.recordTimestamp = GlobalConfig.recordTimestamp; //课堂录制的累积时间  
1010 - joinClassSuccessCallBackData.recordPlaybackMaxTime = GlobalConfig.recordPlaybackMaxTime; //录制回放的总时间  
1011 -  
1012 - joinClassSuccessCallBackData.fps = GlobalConfig.fps;  
1013 - joinClassSuccessCallBackData.gop = GlobalConfig.gop;  
1014 - joinClassSuccessCallBackData.videoQuality = GlobalConfig.videoQuality;  
1015 -  
1016 - joinClassSuccessCallBackData.ssTunnelAppURL = GlobalConfig.ssTunnelAppURL;  
1017 - joinClassSuccessCallBackData.currentSceneTableId = GlobalConfig.currentSceneTableId; //文档区域的模块显示  
1018 - joinClassSuccessCallBackData.serverAndLoacTimeDistanc = GlobalConfig.serverAndLoacTimeDistanc;  
1019 -  
1020 - joinClassSuccessCallBackData.deviceType = GlobalConfig.deviceType;  
1021 - joinClassSuccessCallBackData.language = GlobalConfig.language;  
1022 - joinClassSuccessCallBackData.explorer = GlobalConfig.explorer;  
1023 - joinClassSuccessCallBackData.explorerVersion = GlobalConfig.explorerVersion;  
1024 - joinClassSuccessCallBackData.os = GlobalConfig.os;  
1025 -  
1026 - loger.log('加入课堂成功->');  
1027 - loger.log(joinClassSuccessCallBackData);  
1028 -  
1029 - //加入课堂成功,广播消息  
1030 - this._emit(MessageTypes.CLASS_JOIN_SUCCESS, joinClassSuccessCallBackData);  
1031 - }  
1032 -  
1033 - //切换MCU ->_param->{reConnect:false} //reConnect(是否立即替换当前的ip并且重新连接)  
1034 - _switchMcuIpHandler(_param) {  
1035 - if (GlobalConfig.isRecordPlayBack) {  
1036 - loger.log('录制回放->不进行MCU动态选点');  
1037 - return;  
1038 - }  
1039 - loger.log('MCU->动态选点');  
1040 - let _this = this;  
1041 - this._getFastestMcuServer(function (_data) {  
1042 - loger.log("MCU选点结束->", _data);  
1043 - //记录当前的IP地址,选点结束后需要判断一下是否是新的IP;  
1044 - let oldIp = GlobalConfig.MCUServerIP;  
1045 -  
1046 - if (_data && _data.ip) {  
1047 - GlobalConfig.MCUServerIP = _data.ip || "";  
1048 - GlobalConfig.MCUServerPort = _data.port || "";  
1049 - } else {  
1050 - //随机选择一个  
1051 - if (GlobalConfig.mcuList && GlobalConfig.mcuList.length > 0) {  
1052 - let index = parseInt(Math.random() * GlobalConfig.mcuList.length);  
1053 - GlobalConfig.MCUServerIP = GlobalConfig.mcuList[index].ip || "";  
1054 - GlobalConfig.MCUServerPort = GlobalConfig.mcuList[index].port || "";  
1055 - }  
1056 - }  
1057 - if (oldIp && oldIp != GlobalConfig.MCUServerIP) {  
1058 - loger.log('MCU->最新地址->', GlobalConfig.MCUServerIP, GlobalConfig.MCUServerPort);  
1059 - //判断是否需要主动断开当前的连接然后重连新的服务器  
1060 - if (_param && _param.reConnect == true) {  
1061 - loger.log('MCU->切换到最新的IP->', GlobalConfig.MCUServerIP, GlobalConfig.MCUServerPort);  
1062 - _this._startConnectMCU();  
1063 - } else {  
1064 - //不需要断开当前的连接,更改ip即可  
1065 - _this._switchMcuIp();  
1066 - }  
1067 - } else {  
1068 - //如果选点结束后获得的ip和当前的IP相同,不需要切换  
1069 - loger.log('MCU不需要切换->之前的IP->', oldIp, "新的IP->", GlobalConfig.MCUServerIP);  
1070 - }  
1071 - });  
1072 - }  
1073 -  
1074 - //课堂状态发生改变,需要停止当前的所有推流  
1075 - _stopAllMediaPublishHandler(_data) {  
1076 - loger.log('课堂状态发生改变,需要停止当前的所有推流');  
1077 - this._emit(MessageTypes.MEDIA_STOP_PUBLISH);  
1078 - }  
1079 -  
1080 - //手动切换MS -> {ip;"xxx.xx.xx","port":"xxxx"}  
1081 - _switchMediaServer(_param) {  
1082 - if (GlobalConfig.isRecordPlayBack) {  
1083 - //录制回放不做操作  
1084 - loger.warn('录制回放->不能手动切换MS');  
1085 - return;  
1086 - }  
1087 - if (_param && _param.ip) {  
1088 - GlobalConfig.MS_PUBLISH_IP = _param.ip || "";  
1089 - GlobalConfig.MS_PUBLISH_PORT = _param.port || "";  
1090 - }  
1091 - loger.warn('手动切换MS->', GlobalConfig.MS_PUBLISH_IP + ":" + GlobalConfig.MS_PUBLISH_PORT);  
1092 - //更换完用户当前的MS地址,需要更新用户数据  
1093 - if (_confer_ape) {  
1094 - _confer_ape.updateUserInfo();  
1095 - }  
1096 - }  
1097 -  
1098 - //切换MS ->_param->{reConnect:false} //reConnect(是否立即替换当前的ip并且重新连接)  
1099 - _switchMsIpHandler(_param) {  
1100 - if (GlobalConfig.isRecordPlayBack) {  
1101 - //录制回放不做操作  
1102 - loger.warn('录制回放->不进行MS动态选点');  
1103 - return;  
1104 - }  
1105 - let _this = this;  
1106 - this._getFastestMsServer(function (_data) {  
1107 - loger.log("MS选点结束->", _data);  
1108 - //记录当前的IP地址,选点结束后需要判断一下是否是新的IP;  
1109 - let oldIp = GlobalConfig.MS_PUBLISH_IP;  
1110 -  
1111 - if (_data && _data.ip) {  
1112 -  
1113 - GlobalConfig.MS_PUBLISH_IP = _data.ip || "";  
1114 - GlobalConfig.MS_PUBLISH_PORT = _data.port || "";  
1115 - } else {  
1116 - //随机选择一个  
1117 - if (GlobalConfig.msListFinal && GlobalConfig.msListFinal.length > 0) {  
1118 - let index = parseInt(Math.random() * GlobalConfig.msListFinal.length);  
1119 - GlobalConfig.MS_PUBLISH_IP = GlobalConfig.msListFinal[index].ip || "";  
1120 - GlobalConfig.MS_PUBLISH_PORT = GlobalConfig.msListFinal[index].port || "";  
1121 - }  
1122 - }  
1123 -  
1124 - if (oldIp && oldIp != GlobalConfig.MS_PUBLISH_IP) {  
1125 - //选点完成需要更新用户数据  
1126 - if (_confer_ape) {  
1127 - _confer_ape.updateUserInfo();  
1128 - }  
1129 - loger.log('MS->最新地址->', GlobalConfig.MS_PUBLISH_IP, GlobalConfig.MS_PUBLISH_PORT);  
1130 - } else {  
1131 - //如果选点结束后获得的ip和当前的IP相同,不需要切换  
1132 - loger.log('MS不需要切换->IP', GlobalConfig.MS_PUBLISH_IP);  
1133 - }  
1134 - });  
1135 - }  
1136 -  
1137 - //切换MS -PULL地址  
1138 - _switchRtmpPullIpHandler(_param) {  
1139 - if (GlobalConfig.isRecordPlayBack) {  
1140 - //录制回放不做操作  
1141 - loger.warn('录制回放->不进行MS-PULL动态选点');  
1142 - return;  
1143 - }  
1144 - if(!GlobalConfig.rtmpPullListFinal||GlobalConfig.rtmpPullListFinal.length<1){  
1145 - return;  
1146 - }  
1147 - let _this = this;  
1148 - this._getFastestRtmpPullServer(function (_data) {  
1149 - loger.log("MS->PULL->选点结束->", _data);  
1150 - if (_data && _data.ip) {  
1151 - GlobalConfig.MS_PLAY_RTMP_IP = _data.ip || "";  
1152 - GlobalConfig.MS_PLAY_RTMP_PORT = _data.port || "";  
1153 - } else {  
1154 - //随机选择一个  
1155 - if (GlobalConfig.rtmpPullListFinal && GlobalConfig.rtmpPullListFinal.length > 0) {  
1156 - let index = parseInt(Math.random() * GlobalConfig.rtmpPullListFinal.length);  
1157 - GlobalConfig.MS_PLAY_RTMP_IP = GlobalConfig.rtmpPullListFinal[index].ip || "";  
1158 - GlobalConfig.MS_PLAY_RTMP_PORT = GlobalConfig.rtmpPullListFinal[index].port || "";  
1159 - }  
1160 - }  
1161 - //如果RTMP没有配置地址,那么还是使用推流的地址  
1162 - if(!GlobalConfig.MS_PLAY_RTMP_IP){  
1163 - GlobalConfig.MS_PLAY_RTMP_IP = GlobalConfig.MS_PUBLISH_IP;  
1164 - GlobalConfig.MS_PLAY_RTMP_PORT = GlobalConfig.MS_PUBLISH_PORT;  
1165 - }  
1166 - });  
1167 - }  
1168 -  
1169 - //切换MS HLS地址  
1170 - _switchHlsIpHandler(_param) {  
1171 - if (GlobalConfig.isRecordPlayBack) {  
1172 - //录制回放不做操作  
1173 - loger.warn('录制回放->不进行MS-HLS动态选点');  
1174 - return;  
1175 - }  
1176 - if(!GlobalConfig.hlsPullListFinal||GlobalConfig.hlsPullListFinal.length<1){  
1177 - return;  
1178 - }  
1179 - let _this = this;  
1180 - this._getFastestHlsServer(function (_data) {  
1181 - loger.log("HLS选点结束->", _data);  
1182 - if (_data && _data.ip) {  
1183 - GlobalConfig.MS_PLAY_HLS_IP = _data.ip || "";  
1184 - GlobalConfig.MS_PLAY_HLS_PORT = _data.port || "";  
1185 - } else {  
1186 - //随机选择一个  
1187 - if (GlobalConfig.hlsPullListFinal && GlobalConfig.hlsPullListFinal.length > 0) {  
1188 - let index = parseInt(Math.random() * GlobalConfig.hlsPullListFinal.length);  
1189 - GlobalConfig.MS_PLAY_HLS_IP = GlobalConfig.hlsPullListFinal[index].ip || "";  
1190 - GlobalConfig.MS_PLAY_HLS_PORT = GlobalConfig.hlsPullListFinal[index].port || "";  
1191 - }  
1192 - }  
1193 - //如果HLS没有配置地址,那么还是使用推流的地址  
1194 - if(!GlobalConfig.MS_PLAY_HLS_IP){  
1195 - GlobalConfig.MS_PLAY_HLS_IP = GlobalConfig.RS_RECORD_PLAY_IP;  
1196 - GlobalConfig.MS_PLAY_HLS_PORT = GlobalConfig.RS_RECORD_PLAY_PORT;  
1197 - }  
1198 - });  
1199 - }  
1200 -  
1201 - //先通过Sass删除文档数据,删除成功之后才能删除MCU的  
1202 - _sassDeleteDocument(_param) {  
1203 - if (!_mcu.connected) {  
1204 - loger.warn(GlobalConfig.getCurrentStatus());  
1205 - return;  
1206 - }  
1207 -  
1208 - //判断传入的参数是否存在  
1209 - if (_param == null || EngineUtils.isEmptyObject(_param)) {  
1210 - loger.error('删除文档失败->参数错误', _param);  
1211 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);  
1212 - return;  
1213 - }  
1214 - //判断必要的参数字段值  
1215 - if (_param.itemIdx == null || isNaN(_param.itemIdx) || _param.docId == null || _param.docId == "") {  
1216 - loger.error('删除文档失败->', _param);  
1217 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_DOC_DELETE_FAILED_PARAM);  
1218 - return;  
1219 - }  
1220 - loger.log('删除文档->', _param);  
1221 -  
1222 - if (_sass) {  
1223 - _sass.sassDeleteDocument(_param);  
1224 - }  
1225 - }  
1226 -  
1227 - _sendDocBroadcastMsg(_param) {  
1228 - if (!_mcu.connected) {  
1229 - loger.warn(GlobalConfig.getCurrentStatus());  
1230 - return;  
1231 - }  
1232 - if (_doc_ape) {  
1233 - _doc_ape.sendDocBroadcastMsg(_param);  
1234 - }  
1235 - }  
1236 -  
1237 - //Sass删除文档成功之后,同步删除MCU数据  
1238 - _sassDeleteDocumentSuccess(_param) {  
1239 - loger.log('删除文档成功->', _param);  
1240 - this._sendDocumentDelete(_param);  
1241 - }  
1242 -  
1243 - _sassDeleteMediaShareSuccess(_param) {  
1244 - loger.log('删除媒体文件成功->', _param);  
1245 - this._sendMediaSharedDelete(_param);  
1246 - }  
1247 -  
1248 - _sassDeleteMusicShareSuccess(_param) {  
1249 - loger.log('删除Music文件成功->', _param);  
1250 - this._sendMusicSharedDelete(_param);  
1251 - }  
1252 -  
1253 - //ConferApe  
1254 - //开始上课  
1255 - _sendStartClass(_param) {  
1256 - if (!_mcu.connected) {  
1257 - loger.warn(GlobalConfig.getCurrentStatus());  
1258 - return;  
1259 - }  
1260 -  
1261 - if (_confer_ape) {  
1262 - _confer_ape.startClass(_param);  
1263 - }  
1264 - }  
1265 -  
1266 - //ConferApe  
1267 - //全局禁言  
1268 - _silenceClass(_param) {  
1269 - if (!_mcu.connected) {  
1270 - loger.warn(GlobalConfig.getCurrentStatus());  
1271 - return;  
1272 - }  
1273 -  
1274 - if (_confer_ape) {  
1275 - _confer_ape.silenceClass(_param);  
1276 - }  
1277 - }  
1278 -  
1279 - //暂停上课  
1280 - _sendPauseClass(_param) {  
1281 - if (!_mcu.connected) {  
1282 - loger.warn(GlobalConfig.getCurrentStatus());  
1283 - return;  
1284 - }  
1285 - if (_confer_ape) {  
1286 - _confer_ape.pauseClass(_param);  
1287 - }  
1288 - }  
1289 -  
1290 - //更新设备信息  
1291 - _updateDeviceInfo(_param) {  
1292 - if (!_mcu.connected) {  
1293 - loger.warn('更新设备信息->失败', GlobalConfig.getCurrentStatus());  
1294 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1295 - }  
1296 - if (!GlobalConfig.classJoinSuccess) {  
1297 - loger.warn('更新设备信息->失败->还没有加入课堂成功', GlobalConfig.getCurrentStatus());  
1298 - }  
1299 - if (_confer_ape) {  
1300 - _confer_ape.updateDeviceInfo(_param);  
1301 - }  
1302 - }  
1303 -  
1304 - //文档-媒体共享-屏幕共享模块切换  
1305 - _sceneTableChange(_param) {  
1306 - if (!_mcu.connected) {  
1307 - loger.warn(GlobalConfig.getCurrentStatus());  
1308 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1309 - }  
1310 - if (_confer_ape) {  
1311 - _confer_ape.sceneTableChange(_param);  
1312 - }  
1313 - }  
1314 -  
1315 - //通过第三方消息通道发送消息  
1316 - _sendThridChannelMessage(_param) {  
1317 - if (!_mcu.connected) {  
1318 - loger.warn(GlobalConfig.getCurrentStatus());  
1319 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1320 - }  
1321 - if (_confer_ape) {  
1322 - _confer_ape.onThirdReciveParentMessage(_param);  
1323 - }  
1324 - }  
1325 -  
1326 - //将指定nodeId的人踢出课堂  
1327 - _kickOutRosterFormNodeId(_param) {  
1328 - if (!_mcu.connected) {  
1329 - loger.warn(GlobalConfig.getCurrentStatus());  
1330 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1331 - }  
1332 - if (_confer_ape) {  
1333 - _confer_ape.kickOutRosterFormNodeId(_param);  
1334 - }  
1335 - }  
1336 -  
1337 - // 禁言控制  
1338 - _controlSilenceStatus(_param) {  
1339 - if (!_mcu.connected) {  
1340 - loger.warn(GlobalConfig.getCurrentStatus());  
1341 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1342 - }  
1343 - if (_confer_ape) {  
1344 - _confer_ape.controlSilenceStatus(_param);  
1345 - }  
1346 - }  
1347 -  
1348 - //举手状态控制  
1349 - _controlHandUpStatus(_param) {  
1350 - if (!_mcu.connected) {  
1351 - loger.warn(GlobalConfig.getCurrentStatus());  
1352 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1353 - }  
1354 - if (_confer_ape) {  
1355 - _confer_ape.controlHandUpStatus(_param);  
1356 - }  
1357 - }  
1358 -  
1359 - //举手状态切换  
1360 - _changeHandUpStatus(_param) {  
1361 - if (!_mcu.connected) {  
1362 - loger.warn(GlobalConfig.getCurrentStatus());  
1363 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1364 - }  
1365 - if (_confer_ape) {  
1366 - _confer_ape.changeHandUpStatus(_param);  
1367 - }  
1368 - }  
1369 -  
1370 - //停止上课  
1371 - _sendCloseClass(_param) {  
1372 - if (!_mcu.connected) {  
1373 - loger.warn(GlobalConfig.getCurrentStatus());  
1374 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1375 - }  
1376 - if (_confer_ape) {  
1377 - _confer_ape.closeClass(_param);  
1378 - }  
1379 - }  
1380 -  
1381 - // 离开课堂 {type:1} type=1被踢出课堂;type=0自己主动离开  
1382 - _leaveClass(_param) {  
1383 - if (!_mcu.connected) {  
1384 - loger.warn(GlobalConfig.getCurrentStatus());  
1385 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1386 - }  
1387 -  
1388 - //停止推流  
1389 - if (_video_ape) {  
1390 - _video_ape.stopPublishVideo();  
1391 - _video_ape.stopPublishScreenShare();  
1392 - }  
1393 - if (_audio_ape) {  
1394 - _audio_ape.stopPublishAudio();  
1395 - }  
1396 - //离开课堂  
1397 - if (_confer_ape) {  
1398 - _confer_ape.stopRecord();  
1399 - _confer_ape.leaveClass();  
1400 - }  
1401 -  
1402 - let callBack = {};  
1403 - if (_param && _param.type) {  
1404 - callBack = _param;  
1405 - } else {  
1406 - callBack.type = 0;  
1407 - }  
1408 - loger.warn('离开课堂->', MessageTypes.CLASS_EXIT, callBack);  
1409 - this._emit(MessageTypes.CLASS_EXIT, callBack);  
1410 -  
1411 - //断开MCU连接  
1412 - if (_mcu) {  
1413 - _mcu.leaveMCU();  
1414 - GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_3);  
1415 - }  
1416 - }  
1417 -  
1418 - //获取课堂所有参数(20170727新规则) api/meeting/detail.do? flash中的接口文件是 getClassParam.do  
1419 - _sassGetClassParamSuccessHandler(_data) {  
1420 - loger.log('获取课堂课堂信息完成.');  
1421 - //包含整个课堂最全的信息,储存数据  
1422 - if (_data) {  
1423 - GlobalConfig.mcuDelay = _data.h5Delay || 0; //mcu消息延迟的时间间隔,单位(秒),结合客户端传的messageDelay的值使用  
1424 - GlobalConfig.className = _data.meetingName || "";  
1425 - GlobalConfig.classBeginTime = _data.beginTime || "";  
1426 - GlobalConfig.classEndTime = _data.endTime || "";  
1427 - GlobalConfig.userIp = _data.userIp || "";  
1428 -  
1429 - GlobalConfig.maxVideoChannels = _data.maxVideoChannels;  
1430 - GlobalConfig.maxAudioChannels = _data.maxAudioChannels;  
1431 - GlobalConfig.maxMediaChannels = Math.max(GlobalConfig.maxVideoChannels, GlobalConfig.maxAudioChannels);  
1432 -  
1433 - GlobalConfig.ssTunnelAppURL = _data.ssTunnelAppURL || ''; //屏幕共享插件的地址  
1434 -  
1435 - //视频质量相关设置,每次加入课堂都按最新的获取设置  
1436 - GlobalConfig.fps = _data.fps || 15;  
1437 - GlobalConfig.gop = _data.gop || 3;  
1438 - GlobalConfig.videoQuality = parseInt(_data.videoQuality);  
1439 - GlobalConfig.curVideoQuality = GlobalConfig.videoQuality;  
1440 -  
1441 - //是否自动开始(身份是host的时候才用到的)  
1442 - GlobalConfig.isAutoStartClass = _data.autoRecord || 0;  
1443 -  
1444 - GlobalConfig.serverTime = _data.serverTime || new Date().getTime(); //获取服务器时间戳  
1445 - GlobalConfig.serverAndLoacTimeDistanc = (new Date().getTime() - GlobalConfig.serverTime) / 1000; //当前系统时间和服务器时间的差值 (秒)  
1446 - loger.warn("服务器时间:" + GlobalConfig.serverTime + " 系统时间:" + new Date().getTime() + " 时间差:" + GlobalConfig.serverAndLoacTimeDistanc);  
1447 -  
1448 -  
1449 - GlobalConfig.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表  
1450 - GlobalConfig.setRecordList(_data.recordList); //录制回放地址  
1451 - GlobalConfig.setDocList(_data.docList); //文档地址  
1452 - GlobalConfig.setMusicList(_data.musicList); //  
1453 - GlobalConfig.setMusicListPrepare(_data.musicListPrepare); //提前上传的声音文件列表  
1454 - GlobalConfig.setVideoCDNAddr(_data.videoCDNAddr); //cdn加速的拉流地址,直播的时候才使用  
1455 - GlobalConfig.setMediaShareList(_data.sharedMediaList); //提前上传的媒体共享文件列表  
1456 -  
1457 - //存从Sass获取的MS和MCU服务列表  
1458 - if (_data.msList2) {  
1459 - GlobalConfig.setMsList(_data.msList2.msList); //储存Sass ms拉流地址  
1460 - GlobalConfig.setRtmpPullList(_data.msList2.rtmpPullArray); //储存Sass ms拉流地址  
1461 - GlobalConfig.setHlsPullList(_data.msList2.hlsPullArray); //储存Sass ms拉流地址  
1462 - GlobalConfig.setRsList(_data.msList2.rsList); //储存Sass 录制回放hls拉流地址  
1463 - }  
1464 - //Sass mcu  
1465 - GlobalConfig.setMcuList(_data.mcuList); //mcu  
1466 -  
1467 - loger.warn('从Sass获取的推流拉流列表数据:');  
1468 - loger.warn('Sass->msList->', GlobalConfig.msList);  
1469 - loger.warn('Sass->rtmpPullList->', GlobalConfig.rtmpPullList);  
1470 - loger.warn('Sass->hlsPullList->', GlobalConfig.hlsPullList);  
1471 - loger.warn('Sass->rsList->', GlobalConfig.rsList);  
1472 -  
1473 - //没有加载server.json之前,最终的服务列表按Sass的为准,server.json加载完成后会选点  
1474 - GlobalConfig.msListFinal=GlobalConfig.msList;  
1475 - GlobalConfig.rtmpPullListFinal=GlobalConfig.rtmpPullList;  
1476 - GlobalConfig.hlsPullListFinal=GlobalConfig.hlsPullList;  
1477 - GlobalConfig.rsPullListFinal=GlobalConfig.rsList;  
1478 - GlobalConfig.mcuListFinal=GlobalConfig.mcuList;  
1479 - }  
1480 -  
1481 - //课堂获取Sass数据完成  
1482 - this._emit(MessageTypes.CLASS_GET_INFO_SUCCESS, GlobalConfig.getClassInfo());  
1483 -  
1484 - if (_data.currentInfo) {  
1485 - //根据从Sass获取的数据信息,同步最后一次保存的课堂状态信息  
1486 - try {  
1487 - GlobalConfig.setClassStatusInfo(JSON.parse(_data.currentInfo));  
1488 - } catch (err) {  
1489 - loger.warn("从Sass获取的课堂数据JSON转换失败->");  
1490 - console.log("currentInfo", _data.currentInfo);  
1491 - GlobalConfig.setClassStatusInfo(_data.currentInfo);  
1492 - }  
1493 - loger.log(GlobalConfig.classStatusInfo);  
1494 - } else {  
1495 - loger.log("还没有保存过课堂状信息");  
1496 - }  
1497 -  
1498 - //课堂数据获取完成->进入课堂或进入录制回放  
1499 - //录制回放不需要获取ip信息和选点  
1500 - if (GlobalConfig.isRecordPlayBack) {  
1501 - if (_recordPlayback) {  
1502 - //获取MCU和MS 推流拉流、录制回放的默认地址  
1503 - this.getMcuAndMsDefaultServerIp();  
1504 - //开启录制回放流程  
1505 - loger.warn("开启录制回放流程");  
1506 - _recordPlayback.readyRecordPlay();  
1507 - } else {  
1508 - loger.warn("开启录制回放流程失败->还未创建模块");  
1509 - }  
1510 - } else {  
1511 - //根据用户的userIp获取信息,获取服务列表选点,选点测速完成后才加入MCU  
1512 - this.loadServerJsonAndgetUserIpInfo();  
1513 - }  
1514 - }  
1515 -  
1516 - //获取各个服务的默认ip,之后会进行测速选择更快的ip  
1517 - getMcuAndMsDefaultServerIp() {  
1518 - //MCU地址  
1519 - if (GlobalConfig.mcuListFinal && GlobalConfig.mcuListFinal.length > 0) {  
1520 - //还未开始选点之前随机选择一个  
1521 - let index = parseInt(Math.random() * GlobalConfig.mcuListFinal.length);  
1522 - GlobalConfig.MCUServerIP = GlobalConfig.mcuListFinal[index].ip || "";  
1523 - GlobalConfig.MCUServerPort = GlobalConfig.mcuListFinal[index].port || "";  
1524 - }  
1525 -  
1526 - //录制回放时m3u8播流地址  
1527 - if (GlobalConfig.rsPullListFinal && GlobalConfig.rsPullListFinal.length > 0) {  
1528 - //还未开始选点之前随机选择一个  
1529 - let index = parseInt(Math.random() * GlobalConfig.rsPullListFinal.length);  
1530 - GlobalConfig.RS_RECORD_PLAY_IP = GlobalConfig.rsPullListFinal[index].ip || "";  
1531 - GlobalConfig.RS_RECORD_PLAY_PORT = GlobalConfig.rsPullListFinal[index].port || "";  
1532 - }  
1533 -  
1534 - //推流地址  
1535 - if (GlobalConfig.msListFinal && GlobalConfig.msListFinal.length > 0) {  
1536 - //还未开始选点之前随机选择一个  
1537 - let index = parseInt(Math.random() * GlobalConfig.msListFinal.length);  
1538 - GlobalConfig.MS_PUBLISH_IP = GlobalConfig.msListFinal[index].ip || "";  
1539 - GlobalConfig.MS_PUBLISH_PORT = GlobalConfig.msListFinal[index].port || "";  
1540 - }  
1541 -  
1542 - //RTMP拉流  
1543 - if (GlobalConfig.rtmpPullListFinal && GlobalConfig.rtmpPullListFinal.length > 0) {  
1544 - // //还未开始选点之前随机选择一个  
1545 - let index = parseInt(Math.random() * GlobalConfig.rtmpPullListFinal.length);  
1546 - GlobalConfig.MS_PLAY_RTMP_IP = GlobalConfig.rtmpPullListFinal[index].ip || "";  
1547 - GlobalConfig.MS_PLAY_RTMP_PORT = GlobalConfig.rtmpPullListFinal[index].port || "";  
1548 - } else {  
1549 - //如果没有单独的rtmp拉流地址,和推流地址一样即可  
1550 - GlobalConfig.MS_PLAY_RTMP_IP = GlobalConfig.MS_PUBLISH_IP;  
1551 - GlobalConfig.MS_PLAY_RTMP_PORT = GlobalConfig.MS_PUBLISH_PORT;  
1552 - }  
1553 -  
1554 - //课堂中HLS拉流地址  
1555 - if (GlobalConfig.hlsPullListFinal && GlobalConfig.hlsPullListFinal.length > 0) {  
1556 - //有单独的hls拉流地址  
1557 - let index = parseInt(Math.random() * GlobalConfig.hlsPullListFinal.length);  
1558 - GlobalConfig.MS_PLAY_HLS_IP = GlobalConfig.hlsPullListFinal[index].ip || "";  
1559 - GlobalConfig.MS_PLAY_HLS_PORT = GlobalConfig.hlsPullListFinal[index].port || "";  
1560 - } else {  
1561 - //没有单独的hls拉流地址,和录制回放地址一样即可  
1562 - GlobalConfig.MS_PLAY_HLS_IP = GlobalConfig.RS_RECORD_PLAY_IP;  
1563 - GlobalConfig.MS_PLAY_HLS_PORT = GlobalConfig.RS_RECORD_PLAY_PORT;  
1564 - }  
1565 -  
1566 -  
1567 - //文档服务器地址  
1568 - if (GlobalConfig.docList && GlobalConfig.docList.length > 0) {  
1569 - //doc上传地址,随机获取一个  
1570 - let index = parseInt(Math.random() * GlobalConfig.docList.length);  
1571 - GlobalConfig.DOCServerIP = GlobalConfig.docList[index].ip || "";  
1572 - GlobalConfig.DOCServerPort = GlobalConfig.docList[index].port || "";  
1573 -  
1574 - }  
1575 - //录制回放文件的下载地址  
1576 - if (GlobalConfig.recordList && GlobalConfig.recordList.length > 0) {  
1577 - let index = parseInt(Math.random() * GlobalConfig.recordList.length);  
1578 - GlobalConfig.RecordServerIP = GlobalConfig.recordList[index].ip || "";  
1579 - GlobalConfig.RecordServerPort = GlobalConfig.recordList[index].port || "";  
1580 -  
1581 - }  
1582 - loger.warn('默认->MCU地址->.', GlobalConfig.MCUServerIP, GlobalConfig.MCUServerPort);  
1583 -  
1584 - loger.warn('默认->MS推流地址->.', GlobalConfig.MS_PUBLISH_IP, GlobalConfig.MS_PUBLISH_PORT);  
1585 - loger.warn('默认->HLS点播地址->.', GlobalConfig.RS_RECORD_PLAY_IP, GlobalConfig.RS_RECORD_PLAY_PORT);  
1586 - loger.warn('默认->HLS拉流地址->.', GlobalConfig.MS_PLAY_HLS_IP, GlobalConfig.MS_PLAY_HLS_PORT);  
1587 - loger.warn('默认->RTMP拉流地址->.', GlobalConfig.MS_PLAY_RTMP_IP, GlobalConfig.MS_PLAY_RTMP_PORT);  
1588 -  
1589 - loger.warn('默认->文档服务器地址->.', GlobalConfig.DOCServerIP, GlobalConfig.DOCServerPort);  
1590 - loger.warn('默认->录制回放文件下载地址->.', GlobalConfig.RecordServerIP, GlobalConfig.RecordServerPort);  
1591 - }  
1592 -  
1593 - //获取课堂所有参数 api/meeting/detail.do? flash中的接口文件是 getClassParam.do(20170727之前的规则)  
1594 - /*_sassGetClassParamSuccessHandler(_data) {  
1595 - loger.log('获取课堂课堂信息完成.');  
1596 - //包含整个课堂最全的信息,储存数据  
1597 - if (_data) {  
1598 - GlobalConfig.mcuDelay = _data.h5Delay || 0; //mcu消息延迟的时间间隔,单位(秒),结合客户端传的messageDelay的值使用  
1599 - GlobalConfig.className = _data.meetingName || "";  
1600 - GlobalConfig.classBeginTime = _data.beginTime || "";  
1601 - GlobalConfig.classEndTime = _data.endTime || "";  
1602 - GlobalConfig.userIp = _data.userIp || "";  
1603 -  
1604 - GlobalConfig.maxVideoChannels = _data.maxVideoChannels;  
1605 - GlobalConfig.maxAudioChannels = _data.maxAudioChannels;  
1606 - GlobalConfig.maxMediaChannels = Math.max(GlobalConfig.maxVideoChannels, GlobalConfig.maxAudioChannels);  
1607 -  
1608 - GlobalConfig.ssTunnelAppURL = _data.ssTunnelAppURL || ''; //屏幕共享插件的地址  
1609 -  
1610 - //视频质量相关设置,每次加入课堂都按最新的获取设置  
1611 - GlobalConfig.fps = _data.fps || 15;  
1612 - GlobalConfig.gop = _data.gop || 3;  
1613 - GlobalConfig.videoQuality = parseInt(_data.videoQuality);  
1614 - GlobalConfig.curVideoQuality = GlobalConfig.videoQuality;  
1615 -  
1616 - //是否自动开始(身份是host的时候才用到的)  
1617 - GlobalConfig.isAutoStartClass = _data.autoRecord || 0;  
1618 -  
1619 - GlobalConfig.serverTime = _data.serverTime || new Date().getTime(); //获取服务器时间戳  
1620 - GlobalConfig.serverAndLoacTimeDistanc = (new Date().getTime() - GlobalConfig.serverTime) / 1000; //当前系统时间和服务器时间的差值 (秒)  
1621 - loger.warn("服务器时间:" + GlobalConfig.serverTime + " 系统时间:" + new Date().getTime() + " 时间差:" + GlobalConfig.serverAndLoacTimeDistanc);  
1622 -  
1623 - GlobalConfig.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表  
1624 - GlobalConfig.setRecordList(_data.recordList); //录制回放地址  
1625 - GlobalConfig.setDocList(_data.docList); //文档地址  
1626 - GlobalConfig.setMsList(_data.msList); //推流播流服务器地址(需要对列表中的地址进行分类,里面包含了推流和拉流的地址,目前主要是乐视的需要区分开)  
1627 - GlobalConfig.setRsList(_data.rsList); //播放m3u8格式的地址(录制回放时使用)  
1628 - GlobalConfig.setMcuList(_data.mcuList); //mcu  
1629 - GlobalConfig.setMusicList(_data.musicList); //  
1630 - GlobalConfig.setMusicListPrepare(_data.musicListPrepare); //提前上传的声音文件列表  
1631 - GlobalConfig.setVideoCDNAddr(_data.videoCDNAddr); //cdn加速的拉流地址,直播的时候才使用  
1632 - GlobalConfig.setMediaShareList(_data.sharedMediaList); //提前上传的媒体共享文件列表  
1633 -  
1634 - //MCU地址  
1635 - if (_data.mcuList && _data.mcuList.length > 0) {  
1636 - //随机选择一个  
1637 - let index = parseInt(Math.random() * _data.mcuList.length);  
1638 - GlobalConfig.MCUServerIP = _data.mcuList[index].ip || "";  
1639 - GlobalConfig.MCUServerPort = _data.mcuList[index].port || "";  
1640 - loger.log('初始->MCU->.', GlobalConfig.MCUServerIP, GlobalConfig.MCUServerPort);  
1641 - }  
1642 -  
1643 - //录制回放时m3u8播流地址  
1644 - if (_data.rsList && _data.rsList.length > 0) {  
1645 - let index = parseInt(Math.random() * _data.rsList.length);  
1646 - GlobalConfig.RS_RECORD_PLAY_IP = _data.rsList[index].ip || "";  
1647 - GlobalConfig.RS_RECORD_PLAY_PORT = _data.rsList[index].port || "";  
1648 - loger.log('初始->RS->.', GlobalConfig.RS_RECORD_PLAY_IP, GlobalConfig.RS_RECORD_PLAY_PORT);  
1649 - }  
1650 -  
1651 - //上课中音视频推流地址  
1652 - if (GlobalConfig.msList && GlobalConfig.msList.length > 0) {  
1653 - let index = parseInt(Math.random() * GlobalConfig.msList.length);  
1654 - GlobalConfig.MS_PUBLISH_IP = GlobalConfig.msList[index].ip || "";  
1655 - GlobalConfig.MS_PUBLISH_PORT = GlobalConfig.msList[index].port || "";  
1656 - }  
1657 - loger.log('初始->MS->.', GlobalConfig.MS_PUBLISH_IP, GlobalConfig.MS_PUBLISH_PORT);  
1658 -  
1659 - //播流的地址和推流地址需要分开的时候,单独设置拉流的地址 rtmp(目前乐视使用)  
1660 - if (GlobalConfig.rtmpPullList && GlobalConfig.rtmpPullList.length > 0) {  
1661 - //有单独的rtmp拉流地址  
1662 - let index = parseInt(Math.random() * GlobalConfig.rtmpPullList.length);  
1663 - GlobalConfig.MS_PLAY_RTMP_IP = GlobalConfig.rtmpPullList[index].ip || "";  
1664 - GlobalConfig.MS_PLAY_RTMP_PORT = GlobalConfig.rtmpPullList[index].port || "";  
1665 - } else {  
1666 - //如果没有单独的rtmp拉流地址,和推流地址一样即可  
1667 - GlobalConfig.MS_PLAY_RTMP_IP = GlobalConfig.MS_PUBLISH_IP;  
1668 - GlobalConfig.MS_PLAY_RTMP_PORT = GlobalConfig.MS_PUBLISH_PORT;  
1669 - }  
1670 -  
1671 - loger.log('初始->MSPull->.', GlobalConfig.MS_PLAY_RTMP_IP, GlobalConfig.MS_PLAY_RTMP_PORT);  
1672 -  
1673 - //播流的地址和推流地址需要分开的时候,单独设置拉流的地址 hls(目前乐视使用)  
1674 - if (GlobalConfig.hlsList && GlobalConfig.hlsList.length > 0) {  
1675 - //有单独的hls拉流地址  
1676 - let index = parseInt(Math.random() * GlobalConfig.hlsList.length);  
1677 - GlobalConfig.MS_PLAY_HLS_IP = GlobalConfig.hlsList[index].ip || "";  
1678 - GlobalConfig.MS_PLAY_HLS_PORT = GlobalConfig.hlsList[index].port || "";  
1679 - } else {  
1680 - //没有单独的hls拉流地址,和录制回放地址一样即可  
1681 - GlobalConfig.MS_PLAY_HLS_IP = GlobalConfig.RS_RECORD_PLAY_IP;  
1682 - GlobalConfig.MS_PLAY_HLS_PORT = GlobalConfig.RS_RECORD_PLAY_PORT;  
1683 - }  
1684 - loger.log('初始->MSHls->.', GlobalConfig.MS_PLAY_HLS_IP, GlobalConfig.MS_PLAY_HLS_PORT);  
1685 -  
1686 - //直播的时候,拉流(rtmp和hls)需要从 videoCDNAddr中获取  
1687 - //20170531-新规则,所有课堂类型都支持加速  
1688 - // if(GlobalConfig.classType==ApeConsts.CLASS_TYPE_2&&GlobalConfig.videoCDNAddrList.length>0){  
1689 -  
1690 - //20170629-直播课堂和移动端设备的时候支持  
1691 - if (GlobalConfig.classType == ApeConsts.CLASS_TYPE_2 || GlobalConfig.isMobile) {  
1692 - if (GlobalConfig.videoCDNAddrList.length > 0) {  
1693 - //videoCDNAddrList中rtmppush和hls是混在一起的,需要分离开;  
1694 - let listLen = GlobalConfig.videoCDNAddrList.length;  
1695 - for (let i = 0; i < listLen; i++) {  
1696 - let ipItem = GlobalConfig.videoCDNAddrList[i];  
1697 - if (ipItem) {  
1698 - if (ipItem.indexOf('hls') >= 0) {  
1699 - //直播的时候m3u8拉流地址  
1700 - GlobalConfig.MS_PLAY_HLS_IP = ipItem; //ip包含了端口  
1701 - GlobalConfig.MS_PLAY_HLS_PORT = "";  
1702 - loger.log('videoCDNAddr>初始->MSHls', GlobalConfig.MS_PLAY_HLS_IP);  
1703 - }  
1704 - if (ipItem.indexOf('rtmppull')>= 0) {  
1705 - //直播的时候rtmp拉流地址  
1706 - GlobalConfig.MS_PLAY_RTMP_IP = ipItem; //ip包含了端口  
1707 - GlobalConfig.MS_PLAY_RTMP_PORT = '';  
1708 - loger.log('videoCDNAddr->初始->MSPull', GlobalConfig.MS_PLAY_RTMP_IP);  
1709 - }  
1710 - }  
1711 - }  
1712 - } else {  
1713 - loger.error('videoCDNAddr数据无效->', GlobalConfig.videoCDNAddr);  
1714 - }  
1715 - } else {  
1716 - loger.warn('非直播课堂或不是移动端->不需要videoCDN加速');  
1717 - }  
1718 -  
1719 - //文档地址  
1720 - if (_data.docList && _data.docList.length > 0) {  
1721 - //doc上传地址,随机获取一个  
1722 - let index = parseInt(Math.random() * _data.docList.length);  
1723 - loger.log("docServer->", _data.docList[index]);  
1724 - GlobalConfig.DOCServerIP = _data.docList[index].ip || "";  
1725 - GlobalConfig.DOCServerPort = _data.docList[index].port || "";  
1726 - loger.log('初始->DOC->.', GlobalConfig.DOCServerIP, GlobalConfig.DOCServerPort);  
1727 - }  
1728 -  
1729 - //record  
1730 - if (_data.recordList && _data.recordList.length > 0) {  
1731 - let index = parseInt(Math.random() * _data.recordList.length);  
1732 - GlobalConfig.RecordServerIP = _data.recordList[index].ip || "";  
1733 - GlobalConfig.RecordServerPort = _data.recordList[index].port || "";  
1734 - loger.log('初始->RECORD->.', GlobalConfig.RecordServerIP, GlobalConfig.RecordServerPort);  
1735 - }  
1736 -  
1737 - }  
1738 - //这里需要考虑是否加延迟处理,课堂信息刚获取完成,客户端需要根据数据创建界面UI,等创建完成后再加入课堂是最合适的(目前没有加延迟)  
1739 - this._emit(MessageTypes.CLASS_GET_INFO_SUCCESS, GlobalConfig.getClassInfo());  
1740 -  
1741 - if (_data.currentInfo) {  
1742 - //根据从Sass获取的数据信息,同步最后一次保存的课堂状态信息  
1743 - loger.log("本地同步最后一次保存过的课堂状态信息");  
1744 - try {  
1745 - GlobalConfig.setClassStatusInfo(JSON.parse(_data.currentInfo));  
1746 - } catch (err) {  
1747 - loger.warn("从Sass获取的课堂数据JSON转换失败->");  
1748 - console.log("currentInfo", _data.currentInfo);  
1749 - GlobalConfig.setClassStatusInfo(_data.currentInfo);  
1750 - }  
1751 - loger.log(GlobalConfig.classStatusInfo);  
1752 - } else {  
1753 - loger.log("还没有保存过课堂状信息");  
1754 - }  
1755 -  
1756 - //录制回放不需要获取ip信息和选点  
1757 - if (GlobalConfig.isRecordPlayBack) {  
1758 - if (_recordPlayback) {  
1759 - //开启录制回放流程  
1760 - loger.log("开启录制回放流程");  
1761 - _recordPlayback.readyRecordPlay();  
1762 - } else {  
1763 - loger.warn("开启录制回放流程失败->还未创建模块");  
1764 - }  
1765 - } else {  
1766 - //根据用户的userIp获取信息,选点  
1767 - this.getUserIpInfo();  
1768 - }  
1769 - }*/  
1770 -  
1771 - //ChatApe  
1772 - // 发送聊天消息  
1773 - _sendChatMsg(_messageInfo) {  
1774 - if (!_mcu.connected) {  
1775 - loger.warn(GlobalConfig.getCurrentStatus());  
1776 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1777 - }  
1778 - if (_messageInfo === null || EngineUtils.isEmptyObject(_messageInfo)) {  
1779 - loger.log('发送聊天消息失败->参数错误', _messageInfo);  
1780 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1781 - }  
1782 - if (_chat_ape) {  
1783 - _chat_ape.sendChatMsg(_messageInfo);  
1784 - }  
1785 - }  
1786 -  
1787 - //监听摄像头麦克风状态  
1788 - userDeviecStatusChange(_data) {  
1789 - /* nodeId:GlobalConfig.nodeId,  
1790 - userRole:GlobalConfig.userRole,  
1791 - userName:GlobalConfig.userName,  
1792 - userId:GlobalConfig.userId,  
1793 - openCamera:GlobalConfig.openCamera,  
1794 - openMicrophones:GlobalConfig.openMicrophones*/  
1795 - if (_confer_ape) {  
1796 - _confer_ape.updaterUserDeviecStatusChange(_data);  
1797 - }  
1798 - }  
1799 -  
1800 - //屏幕共享  
1801 - //开始屏幕共享  
1802 - _publishScreenShare(_param) {  
1803 - if (_video_ape) {  
1804 - _video_ape.publishScreenShare(_param);  
1805 - }  
1806 - }  
1807 -  
1808 - //停止屏幕共享  
1809 - _stopPublishScreenShare(_param) {  
1810 - if (_video_ape) {  
1811 - _video_ape.stopPublishScreenShare(_param);  
1812 - }  
1813 - }  
1814 -  
1815 - //VidoeApe  
1816 - videoUpdate(_data) {  
1817 - //视频同步的消息发送改变,需要通知ferApe模块中的用户更新状态  
1818 - if (_confer_ape) {  
1819 - _confer_ape.updaterRosterStatus(_data);  
1820 - }  
1821 - }  
1822 -  
1823 - _sendVideoBroadcastMsg(_param) {  
1824 - if (!_mcu.connected) {  
1825 - loger.warn(GlobalConfig.getCurrentStatus());  
1826 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1827 - }  
1828 - if (_video_ape) {  
1829 - return _video_ape.sendVideoBroadcastMsg(_param);  
1830 - }  
1831 - }  
1832 -  
1833 - _getVideoPlayPath(_param) {  
1834 - if (_video_ape) {  
1835 - return _video_ape.getPlayVideoPath(_param);  
1836 - }  
1837 - }  
1838 -  
1839 - _getVideoPublishPath(_param) {  
1840 - if (_video_ape) {  
1841 - return _video_ape.getPublishVideoPath(_param);  
1842 - }  
1843 - }  
1844 -  
1845 - _getVideoAllChannelInfo(_param) {  
1846 - if (_video_ape) {  
1847 - return _video_ape.getAllChannelInfo(_param);  
1848 - }  
1849 - }  
1850 -  
1851 - _publishVideo(_param) {  
1852 - if (!_mcu.connected) {  
1853 - loger.warn(GlobalConfig.getCurrentStatus());  
1854 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1855 - }  
1856 - if (_video_ape) {  
1857 - return _video_ape.publishVideo(_param);  
1858 - }  
1859 - }  
1860 -  
1861 - _stopPublishVideo(_param) {  
1862 - if (!_mcu.connected) {  
1863 - loger.warn(GlobalConfig.getCurrentStatus());  
1864 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1865 - }  
1866 - if (_video_ape) {  
1867 - return _video_ape.stopPublishVideo(_param);  
1868 - }  
1869 - }  
1870 -  
1871 - //AudioApe  
1872 - audioUpdate(_data) {  
1873 - //音频同步的消息发送改变,需要通知ferApe模块中的用户更新状态  
1874 - if (_confer_ape) {  
1875 - _confer_ape.updaterRosterStatus(_data);  
1876 - }  
1877 - }  
1878 -  
1879 - sendAudioCommandMsg(_param) {  
1880 - if (!_mcu.connected) {  
1881 - loger.warn(GlobalConfig.getCurrentStatus());  
1882 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1883 - }  
1884 - if (_audio_ape) {  
1885 - return _audio_ape.sendAudioBroadcastMsg(_param);  
1886 - }  
1887 - }  
1888 -  
1889 - _getPlayAudioPath(_param) {  
1890 - if (_audio_ape) {  
1891 - return _audio_ape.getAudioPlayPath(_param);  
1892 - }  
1893 - }  
1894 -  
1895 - _getPublishAudioPath(_param) {  
1896 - if (_audio_ape) {  
1897 - return _audio_ape.getAudioPublishPath(_param);  
1898 - }  
1899 - }  
1900 -  
1901 - _getAudioAllChannelInfo(_param) {  
1902 - if (_audio_ape) {  
1903 - return _audio_ape.getAllChannelInfo(_param);  
1904 - }  
1905 - }  
1906 -  
1907 - _publishAudio(_param) {  
1908 - if (!_mcu.connected) {  
1909 - loger.warn(GlobalConfig.getCurrentStatus());  
1910 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1911 - }  
1912 - if (_audio_ape) {  
1913 - return _audio_ape.publishAudio(_param);  
1914 - }  
1915 - }  
1916 -  
1917 - _stopPublishAudio(_param) {  
1918 - if (!_mcu.connected) {  
1919 - loger.warn(GlobalConfig.getCurrentStatus());  
1920 - return {"code": ApeConsts.RETURN_FAILED, "data": ""};  
1921 - }  
1922 - if (_audio_ape) {  
1923 - return _audio_ape.stopPublishAudio(_param);  
1924 - }  
1925 - }  
1926 -  
1927 - //WhiteBoardApe  
1928 - // 添加标注,发送信息  
1929 - _sendInsertAnnotaion(_param) {  
1930 - if (!_mcu.connected) {  
1931 - loger.warn(GlobalConfig.getCurrentStatus());  
1932 - return;  
1933 - }  
1934 - if (_whiteboard_ape) {  
1935 - _whiteboard_ape.sendInsetAnnotaion(_param);  
1936 - }  
1937 - }  
1938 -  
1939 - //CursorApe  
1940 - // 添加鼠标同步  
1941 - _sendInsertCursor(_param) {  
1942 - if (!_mcu.connected) {  
1943 - loger.warn(GlobalConfig.getCurrentStatus());  
1944 - return;  
1945 - }  
1946 - if (_cursor_ape) {  
1947 - _cursor_ape.sendInsertCursor(_param);  
1948 - }  
1949 - }  
1950 -  
1951 - //删除当前页面上的所有标注  
1952 - _sendDeleteCurPageAnnotation(_param) {  
1953 - if (!_mcu.connected) {  
1954 - loger.warn(GlobalConfig.getCurrentStatus());  
1955 - return;  
1956 - }  
1957 - if (_whiteboard_ape) {  
1958 - _whiteboard_ape.sendDeleteCurPageAnnotation(_param);  
1959 - }  
1960 - }  
1961 -  
1962 - //删除所有标注  
1963 - _sendDeleteAllAnnotation(_param) {  
1964 - if (!_mcu.connected) {  
1965 - loger.warn(GlobalConfig.getCurrentStatus());  
1966 - return;  
1967 - }  
1968 - if (_whiteboard_ape) {  
1969 - _whiteboard_ape.sendDeleteAllAnnotation(_param);  
1970 - }  
1971 - }  
1972 -  
1973 - //返回上一步标注  
1974 - _sendGotoPrev(_param) {  
1975 - if (_whiteboard_ape) {  
1976 - _whiteboard_ape.sendGotoPrev(_param);  
1977 - }  
1978 - }  
1979 -  
1980 - //DocApe  
1981 - //获取文档的所有资源地址  
1982 - _getDocFullAddress(_param) {  
1983 - if (_doc_ape) {  
1984 - return _doc_ape.getDocFullAddress(_param);  
1985 - } else {  
1986 - loger.error("文档模块还没有创建无法获取");  
1987 - return {"code": ApeConsts.RETURN_FAILED, "data": "文档模块还没有创建无法获取"};  
1988 - }  
1989 - }  
1990 -  
1991 - //获取文档完整路径  
1992 - _getDocImageFullPath(_param) {  
1993 - if (_doc_ape) {  
1994 - return _doc_ape.getDocImageFullPath(_param);  
1995 - } else {  
1996 - loger.error("文档模块还没有创建无法获取");  
1997 - return [];  
1998 - }  
1999 - }  
2000 -  
2001 - _getDocPDFFullPath(_param) {  
2002 - if (_doc_ape) {  
2003 - return _doc_ape.getDocPDFFullPath(_param);  
2004 - } else {  
2005 - loger.error("文档模块还没有创建,无法获取");  
2006 - return [];  
2007 - }  
2008 - }  
2009 -  
2010 - //上传文档  
2011 - _sendDocumentUpload(_param) {  
2012 - if (!_mcu.connected) {  
2013 - loger.warn(GlobalConfig.getCurrentStatus());  
2014 - return;  
2015 - }  
2016 - if (_doc_ape) {  
2017 - _doc_ape.documentUpload(_param);  
2018 - }  
2019 - }  
2020 -  
2021 - //切换文档  
2022 - _sendDocumentSwitchDoc(_param) {  
2023 - if (!_mcu.connected) {  
2024 - loger.warn(GlobalConfig.getCurrentStatus());  
2025 - return;  
2026 - }  
2027 - if (_doc_ape) {  
2028 - _doc_ape.documentSwitchDoc(_param);  
2029 - }  
2030 - }  
2031 -  
2032 - //操作文档(翻页)  
2033 - _sendDocumentSwitchPage(_param) {  
2034 - if (!_mcu.connected) {  
2035 - loger.warn(GlobalConfig.getCurrentStatus());  
2036 - return;  
2037 - }  
2038 - if (_doc_ape) {  
2039 - _doc_ape.documentSwitchPage(_param);  
2040 - }  
2041 - }  
2042 -  
2043 - //操作文档(页码上的动画步骤操作)  
2044 - _sendDocumentSwitchAnimation(_param) {  
2045 - if (!_mcu.connected) {  
2046 - loger.warn(GlobalConfig.getCurrentStatus());  
2047 - return;  
2048 - }  
2049 - if (_doc_ape) {  
2050 - _doc_ape.documentSwitchAnimation(_param);  
2051 - }  
2052 - }  
2053 -  
2054 - //操作文档(缩放、滚动...)  
2055 - _sendDocumentCommand(_param) {  
2056 - if (!_mcu.connected) {  
2057 - loger.warn(GlobalConfig.getCurrentStatus());  
2058 - return;  
2059 - }  
2060 - if (_doc_ape) {  
2061 - _doc_ape.documentCommand(_param);  
2062 - }  
2063 - }  
2064 -  
2065 - //删除文档  
2066 - _sendDocumentDelete(_param) {  
2067 - if (!_mcu.connected) {  
2068 - loger.warn(GlobalConfig.getCurrentStatus());  
2069 - return;  
2070 - }  
2071 - if (_doc_ape) {  
2072 - _doc_ape.documentDelete(_param);  
2073 - }  
2074 - }  
2075 -  
2076 - //删除所有文档  
2077 - _documentDeleteAll(_param) {  
2078 - if (!_mcu.connected) {  
2079 - loger.warn(GlobalConfig.getCurrentStatus());  
2080 - return;  
2081 - }  
2082 - if (_doc_ape) {  
2083 - _doc_ape.documentDeleteAll(_param);  
2084 - }  
2085 - }  
2086 -  
2087 - //// 文档变更,白板也需要做处理  
2088 - docUpdateHandler(_data) {  
2089 - if (!_mcu.connected && !GlobalConfig.isRecordPlayBack) {  
2090 - loger.warn(GlobalConfig.getCurrentStatus());  
2091 - return;  
2092 - }  
2093 - //loger.log('Doc UpdateId ->');  
2094 - //loger.log(_data);  
2095 - if (_whiteboard_ape) {  
2096 - _whiteboard_ape.docUpdateHandler(_data);  
2097 - }  
2098 - }  
2099 -  
2100 - //文档删除,白板也需要做处理  
2101 - docDeleteHandler(_data) {  
2102 - if (_whiteboard_ape) {  
2103 - _whiteboard_ape.docDeleteHandler(_data);  
2104 - }  
2105 - }  
2106 -  
2107 - //文档加入频道成功,同步到MCU服务器上的数据  
2108 - docJoinChannelSuccess() {  
2109 - loger.log("docJoinChannelSuccess->isHost=", GlobalConfig.isHost, "当前总人数:", GlobalConfig.rosterNumber, "sassDoclength=", GlobalConfig.docListPrepare.length);  
2110 - //loger.log("docJoinChannelSuccess docListPrepare=");  
2111 - //如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传  
2112 - if (GlobalConfig.docListPrepare && GlobalConfig.docListPrepare.length > 0) {  
2113 - //如果当前身份是老师或者当前课堂内只有一个人,有权限同步文档到MCU  
2114 - if (GlobalConfig.isHost || GlobalConfig.rosterNumber <= 1) {  
2115 - for (let i = 0; i < GlobalConfig.docListPrepare.length; i++) {  
2116 - let value = GlobalConfig.docListPrepare[i];  
2117 - if (value) {  
2118 - //loger.log("判断是否需要把提前上传的文档上传到mcu", value);  
2119 - let paramInfo = {  
2120 - "pageNum": value.pdfSize,  
2121 - "fileName": value.name,  
2122 - "fileType": value.type,  
2123 - "relativeUrl": value.relativeLocation,  
2124 - "url": value.absoluteLocation,  
2125 - "creatUserId": value.createUserID,  
2126 - "docId": value.id,  
2127 - "md5": value.MD5,  
2128 - "visible": false  
2129 - };  
2130 - this._sendDocumentUpload(paramInfo);  
2131 - }  
2132 - }  
2133 - }  
2134 - }  
2135 - }  
2136 -  
2137 - //媒体共享模块的接口  
2138 - //上传  
2139 - _sendMediaSharedUpload(_param) {  
2140 - if (!_mcu.connected) {  
2141 - loger.warn(GlobalConfig.getCurrentStatus());  
2142 - return;  
2143 - }  
2144 - if (_mediaShareApe) {  
2145 - _mediaShareApe.mediaSharedUpload(_param);  
2146 - }  
2147 - }  
2148 -  
2149 - //音乐共享模块的接口  
2150 - //上传  
2151 - _sendMusicSharedUpload(_param) {  
2152 - if (!_mcu.connected) {  
2153 - loger.warn(GlobalConfig.getCurrentStatus());  
2154 - return;  
2155 - }  
2156 - if (_musicShareApe) {  
2157 - _musicShareApe.musicSharedUpload(_param);  
2158 - }  
2159 - }  
2160 -  
2161 - //Sass删除媒体文件数据  
2162 - _sassDeletMediaShare(_param) {  
2163 - if (!_mcu.connected) {  
2164 - loger.warn(GlobalConfig.getCurrentStatus());  
2165 - return;  
2166 - }  
2167 -  
2168 - //判断传入的参数是否存在  
2169 - if (_param == null || EngineUtils.isEmptyObject(_param)) {  
2170 - loger.error('删除媒体文件失败->参数错误', _param);  
2171 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_MEDIASHARE_DELETE_FAILED_PARAM);  
2172 - return;  
2173 - }  
2174 - //判断必要的参数字段值  
2175 - if (_param.itemIdx == null || isNaN(_param.itemIdx) || _param.fileId == null || _param.fileId == "") {  
2176 - loger.error('删除媒体文件失败->', _param);  
2177 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_MEDIASHARE_DELETE_FAILED_PARAM);  
2178 - return;  
2179 - }  
2180 - loger.log('删除媒体文件->', _param);  
2181 -  
2182 - if (_sass) {  
2183 - _sass.sassDeletMediaShare(_param);  
2184 - }  
2185 - }  
2186 -  
2187 - // 删除Music  
2188 - _sassDeletMusicShare(_param) {  
2189 - if (!_mcu.connected) {  
2190 - loger.warn(GlobalConfig.getCurrentStatus());  
2191 - return;  
2192 - }  
2193 -  
2194 - //判断传入的参数是否存在  
2195 - if (_param == null || EngineUtils.isEmptyObject(_param)) {  
2196 - loger.error('删除媒体文件失败->参数错误', _param);  
2197 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_MUSICSHARE_DELETE_FAILED_PARAM);  
2198 - return;  
2199 - }  
2200 - //判断必要的参数字段值  
2201 - if (_param.itemIdx == null || isNaN(_param.itemIdx) || _param.fileId == null || _param.fileId == "") {  
2202 - loger.error('删除媒体文件失败->', _param);  
2203 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_MUSICSHARE_DELETE_FAILED_PARAM);  
2204 - return;  
2205 - }  
2206 - loger.log('删除媒体文件->', _param);  
2207 -  
2208 - if (_sass) {  
2209 - _sass.sassDeletMusicShare(_param);  
2210 - }  
2211 - }  
2212 -  
2213 - //删除媒体  
2214 - _sendMediaSharedDelete(_param) {  
2215 - if (!_mcu.connected) {  
2216 - loger.warn(GlobalConfig.getCurrentStatus());  
2217 - return;  
2218 - }  
2219 - if (_mediaShareApe) {  
2220 - _mediaShareApe.mediaSharedDelete(_param);  
2221 - }  
2222 - }  
2223 -  
2224 - //删除媒体  
2225 - _sendMusicSharedDelete(_param) {  
2226 - if (!_mcu.connected) {  
2227 - loger.warn(GlobalConfig.getCurrentStatus());  
2228 - return;  
2229 - }  
2230 - if (_musicShareApe) {  
2231 - _musicShareApe.musicSharedDelete(_param);  
2232 - }  
2233 - }  
2234 -  
2235 - //音乐更新  
2236 - _sendMusicSharedUpdate(_param) {  
2237 - if (!_mcu.connected) {  
2238 - loger.warn(GlobalConfig.getCurrentStatus());  
2239 - return;  
2240 - }  
2241 - if (_musicShareApe) {  
2242 - _musicShareApe.musicSharedUpdate(_param);  
2243 - }  
2244 - }  
2245 -  
2246 - //音乐播放  
2247 - _sendMusicSharedPlay(_param) {  
2248 - if (!_mcu.connected) {  
2249 - loger.warn(GlobalConfig.getCurrentStatus());  
2250 - return;  
2251 - }  
2252 - if (_musicShareApe) {  
2253 - _musicShareApe.musicSharedPlay(_param);  
2254 - }  
2255 - }  
2256 -  
2257 - //音乐停止  
2258 - _sendMusicSharedStop(_param) {  
2259 - if (!_mcu.connected) {  
2260 - loger.warn(GlobalConfig.getCurrentStatus());  
2261 - return;  
2262 - }  
2263 - if (_musicShareApe) {  
2264 - _musicShareApe.musicSharedStop(_param);  
2265 - }  
2266 - }  
2267 -  
2268 - //更新媒体文件的状态信息  
2269 - _sendMediaSharedUpdate(_param) {  
2270 - if (!_mcu.connected) {  
2271 - loger.warn(GlobalConfig.getCurrentStatus());  
2272 - return;  
2273 - }  
2274 - if (_mediaShareApe) {  
2275 - _mediaShareApe.mediaSharedUpdate(_param);  
2276 - }  
2277 - }  
2278 -  
2279 - //播放  
2280 - _sendMediaSharedPlay(_param) {  
2281 - if (!_mcu.connected) {  
2282 - loger.warn(GlobalConfig.getCurrentStatus());  
2283 - return;  
2284 - }  
2285 - if (_mediaShareApe) {  
2286 - _mediaShareApe.mediaSharedPlay(_param);  
2287 - }  
2288 - }  
2289 -  
2290 - //停止  
2291 -  
2292 - _sendMediaSharedStop(_param) {  
2293 - if (!_mcu.connected) {  
2294 - loger.warn(GlobalConfig.getCurrentStatus());  
2295 - return;  
2296 - }  
2297 - if (_mediaShareApe) {  
2298 - _mediaShareApe.mediaSharedStop(_param);  
2299 - }  
2300 - }  
2301 -  
2302 - //音乐共享模块加入频道成功,同步到MCU服务器上的数据  
2303 - musicShareApeJoinChannelSuccess() {  
2304 - loger.log("伴音MUSIC模块加入频道成功->isHost=", GlobalConfig.isHost, "length=", GlobalConfig.musicListPrepare.length);  
2305 - console.log("伴音MUSIC模块共享模数据->", GlobalConfig.musicListPrepare);  
2306 - //如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传  
2307 - if (GlobalConfig.isHost && GlobalConfig.musicListPrepare.length > 0) {  
2308 - for (let i = 0; i < GlobalConfig.musicListPrepare.length; i++) {  
2309 - let value = GlobalConfig.musicListPrepare[i];  
2310 - if (value) {  
2311 - let paramInfo = {  
2312 - "status": 0,  
2313 - "creatUserId": value.creatUserId,  
2314 - "creatUserName": value.createUserName,  
2315 - "url": value.url || value.absoluteLocation,//伴音上传的接口有差异,课堂内上传返回的是url字段,后台带入的字段是absoluteLocation  
2316 - "fileType": value.type,  
2317 - "fileId": "" + value.id,  
2318 - "fileName": value.name,  
2319 - "seek": 0  
2320 - };  
2321 - this._sendMusicSharedUpload(paramInfo);  
2322 - }  
2323 - }  
2324 - }  
2325 - }  
2326 -  
2327 - //媒体共享模块加入频道成功,同步到MCU服务器上的数据  
2328 - mediaShareApeJoinChannelSuccess() {  
2329 - loger.log("媒体共享模块加入频道成功->isHost=", GlobalConfig.isHost, "length=", GlobalConfig.sharedMediaList.length);  
2330 - console.log("媒体共享模数据->", GlobalConfig.sharedMediaList);  
2331 - //如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传  
2332 - if (GlobalConfig.isHost && GlobalConfig.sharedMediaList.length > 0) {  
2333 - for (let i = 0; i < GlobalConfig.sharedMediaList.length; i++) {  
2334 - let value = GlobalConfig.sharedMediaList[i];  
2335 - if (value) {  
2336 - let paramInfo = {  
2337 - "status": 0,  
2338 - "creatUserId": value.creatUserId,  
2339 - "creatUserName": value.createUserName,  
2340 - "url": value.url,  
2341 - "fileType": value.type,  
2342 - "fileId": "" + value.id,  
2343 - "fileName": value.name,  
2344 - "seek": 0  
2345 - };  
2346 - this._sendMediaSharedUpload(paramInfo);  
2347 - }  
2348 - }  
2349 - }  
2350 - }  
2351 -  
2352 - //录制回放相关的处理------------------------------------------------  
2353 - //录制回放初始化  
2354 - _initRecordPlayback(_param) {  
2355 - //{"classId":"1653304953","portal":"112.126.80.182:80","userRole":"normal","userId":0}  
2356 - if (_param == null) {  
2357 - loger.error('录制回放初始化失败->参数错误');  
2358 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED);  
2359 - return;  
2360 - }  
2361 - //判断必要的参数字段值  
2362 - if (_param.classId == null || isNaN(_param.classId) || _param.portal == null || _param.portal == "") {  
2363 - loger.error('录制回放初始化失败->', _param);  
2364 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_INIT_RECORD_PLAY_BACK_FAILED);  
2365 - return;  
2366 - }  
2367 - loger.log('录制回放初始化->', _param);  
2368 -  
2369 - //保存参数  
2370 - GlobalConfig.isRecordPlayBack = true; //设置为录制回放状态  
2371 - GlobalConfig.classId = parseInt(_param.classId);  
2372 - GlobalConfig.portal = _param.portal;  
2373 - GlobalConfig.userRole = ApeConsts.normal; //*************很重要,录制回放的时候,身份模式是普通人********  
2374 - GlobalConfig.userId = _param.userId || "0";  
2375 - GlobalConfig.userName = _param.userName || "";  
2376 -  
2377 - //获取课堂最完整的数据,录制回放需要获取课堂数据  
2378 - if (_sass) {  
2379 - _sass.getClassParam();  
2380 - }  
2381 - }  
2382 -  
2383 - //开始录制回放  
2384 - _startRecordPlayback(_param) {  
2385 - if (_recordPlayback) {  
2386 - _recordPlayback.startRecordPlayback(_param);  
2387 - }  
2388 - }  
2389 -  
2390 - //停止录制回放  
2391 - _stopRecordPlayback(_param) {  
2392 - if (_recordPlayback) {  
2393 - _recordPlayback.stopRecordPlayback(_param);  
2394 - }  
2395 - }  
2396 -  
2397 - //暂停录制回放  
2398 - _pauseRecordPlayback(_param) {  
2399 - if (_recordPlayback) {  
2400 - _recordPlayback.pauseRecordPlayback(_param);  
2401 - }  
2402 - }  
2403 -  
2404 - //seek录制回放  
2405 - _seekRecordPlayback(_param) {  
2406 - if (_recordPlayback) {  
2407 - _recordPlayback.seekRecordPlayback(_param);  
2408 - }  
2409 - }  
2410 -  
2411 - //录制回放状态更新  
2412 - _recordPlaybackClearDataHandler(_param) {  
2413 - loger.log("录制回放状态更新->")  
2414 - if (_doc_ape) {  
2415 - _doc_ape.clearData();  
2416 - }  
2417 - if (_whiteboard_ape) {  
2418 - _whiteboard_ape.clearData();  
2419 - }  
2420 - if (_video_ape) {  
2421 - _video_ape.clearData();  
2422 - }  
2423 - }  
2424 -  
2425 - //录制回放加入 课堂成功  
2426 - _joinRecordPlaybackSuccessHandler(_data) {  
2427 - loger.log('加入录制回放成功.');  
2428 - GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);  
2429 -  
2430 - //返回给客户端初始化成功的数据  
2431 - let joinClassSuccessCallBackData = {};  
2432 -  
2433 - joinClassSuccessCallBackData.isRecordPlayBack = GlobalConfig.isRecordPlayBack;  
2434 -  
2435 - joinClassSuccessCallBackData.DOCServerIP = GlobalConfig.DOCServerIP;  
2436 - joinClassSuccessCallBackData.DOCServerPort = GlobalConfig.DOCServerPort;  
2437 -  
2438 - joinClassSuccessCallBackData.classStatus = GlobalConfig.classStatus;  
2439 - joinClassSuccessCallBackData.classId = GlobalConfig.classId;  
2440 - joinClassSuccessCallBackData.className = GlobalConfig.className;  
2441 - joinClassSuccessCallBackData.h5Module = GlobalConfig.h5Module;  
2442 - joinClassSuccessCallBackData.isHost = GlobalConfig.isHost; //  
2443 - joinClassSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;  
2444 - joinClassSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;  
2445 - joinClassSuccessCallBackData.maxMediaChannels = GlobalConfig.maxMediaChannels;  
2446 -  
2447 - joinClassSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;  
2448 -  
2449 - joinClassSuccessCallBackData.msType = GlobalConfig.msType;  
2450 - joinClassSuccessCallBackData.nodeId = GlobalConfig.nodeId;  
2451 - joinClassSuccessCallBackData.password = GlobalConfig.password;  
2452 - joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired; // 老师的默认是true  
2453 - //GlobalConfig.passwordRequired 老师的默认是true  
2454 - //GlobalConfig.portal=_data.portal;  
2455 - joinClassSuccessCallBackData.role = GlobalConfig.role;  
2456 - joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;  
2457 - joinClassSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;  
2458 - joinClassSuccessCallBackData.userId = GlobalConfig.userId;  
2459 - joinClassSuccessCallBackData.userName = GlobalConfig.userName;  
2460 - joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;  
2461 - joinClassSuccessCallBackData.userType = GlobalConfig.userType;  
2462 -  
2463 - joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;  
2464 - joinClassSuccessCallBackData.classId = GlobalConfig.classId;  
2465 - joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;  
2466 - joinClassSuccessCallBackData.userId = GlobalConfig.userId;  
2467 - joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;  
2468 - joinClassSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_1;  
2469 -  
2470 - joinClassSuccessCallBackData.country = GlobalConfig.country; //国家  
2471 - joinClassSuccessCallBackData.city = GlobalConfig.city; //城市  
2472 - joinClassSuccessCallBackData.province = GlobalConfig.province; //服务商  
2473 - joinClassSuccessCallBackData.isp = GlobalConfig.isp; //服务商  
2474 -  
2475 - joinClassSuccessCallBackData.classTimestamp = GlobalConfig.classTimestamp; //课堂进行的累积时间  
2476 - joinClassSuccessCallBackData.recordTimestamp = GlobalConfig.recordTimestamp; //录制累积的总时间  
2477 - joinClassSuccessCallBackData.recordPlaybackMaxTime = GlobalConfig.recordPlaybackMaxTime; //录制回放的总时间  
2478 -  
2479 - joinClassSuccessCallBackData.fps = GlobalConfig.fps;  
2480 - joinClassSuccessCallBackData.gop = GlobalConfig.gop;  
2481 - joinClassSuccessCallBackData.videoQuality = GlobalConfig.videoQuality;  
2482 -  
2483 - joinClassSuccessCallBackData.ssTunnelAppURL = GlobalConfig.ssTunnelAppURL;  
2484 - joinClassSuccessCallBackData.currentSceneTableId = GlobalConfig.currentSceneTableId; //文档区域的模块显示  
2485 - joinClassSuccessCallBackData.serverAndLoacTimeDistanc = GlobalConfig.serverAndLoacTimeDistanc;  
2486 -  
2487 - joinClassSuccessCallBackData.deviceType = GlobalConfig.deviceType;  
2488 - joinClassSuccessCallBackData.language = GlobalConfig.language;  
2489 - joinClassSuccessCallBackData.explorer = GlobalConfig.explorer;  
2490 - joinClassSuccessCallBackData.explorerVersion = GlobalConfig.explorerVersion;  
2491 - joinClassSuccessCallBackData.os = GlobalConfig.os;  
2492 -  
2493 - loger.log(joinClassSuccessCallBackData);  
2494 - //和加入课堂成功使用同样的消息处理  
2495 - this._emit(MessageTypes.CLASS_JOIN_SUCCESS, joinClassSuccessCallBackData);  
2496 - }  
2497 -  
2498 - // //答题卡  
2499 - _creatQuestion(_param) {  
2500 - if (!_mcu.connected) {  
2501 - loger.warn(GlobalConfig.getCurrentStatus());  
2502 - return;  
2503 - }  
2504 - if (_questionApe) {  
2505 - _questionApe.creatQuestion(_param);  
2506 - }  
2507 - }  
2508 -  
2509 - _getQuestion(_param) {  
2510 - if (!_mcu.connected) {  
2511 - loger.warn(GlobalConfig.getCurrentStatus());  
2512 - return;  
2513 - }  
2514 - if (_questionApe) {  
2515 - _questionApe.getQuestion(_param);  
2516 - }  
2517 - }  
2518 -  
2519 - _getQuestionResult(_param) {  
2520 - if (!_mcu.connected) {  
2521 - loger.warn(GlobalConfig.getCurrentStatus());  
2522 - return;  
2523 - }  
2524 - if (_questionApe) {  
2525 - _questionApe.getQuestionResult(_param);  
2526 - }  
2527 - }  
2528 -  
2529 - _stopQuestion(_param) {  
2530 - if (!_mcu.connected) {  
2531 - loger.warn(GlobalConfig.getCurrentStatus());  
2532 - return;  
2533 - }  
2534 - if (_questionApe) {  
2535 - _questionApe.stopQuestion(_param);  
2536 - }  
2537 - }  
2538 -  
2539 - _sendAnswer(_param) {  
2540 - if (!_mcu.connected) {  
2541 - loger.warn(GlobalConfig.getCurrentStatus());  
2542 - return;  
2543 - }  
2544 - if (_questionApe) {  
2545 - _questionApe.sendAnswer(_param);  
2546 - }  
2547 - }  
2548 -  
2549 -}  
2550 -  
@@ -135,7 +135,8 @@ class GlobalConfig { @@ -135,7 +135,8 @@ class GlobalConfig {
135 this.classTimestamp = data.classTimestamp || this.classTimestamp; //相对于点开始课堂的时间戳 135 this.classTimestamp = data.classTimestamp || this.classTimestamp; //相对于点开始课堂的时间戳
136 136
137 137
138 - this.recordStatus = data.recordStatus || this.recordStatus; //当前录制状态 138 + //this.recordStatus = data.recordStatus || this.recordStatus; //当前录制状态
  139 + this.recordStatus = data.recordStatus ||false; //当前录制状态
139 this.recordTimestamp = data.recordTimestamp || this.recordTimestamp; //相对于首次开始录制的时间戳 140 this.recordTimestamp = data.recordTimestamp || this.recordTimestamp; //相对于首次开始录制的时间戳
140 this.recordFileName = data.recordFileName || this.recordFileName; //录制的文件名 141 this.recordFileName = data.recordFileName || this.recordFileName; //录制的文件名
141 this.recordDownloadUrl = data.recordDownloadUrl || this.recordDownloadUrl; //下载地址 142 this.recordDownloadUrl = data.recordDownloadUrl || this.recordDownloadUrl; //下载地址
@@ -522,7 +523,7 @@ GlobalConfig.recordReplaytickValues = {}; // 滚动条关键点,用于快进 @@ -522,7 +523,7 @@ GlobalConfig.recordReplaytickValues = {}; // 滚动条关键点,用于快进
522 523
523 GlobalConfig.isAutoStartClass = 0; //是否自动开始上课 0-否 ;1 是 524 GlobalConfig.isAutoStartClass = 0; //是否自动开始上课 0-否 ;1 是
524 525
525 -GlobalConfig.updateClassInfoDelay = 30; //(秒),每隔30秒同步一次课堂状态的并保存到Sass 526 +GlobalConfig.updateClassInfoDelay = 20; //(秒),每隔30秒同步一次课堂状态的并保存到Sass
526 GlobalConfig.msDynamicChooseIpDelay = 60 * 3; //(秒)MS动态选点的间隔 527 GlobalConfig.msDynamicChooseIpDelay = 60 * 3; //(秒)MS动态选点的间隔
527 //GlobalConfig.serverTimestamp=0;//当前的系统时间戳 用get set 获取 528 //GlobalConfig.serverTimestamp=0;//当前的系统时间戳 用get set 获取
528 529
@@ -540,7 +541,7 @@ GlobalConfig.classDetail = {}; //Sass直接返回的当前课堂基本信息 @@ -540,7 +541,7 @@ GlobalConfig.classDetail = {}; //Sass直接返回的当前课堂基本信息
540 541
541 542
542 GlobalConfig.isRecordPlayBack = false; //是否是录制回放,默认是否 543 GlobalConfig.isRecordPlayBack = false; //是否是录制回放,默认是否
543 -GlobalConfig.allowRecordMaxTime = 24*60*60; //(秒)允许录制的最长时间 544 +GlobalConfig.allowRecordMaxTime = 48*60*60; //(秒)允许录制的最长时间
544 545
545 GlobalConfig.siteId_letv = 'shchuanbao'; //乐视,MS不需要动态选点的站点 546 GlobalConfig.siteId_letv = 'shchuanbao'; //乐视,MS不需要动态选点的站点
546 GlobalConfig.ssTunnelAppURL = ''; //屏幕共享插件的地址 547 GlobalConfig.ssTunnelAppURL = ''; //屏幕共享插件的地址
@@ -7,7 +7,6 @@ import ApeConsts from './ApeConsts'; @@ -7,7 +7,6 @@ import ApeConsts from './ApeConsts';
7 import ThirdMessage from './ThirdMessage'; 7 import ThirdMessage from './ThirdMessage';
8 import MessageTypes from 'MessageTypes'; 8 import MessageTypes from 'MessageTypes';
9 import pdu from 'pdus'; 9 import pdu from 'pdus';
10 -//import { Zlib } from 'zlibjs/bin/zlib.min';  
11 import UTF8 from 'utf-8'; 10 import UTF8 from 'utf-8';
12 import Loger from 'Loger'; 11 import Loger from 'Loger';
13 import GlobalConfig from 'GlobalConfig'; 12 import GlobalConfig from 'GlobalConfig';
@@ -28,6 +27,7 @@ class ConferApe extends Ape { @@ -28,6 +27,7 @@ class ConferApe extends Ape {
28 this.rosters = {}; //用户列表 27 this.rosters = {}; //用户列表
29 this.rosterLen = 0;//当前课堂人数 28 this.rosterLen = 0;//当前课堂人数
30 this.timerCounter = new TimerCounter(); //计时器 29 this.timerCounter = new TimerCounter(); //计时器
  30 + this.startClassTimer;//开始课堂和开始录制的计时器
31 31
32 //第三方消息控制 parent和Iframe直接的通讯 32 //第三方消息控制 parent和Iframe直接的通讯
33 this.thirdMessage = new ThirdMessage(); 33 this.thirdMessage = new ThirdMessage();
@@ -246,7 +246,6 @@ class ConferApe extends Ape { @@ -246,7 +246,6 @@ class ConferApe extends Ape {
246 246
247 //保存当前的录制状态 247 //保存当前的录制状态
248 GlobalConfig.recordStatus = _param.recordStatus || false; 248 GlobalConfig.recordStatus = _param.recordStatus || false;
249 -  
250 let conferRecordSendPdu = new pdu['RCConferenceRecordRequestPdu']; 249 let conferRecordSendPdu = new pdu['RCConferenceRecordRequestPdu'];
251 conferRecordSendPdu.type = pdu.RCPDU_CONFERENCE_RECORD_REQUEST; 250 conferRecordSendPdu.type = pdu.RCPDU_CONFERENCE_RECORD_REQUEST;
252 conferRecordSendPdu.peer = 0; //channel 为0 251 conferRecordSendPdu.peer = 0; //channel 为0
@@ -257,9 +256,12 @@ class ConferApe extends Ape { @@ -257,9 +256,12 @@ class ConferApe extends Ape {
257 //conferRecordSendPdu.classTime = GlobalConfig.classTimestamp;//不能使用课堂进行时间,这个时间结束课堂的时候会被清除 256 //conferRecordSendPdu.classTime = GlobalConfig.classTimestamp;//不能使用课堂进行时间,这个时间结束课堂的时候会被清除
258 conferRecordSendPdu.classTime = GlobalConfig.recordTimestamp; //课堂录制的累积时间,不会被清除 257 conferRecordSendPdu.classTime = GlobalConfig.recordTimestamp; //课堂录制的累积时间,不会被清除
259 conferRecordSendPdu.filename = GlobalConfig.recordFileName || GlobalConfig.classId + "_" + EngineUtils.creatTimestampYMD() + ".rec"; 258 conferRecordSendPdu.filename = GlobalConfig.recordFileName || GlobalConfig.classId + "_" + EngineUtils.creatTimestampYMD() + ".rec";
  259 + if(GlobalConfig.recordStatus){
  260 + loger.log("发送录制的指令->开启",conferRecordSendPdu);
  261 + }else {
  262 + loger.log("发送录制的指令->停止",conferRecordSendPdu);
  263 + }
260 this.sendChatUniform(conferRecordSendPdu); 264 this.sendChatUniform(conferRecordSendPdu);
261 - // to, message  
262 - loger.warn('发送录制消息-》', _param);  
263 } 265 }
264 266
265 //开启录制 267 //开启录制
@@ -270,22 +272,27 @@ class ConferApe extends Ape { @@ -270,22 +272,27 @@ class ConferApe extends Ape {
270 return; 272 return;
271 } 273 }
272 274
273 - loger.warn('开启录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);  
274 - //如果是host  
275 - if (GlobalConfig.isHost) { 275 + //如果是host或者当前课堂只有1个人
  276 + if (GlobalConfig.isHost||this.rosterLen<=1) {
  277 + if(GlobalConfig.recordStatus){
  278 + loger.warn("课堂已经是录制状态不->不需要再开启,isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus,"当前人数:"+this.rosterLen);
  279 + }else{
  280 + loger.warn('开启录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus,"当前人数:"+this.rosterLen);
276 GlobalConfig.classStopTime = EngineUtils.creatTimestampStr(); 281 GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
277 this.sendConferRecordMsg({"recordStatus": true}); 282 this.sendConferRecordMsg({"recordStatus": true});
278 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 283 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
279 this._emit(MessageTypes.CLASS_RECORD_START); //课堂开始录制 284 this._emit(MessageTypes.CLASS_RECORD_START); //课堂开始录制
280 } 285 }
  286 +
  287 + }
281 } 288 }
282 289
283 //停止录制 290 //停止录制
284 stopRecord(isForce) { 291 stopRecord(isForce) {
285 - loger.warn('停止录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);  
286 - if (isForce && isForce == true) { 292 + /* if (isForce && isForce == true) {
287 //强制停止,可以是host之外的身份(比如当前课堂老师异常退出,没有老师,会随机选择一个人来做释放操作) 293 //强制停止,可以是host之外的身份(比如当前课堂老师异常退出,没有老师,会随机选择一个人来做释放操作)
288 if (GlobalConfig.recordStatus) { 294 if (GlobalConfig.recordStatus) {
  295 + loger.warn('停止录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
289 GlobalConfig.classStopTime = EngineUtils.creatTimestampStr(); 296 GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
290 this.sendConferRecordMsg({"recordStatus": false}); 297 this.sendConferRecordMsg({"recordStatus": false});
291 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 298 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
@@ -297,6 +304,15 @@ class ConferApe extends Ape { @@ -297,6 +304,15 @@ class ConferApe extends Ape {
297 this.sendConferRecordMsg({"recordStatus": false}); 304 this.sendConferRecordMsg({"recordStatus": false});
298 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 305 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
299 } 306 }
  307 + }*/
  308 + //身份是host
  309 + if (GlobalConfig.isHost) {
  310 + loger.warn('停止录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
  311 + GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
  312 + this.sendConferRecordMsg({"recordStatus": false});
  313 + this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
  314 + }else {
  315 + loger.warn('没有权限停止录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
300 } 316 }
301 } 317 }
302 318
@@ -339,9 +355,10 @@ class ConferApe extends Ape { @@ -339,9 +355,10 @@ class ConferApe extends Ape {
339 GlobalConfig.classTimestamp = 0; 355 GlobalConfig.classTimestamp = 0;
340 GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_WAIT; 356 GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_WAIT;
341 GlobalConfig.classStopTime = EngineUtils.creatTimestampStr(); 357 GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
342 - this.stopRecord(); 358 + //this.stopRecord();//停止录制的接口单独调用
343 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 359 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
344 - this.sendUpdaterClassStatusInfo({"actionType": 0, isStopAllPublishMedia: true}); 360 + //this.sendUpdaterClassStatusInfo({"actionType": 0, isStopAllPublishMedia: true});
  361 + this.sendUpdaterClassStatusInfo({"actionType": ApeConsts.CLASS_STATUS_WAIT, isStopAllPublishMedia: false});
345 loger.log('restorClass'); 362 loger.log('restorClass');
346 } 363 }
347 364
@@ -376,7 +393,6 @@ class ConferApe extends Ape { @@ -376,7 +393,6 @@ class ConferApe extends Ape {
376 //开始上课 393 //开始上课
377 startClass(_param) { 394 startClass(_param) {
378 if (GlobalConfig.isHost) { 395 if (GlobalConfig.isHost) {
379 -  
380 let timestamp = EngineUtils.creatTimestampStr(); 396 let timestamp = EngineUtils.creatTimestampStr();
381 GlobalConfig.classStopTime = timestamp; 397 GlobalConfig.classStopTime = timestamp;
382 398
@@ -391,13 +407,13 @@ class ConferApe extends Ape { @@ -391,13 +407,13 @@ class ConferApe extends Ape {
391 } 407 }
392 408
393 GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_STARTED; 409 GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_STARTED;
394 - //开始录制  
395 - this.startRecord();  
396 - //课堂状态改变  
397 - this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 410 + ////开始录制
  411 + //this.startRecord();
  412 + ////课堂状态改变
  413 + //this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
398 //同步课堂状态 414 //同步课堂状态
399 - this.sendUpdaterClassStatusInfo({"actionType": 1, isStopAllPublishMedia: true});  
400 - 415 + //this.sendUpdaterClassStatusInfo({"actionType": 1, isStopAllPublishMedia: true});
  416 + this.sendUpdaterClassStatusInfo({"actionType": ApeConsts.CLASS_STATUS_STARTED, isStopAllPublishMedia: false});
401 //开始计时 417 //开始计时
402 this.startTimerCounter(); 418 this.startTimerCounter();
403 } else { 419 } else {
@@ -414,9 +430,10 @@ class ConferApe extends Ape { @@ -414,9 +430,10 @@ class ConferApe extends Ape {
414 GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_PAUSE; 430 GlobalConfig.classStatus = ApeConsts.CLASS_STATUS_PAUSE;
415 GlobalConfig.classStopTime = EngineUtils.creatTimestampStr(); 431 GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
416 432
417 - this.stopRecord(); 433 + //this.stopRecord();
418 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE, _param); 434 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE, _param);
419 - this.sendUpdaterClassStatusInfo({"actionType": 2, isStopAllPublishMedia: true}); 435 + //this.sendUpdaterClassStatusInfo({"actionType": 2, isStopAllPublishMedia: true});
  436 + this.sendUpdaterClassStatusInfo({"actionType": ApeConsts.CLASS_STATUS_PAUSE, isStopAllPublishMedia: false});
420 this.stopTimerCounter(); 437 this.stopTimerCounter();
421 } 438 }
422 439
@@ -426,11 +443,12 @@ class ConferApe extends Ape { @@ -426,11 +443,12 @@ class ConferApe extends Ape {
426 loger.warn('还没有开始,不能点关闭'); 443 loger.warn('还没有开始,不能点关闭');
427 return; 444 return;
428 } 445 }
429 - 446 + loger.warn("调用关闭课堂->");
430 this.stopTimerCounter(); 447 this.stopTimerCounter();
431 this.restorClass(); 448 this.restorClass();
432 //把所有人都踢出课堂 449 //把所有人都踢出课堂
433 this.sendConferMsg({"to": 0, "message": "所有人退出课堂", "actionType": ApeConsts.CLASS_ACTION_CLOSE_ALL}); 450 this.sendConferMsg({"to": 0, "message": "所有人退出课堂", "actionType": ApeConsts.CLASS_ACTION_CLOSE_ALL});
  451 + this.stopRecord();//关闭课堂的时候停止录制
434 } 452 }
435 453
436 //更新设备信息 454 //更新设备信息
@@ -525,7 +543,7 @@ class ConferApe extends Ape { @@ -525,7 +543,7 @@ class ConferApe extends Ape {
525 //保存数据到Sass 543 //保存数据到Sass
526 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 544 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
527 //同步消息给其他人 545 //同步消息给其他人
528 - this.sendUpdaterClassStatusInfo({"actionType": 1, isStopAllPublishMedia: false}); 546 + this.sendUpdaterClassStatusInfo({"actionType": ApeConsts.CLASS_STATUS_STARTED, isStopAllPublishMedia: false});
529 } 547 }
530 } 548 }
531 549
@@ -542,7 +560,6 @@ class ConferApe extends Ape { @@ -542,7 +560,6 @@ class ConferApe extends Ape {
542 } 560 }
543 let itemIdx = ApeConsts.CONFERENCE_OBJ_TABLE_ID; // itemIdx=_param.itemIdx; 561 let itemIdx = ApeConsts.CONFERENCE_OBJ_TABLE_ID; // itemIdx=_param.itemIdx;
544 let modelPdu = this.packPdu(_param, itemIdx); 562 let modelPdu = this.packPdu(_param, itemIdx);
545 - loger.log(modelPdu);  
546 if (modelPdu == null) { 563 if (modelPdu == null) {
547 loger.log('发送更新课堂信息->参数错误'); 564 loger.log('发送更新课堂信息->参数错误');
548 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); 565 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
@@ -582,14 +599,32 @@ class ConferApe extends Ape { @@ -582,14 +599,32 @@ class ConferApe extends Ape {
582 /////收到消息处理///////////////////////////////////////////////////////////////////////////////// 599 /////收到消息处理/////////////////////////////////////////////////////////////////////////////////
583 //加入channel成功 600 //加入channel成功
584 onJoinChannelHandlerSuccess() { 601 onJoinChannelHandlerSuccess() {
585 - loger.log('ConferApe.onJoinChannelHandlerSuccess', GlobalConfig.classStatus); 602 + if(GlobalConfig.isRecordPlayBack){
  603 + loger.log('课堂模块初始完成->当前是录制回放:'+ GlobalConfig.classStatus);
  604 + return;
  605 + }
  606 + loger.log('课堂模块初始完成->当前课堂状态:'+ GlobalConfig.classStatus,"recordStatus:"+GlobalConfig.recordStatus);
586 this.timerCounter.addTimerCallBack(this.timerCounterUptate.bind(this), 1); 607 this.timerCounter.addTimerCallBack(this.timerCounterUptate.bind(this), 1);
  608 + //2秒后执行开始上课和开始录制的判断逻辑
  609 + clearTimeout(this.startClassTimer);
  610 + this.startClassTimer=setTimeout(()=>{
  611 + //开启录制,录制接口中会自动判断是否需要录制
  612 + this.startRecord();
587 //如果当前课堂正在进行中,开启计时器 613 //如果当前课堂正在进行中,开启计时器
588 if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) { 614 if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
589 //开始计时 615 //开始计时
590 this.startTimerCounter(); 616 this.startTimerCounter();
  617 + //this.startRecord();
  618 + } else {
  619 + loger.log('自动开始上课->classStatus:', GlobalConfig.classStatus, " isHost:", GlobalConfig.isHost, " isAutoStartClass:", GlobalConfig.isAutoStartClass, " isRecordPlayBack:", GlobalConfig.isRecordPlayBack);
  620 + this.startClass();
  621 + }
  622 + },2000);
591 623
592 - //如果是host ,开始录制 624 + /* //如果当前课堂正在进行中,开启计时器
  625 + if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
  626 + //开始计时
  627 + this.startTimerCounter();
593 this.startRecord(); 628 this.startRecord();
594 } else if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT && 629 } else if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT &&
595 GlobalConfig.isHost && GlobalConfig.isAutoStartClass && !GlobalConfig.isRecordPlayBack) { 630 GlobalConfig.isHost && GlobalConfig.isAutoStartClass && !GlobalConfig.isRecordPlayBack) {
@@ -597,7 +632,8 @@ class ConferApe extends Ape { @@ -597,7 +632,8 @@ class ConferApe extends Ape {
597 //1.如果自己是host,2.Sass配置的是自动开始上课,3.并且当前是未开始状态,4.当前不是录制回放,开始自动上课 632 //1.如果自己是host,2.Sass配置的是自动开始上课,3.并且当前是未开始状态,4.当前不是录制回放,开始自动上课
598 loger.log('自动开始上课->classStatus:', GlobalConfig.classStatus, " isHost:", GlobalConfig.isHost, " isAutoStartClass:", GlobalConfig.isAutoStartClass, " isRecordPlayBack:", GlobalConfig.isRecordPlayBack); 633 loger.log('自动开始上课->classStatus:', GlobalConfig.classStatus, " isHost:", GlobalConfig.isHost, " isAutoStartClass:", GlobalConfig.isAutoStartClass, " isRecordPlayBack:", GlobalConfig.isRecordPlayBack);
599 this.startClass(); 634 this.startClass();
600 - } 635 + }*/
  636 +
601 } 637 }
602 638
603 //开启计时器 639 //开启计时器
@@ -606,7 +642,6 @@ class ConferApe extends Ape { @@ -606,7 +642,6 @@ class ConferApe extends Ape {
606 if (this.timerCounter) { 642 if (this.timerCounter) {
607 this.timerCounter.startTimer(); 643 this.timerCounter.startTimer();
608 } 644 }
609 -  
610 } 645 }
611 646
612 //停止计时器 647 //停止计时器
@@ -621,8 +656,53 @@ class ConferApe extends Ape { @@ -621,8 +656,53 @@ class ConferApe extends Ape {
621 if (!this.mcu.connected) { 656 if (!this.mcu.connected) {
622 loger.warn('MCU 连接已经断开'); 657 loger.warn('MCU 连接已经断开');
623 this.stopTimerCounter(); 658 this.stopTimerCounter();
  659 + return;
624 } 660 }
625 - //如果还没开始或已经暂停、关闭,不做计时处理 661 + //课堂开始的状态下,课堂进行时间和录制时间都需要更加,录制时间会大于或等于课堂开始的累积时间
  662 + if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
  663 + GlobalConfig.classTimestamp = GlobalConfig.classTimestamp + 1; //计时
  664 + //老师身份的时候要记录录制的时间
  665 + if (GlobalConfig.isHost||this.rosterLen<=1) {
  666 + GlobalConfig.recordTimestamp = GlobalConfig.recordTimestamp + 1;
  667 + }
  668 + //向应用层更新当前课堂进行的时间长度 (秒)
  669 + this._emit(MessageTypes.CLASS_UPDATE_TIMER, {"classTimestamp": GlobalConfig.classTimestamp});
  670 +
  671 + //以一定的时间间隔同步课堂内所有人的累积上课时间
  672 + if (GlobalConfig.classTimestamp % GlobalConfig.updateClassInfoDelay == 0) {
  673 + //如果是host身份,需要同步时间给其他人,同时把当前的状态上传到服务器
  674 + if (GlobalConfig.isHost||this.rosterLen<=1) {
  675 + //保存数据到Sass
  676 + this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
  677 + //同步消息给其他人
  678 + this.sendUpdaterClassStatusInfo({"actionType": ApeConsts.CLASS_STATUS_STARTED, isStopAllPublishMedia: false});
  679 + }
  680 + }
  681 +
  682 + //进行MS动态选点,选择最快的MS服务器地址(录制回放不做处理)
  683 + if (!GlobalConfig.isRecordPlayBack && GlobalConfig.classTimestamp % GlobalConfig.msDynamicChooseIpDelay == 0) {
  684 + //MS推流选点
  685 + this._emit(MessageTypes.SWITCH_MS_IP);
  686 + //MS拉流选点
  687 + this._emit(MessageTypes.SWITCH_RTMP_PULL_IP);
  688 + //HLS拉流选点
  689 + this._emit(MessageTypes.SWITCH_HLS_IP);
  690 + }
  691 + }else {
  692 + //课堂暂停或未开始的情况下,如果已经开始录制,需要更新录制的时间
  693 + if (GlobalConfig.isHost||this.rosterLen<=1) {
  694 + GlobalConfig.recordTimestamp = GlobalConfig.recordTimestamp + 1;
  695 + //以一定的时间间隔同步课堂内所有人的累积上课时间
  696 + if (GlobalConfig.classTimestamp % GlobalConfig.updateClassInfoDelay == 0) {
  697 + //保存数据到Sass
  698 + this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
  699 + //同步消息给其他人
  700 + this.sendUpdaterClassStatusInfo({"actionType": ApeConsts.CLASS_STATUS_STARTED, isStopAllPublishMedia: false});
  701 + }
  702 + }
  703 + }
  704 +
  705 + /* //如果还没开始或已经暂停、关闭,不做计时处理
626 if (GlobalConfig.classStatus != ApeConsts.CLASS_STATUS_STARTED) { 706 if (GlobalConfig.classStatus != ApeConsts.CLASS_STATUS_STARTED) {
627 loger.warn('当前课堂已经暂停或者未开始,不计时', "classStatus-->", GlobalConfig.classStatus); 707 loger.warn('当前课堂已经暂停或者未开始,不计时', "classStatus-->", GlobalConfig.classStatus);
628 return; 708 return;
@@ -633,17 +713,17 @@ class ConferApe extends Ape { @@ -633,17 +713,17 @@ class ConferApe extends Ape {
633 if (GlobalConfig.isHost) { 713 if (GlobalConfig.isHost) {
634 GlobalConfig.recordTimestamp = GlobalConfig.recordTimestamp + 1; 714 GlobalConfig.recordTimestamp = GlobalConfig.recordTimestamp + 1;
635 } 715 }
636 - //loger.log('课堂进行时间',GlobalConfig.classTimestamp); 716 + //向应用层更新当前课堂进行的时间长度 (秒)
637 this._emit(MessageTypes.CLASS_UPDATE_TIMER, {"classTimestamp": GlobalConfig.classTimestamp}); 717 this._emit(MessageTypes.CLASS_UPDATE_TIMER, {"classTimestamp": GlobalConfig.classTimestamp});
638 718
  719 + //以一定的时间间隔同步课堂内所有人的累积上课时间
639 if (GlobalConfig.classTimestamp % GlobalConfig.updateClassInfoDelay == 0) { 720 if (GlobalConfig.classTimestamp % GlobalConfig.updateClassInfoDelay == 0) {
640 //如果是host身份,需要同步时间给其他人,同时把当前的状态上传到服务器 721 //如果是host身份,需要同步时间给其他人,同时把当前的状态上传到服务器
641 if (GlobalConfig.isHost) { 722 if (GlobalConfig.isHost) {
642 //保存数据到Sass 723 //保存数据到Sass
643 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); 724 this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
644 -  
645 //同步消息给其他人 725 //同步消息给其他人
646 - this.sendUpdaterClassStatusInfo({"actionType": 1, isStopAllPublishMedia: false}); 726 + this.sendUpdaterClassStatusInfo({"actionType": ApeConsts.CLASS_STATUS_STARTED, isStopAllPublishMedia: false});
647 } 727 }
648 } 728 }
649 729
@@ -655,12 +735,13 @@ class ConferApe extends Ape { @@ -655,12 +735,13 @@ class ConferApe extends Ape {
655 this._emit(MessageTypes.SWITCH_RTMP_PULL_IP); 735 this._emit(MessageTypes.SWITCH_RTMP_PULL_IP);
656 //HLS拉流选点 736 //HLS拉流选点
657 this._emit(MessageTypes.SWITCH_HLS_IP); 737 this._emit(MessageTypes.SWITCH_HLS_IP);
658 - } 738 + }*/
659 } 739 }
660 740
661 tableUpdateHandler(owner, itemIdx, itemData) { 741 tableUpdateHandler(owner, itemIdx, itemData) {
662 try { 742 try {
663 let model = this.unPackPdu(owner, itemIdx, itemData); 743 let model = this.unPackPdu(owner, itemIdx, itemData);
  744 + loger.log("课堂更新->",model);
664 //处理课堂更新的信息 745 //处理课堂更新的信息
665 if (model && model.classStatusInfo) { 746 if (model && model.classStatusInfo) {
666 try { 747 try {
@@ -668,9 +749,7 @@ class ConferApe extends Ape { @@ -668,9 +749,7 @@ class ConferApe extends Ape {
668 } catch (err) { 749 } catch (err) {
669 750
670 } 751 }
671 -  
672 GlobalConfig.setClassStatusInfo(model.classStatusInfo); 752 GlobalConfig.setClassStatusInfo(model.classStatusInfo);
673 -  
674 if (model.classStatusInfo.isStopAllPublishMedia) { 753 if (model.classStatusInfo.isStopAllPublishMedia) {
675 //课堂状态发送改变 需要对当前正在推的流进行停止,因为录制的问题; 754 //课堂状态发送改变 需要对当前正在推的流进行停止,因为录制的问题;
676 this._emit(MessageTypes.STOP_ALL_MEDIA_PUBLISH); 755 this._emit(MessageTypes.STOP_ALL_MEDIA_PUBLISH);
@@ -697,16 +776,11 @@ class ConferApe extends Ape { @@ -697,16 +776,11 @@ class ConferApe extends Ape {
697 this.stopTimerCounter(); 776 this.stopTimerCounter();
698 } 777 }
699 } catch (err) { 778 } catch (err) {
700 - loger.warn('ConferApe table update got exception->err', err.message); 779 + loger.warn('课堂更新->error', err.message);
701 } 780 }
702 } 781 }
703 782
704 conferMsgComingHandler(_data) { 783 conferMsgComingHandler(_data) {
705 - //flash RCConferenceSendDataRequestPdu  
706 - //loger.warn('conferMsgComingHandler needs to be handled.');  
707 - //const recordInfo = pdu['RCWhiteboardDataRequestPdu'].decode(pdu);  
708 - //loger.log("conferMsgComingHandler",recordInfo);  
709 -  
710 let chatReceivePdu = pdu['RCConferenceSendDataRequestPdu'].decode(_data); 784 let chatReceivePdu = pdu['RCConferenceSendDataRequestPdu'].decode(_data);
711 785
712 let chatMsg = {}; 786 let chatMsg = {};
@@ -823,19 +897,26 @@ class ConferApe extends Ape { @@ -823,19 +897,26 @@ class ConferApe extends Ape {
823 897
824 //------------------第三方消息 end----------------------------------------- 898 //------------------第三方消息 end-----------------------------------------
825 899
  900 + //监听MCU录制状态消息
826 onSendConferRecordRequestHandler(_data) { 901 onSendConferRecordRequestHandler(_data) {
827 try { 902 try {
828 let conferRecordSendPdu = pdu['RCConferenceRecordRequestPdu'].decode(_data); 903 let conferRecordSendPdu = pdu['RCConferenceRecordRequestPdu'].decode(_data);
829 - // {"initiator":820461225,"record":false,"classTime":3213,"filename":"h5dev/20170410/1437784290_20170410.rec"}  
830 - loger.log("录制回放控制操作成功->", conferRecordSendPdu);  
831 - if (conferRecordSendPdu && conferRecordSendPdu.record == true || conferRecordSendPdu.record == "true") { 904 + //{"initiator":564398684,"record":true,"classTime":39,"filename":"markettest/20170823/1096250804_20170823.rec"}//开启成功
  905 + //{"initiator":564398684,"record":false,"classTime":39,"filename":"markettest/20170823/1096250804_20170823.rec"} //停止成功
  906 + loger.warn("录制回放控制操作成功->", conferRecordSendPdu);
  907 + if (conferRecordSendPdu ){
  908 + if(conferRecordSendPdu.record == true || conferRecordSendPdu.record == "true") {
832 //每次开启录制的时候,需要把当前显示的文档数据更新一次,否则无法录制已经显示的文件 909 //每次开启录制的时候,需要把当前显示的文档数据更新一次,否则无法录制已经显示的文件
  910 + loger.warn("MCU已经开启录制");
833 this._emit(MessageTypes.CLASS_RECORD_SUCCESS); 911 this._emit(MessageTypes.CLASS_RECORD_SUCCESS);
  912 + }else{
  913 + //停止录制成功
  914 + loger.warn("MCU已经停止录制");
  915 + }
834 } 916 }
835 } catch (err) { 917 } catch (err) {
836 - loger.warn("录制回放控制操作错误->", err.message); 918 + loger.error("录制回放控制操作错误->", err.message);
837 } 919 }
838 -  
839 } 920 }
840 921
841 rosterInsertHandler(nodeId, nodeData) { 922 rosterInsertHandler(nodeId, nodeData) {
@@ -858,10 +939,10 @@ class ConferApe extends Ape { @@ -858,10 +939,10 @@ class ConferApe extends Ape {
858 // 1.当前课堂只有自己;2.自己的身份不是host;3当前的课堂状态为(CLASS_STATUS_STARTED= 1;//直播中) 939 // 1.当前课堂只有自己;2.自己的身份不是host;3当前的课堂状态为(CLASS_STATUS_STARTED= 1;//直播中)
859 this.rosterLen = Object.keys(this.rosters).length; 940 this.rosterLen = Object.keys(this.rosters).length;
860 GlobalConfig.rosterNumber = this.rosterLen;//记录当前的总人数 941 GlobalConfig.rosterNumber = this.rosterLen;//记录当前的总人数
861 - if (this.rosterLen < 1 && !GlobalConfig.isHost && GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) { 942 + if (this.rosterLen <=1 && !GlobalConfig.isHost && GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
862 loger.warn("当前课堂没有老师->暂停课堂"); 943 loger.warn("当前课堂没有老师->暂停课堂");
863 this.pauseClass({isForce: true}); 944 this.pauseClass({isForce: true});
864 - this.stopRecord(true); 945 + //this.stopRecord(true);
865 } 946 }
866 //处理用户信息 947 //处理用户信息
867 this.unPackRosterInfo(nodeId, nodeData); 948 this.unPackRosterInfo(nodeId, nodeData);
@@ -882,10 +963,11 @@ class ConferApe extends Ape { @@ -882,10 +963,11 @@ class ConferApe extends Ape {
882 deviceType: nodeData.deviceType 963 deviceType: nodeData.deviceType
883 } 964 }
884 if (nodeData.role == ApeConsts.NR_HOST && GlobalConfig.isHost) { 965 if (nodeData.role == ApeConsts.NR_HOST && GlobalConfig.isHost) {
  966 + loger.warn("相同身份的人进入->自己被踢出->进入的人员信息", nodeData);
885 this.kickOutRoster(newUserInfo); 967 this.kickOutRoster(newUserInfo);
886 return; 968 return;
887 } else if (nodeData.userId == GlobalConfig.userId && GlobalConfig.userId != "0") { 969 } else if (nodeData.userId == GlobalConfig.userId && GlobalConfig.userId != "0") {
888 - loger.log("异地登陆->userId->", GlobalConfig.userId); 970 + loger.warn("异地登陆->userId->", GlobalConfig.userId);
889 this._emit(MessageTypes.MCU_ERROR, {type:MessageTypes.ERR_CLASS_REMOTE_LANDING, data:newUserInfo}); 971 this._emit(MessageTypes.MCU_ERROR, {type:MessageTypes.ERR_CLASS_REMOTE_LANDING, data:newUserInfo});
890 this._emit(MessageTypes.CLASS_RUN_EXIT, {'type': 1}); 972 this._emit(MessageTypes.CLASS_RUN_EXIT, {'type': 1});
891 } 973 }
@@ -929,14 +1011,14 @@ class ConferApe extends Ape { @@ -929,14 +1011,14 @@ class ConferApe extends Ape {
929 newNodeData.userData = userDataObj; 1011 newNodeData.userData = userDataObj;
930 //如果是监课,不告诉其他人 1012 //如果是监课,不告诉其他人
931 if (nodeData.role == ApeConsts.NR_INVISIBLE && GlobalConfig.userRole != ApeConsts.invisible) { 1013 if (nodeData.role == ApeConsts.NR_INVISIBLE && GlobalConfig.userRole != ApeConsts.invisible) {
932 - loger.log("NR_INVISIBLE"); 1014 + loger.log("监课进入或更新数据");
933 return; 1015 return;
934 } 1016 }
935 if (!rosterExists) { 1017 if (!rosterExists) {
936 this.rosterLen = Object.keys(this.rosters).length; 1018 this.rosterLen = Object.keys(this.rosters).length;
937 GlobalConfig.rosterNumber = this.rosterLen;//记录当前的总人数 1019 GlobalConfig.rosterNumber = this.rosterLen;//记录当前的总人数
938 newNodeData.rosterLen = this.rosterLen; 1020 newNodeData.rosterLen = this.rosterLen;
939 - //loger.log("人员加入->", newNodeData); 1021 + loger.log("人员加入->", newNodeData);
940 this._emit(MessageTypes.CLASS_INSERT_ROSTER, {"nodeId": nodeId, "nodeData": newNodeData}); 1022 this._emit(MessageTypes.CLASS_INSERT_ROSTER, {"nodeId": nodeId, "nodeData": newNodeData});
941 this.emitRosterChange(); 1023 this.emitRosterChange();
942 } else { 1024 } else {
@@ -944,7 +1026,9 @@ class ConferApe extends Ape { @@ -944,7 +1026,9 @@ class ConferApe extends Ape {
944 this.rosterLen = Object.keys(this.rosters).length; 1026 this.rosterLen = Object.keys(this.rosters).length;
945 GlobalConfig.rosterNumber = this.rosterLen;//记录当前的总人数 1027 GlobalConfig.rosterNumber = this.rosterLen;//记录当前的总人数
946 newNodeData.rosterLen = this.rosterLen; 1028 newNodeData.rosterLen = this.rosterLen;
  1029 + if(nodeId!=GlobalConfig.nodeId){
947 loger.log("人员更新信息->", newNodeData); 1030 loger.log("人员更新信息->", newNodeData);
  1031 + }
948 this._emit(MessageTypes.CLASS_UPDATE_ROSTER, {"nodeId": nodeId, "nodeData": newNodeData}); 1032 this._emit(MessageTypes.CLASS_UPDATE_ROSTER, {"nodeId": nodeId, "nodeData": newNodeData});
949 } 1033 }
950 } 1034 }
@@ -970,33 +1054,6 @@ class ConferApe extends Ape { @@ -970,33 +1054,6 @@ class ConferApe extends Ape {
970 loger.log("媒体模块被占用->占有人已经不存在课堂中->释放->", _param); 1054 loger.log("媒体模块被占用->占有人已经不存在课堂中->释放->", _param);
971 this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": _param.fromNodeId}); 1055 this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": _param.fromNodeId});
972 } 1056 }
973 -  
974 - /* if (_param && _param.status == ApeConsts.CHANNEL_STATUS_OPENING) {  
975 - if(this.rosters[_param.fromNodeId] == null){  
976 - loger.log("媒体模块被占用,占有人已经不存在课堂中,释放Channel,_param->", _param);  
977 - this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": _param.fromNodeId});  
978 - }  
979 -  
980 - //如果音视频消息是自己的,需要设置麦克风和摄像头状态  
981 - if(_param.fromNodeId==GlobalConfig.nodeId){  
982 - if(_param.mediaId==ApeConsts.MEDIA_TYPE_AUDIO){  
983 - GlobalConfig.openMicrophones=EngineUtils.creatTimestamp();  
984 - GlobalConfig.openCamera=0;  
985 - }else {  
986 - GlobalConfig.openCamera=EngineUtils.creatTimestamp();  
987 - GlobalConfig.openMicrophones=GlobalConfig.openCamera;  
988 - }  
989 - this.updateUserInfo();  
990 - }  
991 -  
992 - }else if (_param && _param.status == ApeConsts.CHANNEL_STATUS_RELEASED) {  
993 - //如果音视频消息是自己的,需要设置麦克风和摄像头状态  
994 - if(_param.fromNodeId==GlobalConfig.nodeId){  
995 - GlobalConfig.openCamera=0;  
996 - GlobalConfig.openMicrophones=0;  
997 - this.updateUserInfo();  
998 - }  
999 - }*/  
1000 } 1057 }
1001 1058
1002 //设备状态更新 1059 //设备状态更新
@@ -1034,8 +1091,10 @@ class ConferApe extends Ape { @@ -1034,8 +1091,10 @@ class ConferApe extends Ape {
1034 1091
1035 if (user && user.role == ApeConsts.NR_HOST) { 1092 if (user && user.role == ApeConsts.NR_HOST) {
1036 this.pauseClass(); 1093 this.pauseClass();
1037 - //强制停止录制  
1038 - this.stopRecord(true); 1094 +
  1095 + /* //强制停止录制
  1096 + this.stopRecord(true)*/;
  1097 +
1039 } 1098 }
1040 } else { 1099 } else {
1041 loger.warn(GlobalConfig.nodeId, "没有权限检查离开的人员是否占用channel"); 1100 loger.warn(GlobalConfig.nodeId, "没有权限检查离开的人员是否占用channel");
@@ -1080,7 +1139,7 @@ class ConferApe extends Ape { @@ -1080,7 +1139,7 @@ class ConferApe extends Ape {
1080 classStatusInfo.serverTimestamp = GlobalConfig.serverTimestamp; //当前的系统时间戳 1139 classStatusInfo.serverTimestamp = GlobalConfig.serverTimestamp; //当前的系统时间戳
1081 classStatusInfo.activeDocId = GlobalConfig.activeDocId; //当前激活的文档id 1140 classStatusInfo.activeDocId = GlobalConfig.activeDocId; //当前激活的文档id
1082 classStatusInfo.activeDocCurPage = GlobalConfig.activeDocCurPage; //当前激活的文档的当前页 1141 classStatusInfo.activeDocCurPage = GlobalConfig.activeDocCurPage; //当前激活的文档的当前页
1083 - classStatusInfo.isStopAllPublishMedia = _param.isStopAllPublishMedia || false; 1142 + classStatusInfo.isStopAllPublishMedia = Boolean(_param.isStopAllPublishMedia) || false;
1084 classStatusInfo.currentSceneTableId = GlobalConfig.currentSceneTableId; 1143 classStatusInfo.currentSceneTableId = GlobalConfig.currentSceneTableId;
1085 classStatusInfo.silence = GlobalConfig.silence; 1144 classStatusInfo.silence = GlobalConfig.silence;
1086 classStatusInfo.silenceUsers = JSON.stringify(GlobalConfig.silenceUsers); 1145 classStatusInfo.silenceUsers = JSON.stringify(GlobalConfig.silenceUsers);
1 -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.share=t():e.share=t()}(this,function(){return function(e){function t(n){if(_[n])return _[n].exports;var a=_[n]={exports:{},id:n,loaded:!1};return e[n].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var _={};return t.m=e,t.c=_,t.p="",t(0)}([function(e,t,_){e.exports=_(2)},function(e,t){"use strict";function _(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var n=function(){function e(e,t){for(var _=0;_<t.length;_++){var n=t[_];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,_,n){return _&&e(t.prototype,_),n&&e(t,n),t}}(),a=function(){function e(){_(this,e),this.MAPS={}}return n(e,[{key:"on",value:function(e,t){if(e&&t){var _=this.MAPS[e];if(!_)return this.MAPS[e]=[t];_.push(t)}}},{key:"off",value:function(e,t){if(e){var _=this.MAPS[e];if(_){if(t)return _.splice(_.indexOf(t),1);_.length=0}}}},{key:"emit",value:function(e,t){if(e){var _=this.MAPS["*"];_&&_.length&&_.forEach(function(_){_(e,t)});var n=this.MAPS[e];n&&n.length&&n.forEach(function(e){e(t)})}}}]),e}();t.default=a},function(e,t,_){"use strict";function n(e){return e&&e.__esModule?e:{default:e}}function a(e){var t,_,n,a;n=e.length,t=new Uint8Array(3*n);var r=0;for(_=0;_<n;_++)a=e.charCodeAt(_),a>=1&&a<=127?t[r++]=a:a>2047?(t[r++]=224|a>>12&15,t[r++]=128|a>>6&63,t[r++]=128|a>>0&63):(t[r++]=192|a>>6&31,t[r++]=128|a>>0&63);return new Uint8Array(t.buffer,0,r)}function r(e){var t,_,n,a,r,o;for(t="",n=e.length,_=0;_<n;)switch(a=e[_++],a>>4){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:t+=String.fromCharCode(a);break;case 12:case 13:r=e[_++],t+=String.fromCharCode((31&a)<<6|63&r);break;case 14:r=e[_++],o=e[_++],t+=String.fromCharCode((15&a)<<12|(63&r)<<6|(63&o)<<0)}return t}function o(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",_=new Object;if(_.data_len=0,_.data="",_.name=e,"mov_start"==e)_.type=1;else if("mov_stop"==e)_.type=2;else if("mov_pause"==e){if(_.type=3,pos=t,pos.length>0){_.data_len=4;var n=new ArrayBuffer(_.data_len),r=new Uint32Array(n,0,1);r[0]=parseInt(pos),_.data=new Uint8Array(n,0,4)}}else if("mov_resume"==e)_.type=4;else if("mov_seek"==e){if(_.type=5,pos=t,pos.length>0){_.data_len=4;var n=new ArrayBuffer(_.data_len),r=new Uint32Array(n,0,1);r[0]=parseInt(pos),_.data=new Uint8Array(n,0,4)}}else if("ss_start"==e)_.type=6,_.data=a(t),_.data_len=_.data.length;else if("ss_stop"==e)_.type=7;else if("ss_version"==e)_.type=14;else if("get_mic"==e)_.type=26;else{if("ds_start"==e){_.type=27,_.data_len=536;var n=new ArrayBuffer(_.data_len),o=new Uint32Array(n,0,6);coordstr=t;var i=coordstr.split(",");if(4!=i.length)return;o[0]=parseInt(i[0]),o[1]=parseInt(i[1]),o[2]=parseInt(i[2]),o[3]=parseInt(i[3]);var s=new Uint8Array(n,24,256);window_name=t;for(var S=a(window_name),E=0;E<S.length;E++)s[E]=S[E];o[4]=S.length,o[5]=0;new Uint8Array(n,280,256);return _.data=new Uint8Array(n,0,_.data_len),void A(_)}if("ds_stop"==e)_.type=28;else{if("aud_start"==e){_.type=29,_.data_len=520;var n=new ArrayBuffer(_.data_len),l=new Uint32Array(n,0,1),C=t;l[0]=C.length;var f=new Uint32Array(n,4,1);f[0]=0;for(var c=new Uint8Array(n,8,256),O=a(C),E=0;E<O.length;E++)c[E]=O[E];new Uint8Array(n,264,256);return _.data=new Uint8Array(n,0,_.data_len),void A(_)}if("aud_stop"==e)_.type=30;else if("get_cam"==e)_.type=41;else{if("cam_start"==e){_.type=42,_.data_len=520;var n=new ArrayBuffer(_.data_len),I=new Uint32Array(n,0,1),T=t;I[0]=T.length;var f=new Uint32Array(n,4,1);f[0]=0;for(var U=new Uint8Array(n,8,256),u=a(T),E=0;E<u.length;E++)U[E]=u[E];new Uint8Array(n,264,256);return _.data=new Uint8Array(n,0,_.data_len),void A(_)}"cam_stop"==e?_.type=43:"set_videoparam"==e?(_.type=46,_.data=a(t),_.data_len=_.data.length):"get_videoparam"==e?(_.type=47,_.data=a(t),_.data_len=_.data.length):"start_record"==e?(_.type=48,_.data=a(t),_.data_len=_.data.length):"stop_record"==e?(_.type=49,_.data=a(t),_.data_len=_.data.length):"start_push"==e?(_.type=50,_.data=a(t),_.data_len=_.data.length):"stop_push"==e?(_.type=51,_.data=a(t),_.data_len=_.data.length):"get_rtmp_port"==e?_.type=52:"set_mic_vol"==e?(_.type=53,_.data=a(t),_.data_len=_.data.length):"get_mic_vol"==e&&(_.type=54)}}}A(_)}function A(e){var t=8+e.data_len,_=new ArrayBuffer(t),n=new Uint16Array(_,0,1),a=new Uint8Array(_,2,1),r=new Uint32Array(_,4,1);if(n[0]=e.type,a[0]=0,r[0]=e.data_len,e.data_len>0)for(var o=new Uint8Array(_,8,e.data_len),A=0;A<e.data_len;A++)o[A]=e.data[A];R&&R.send(_)}function i(){try{R&&(R.close(),R=R.onopen=R.onclose=R.onerror=R.onmessage=null,C.emit(C.CLOSE))}catch(e){console.log(e)}}function s(){i()}function S(){R&&i(),R=new WebSocket("ws://"+p+":"+L),g=setTimeout(function(){clearTimeout(g),i()},1500),R.timeout=1500,R.binaryType="arraybuffer",R.onopen=function(){clearTimeout(g),o("get_rtmp_port"),o("get_mic"),o("get_cam"),o("get_mic_vol"),C.emit(C.OPEN)},R.onclose=function(){i()},R.onerror=function(){i()},R.onmessage=function(e){var t=e.data;if("string"==typeof e.data)console.log("on message [string] ignore.");else{var _=new DataView(t),n=_.getUint16(0,!0);console.log("onmessage code->",n);var a=(_.getUint8(2,!0),_.getUint32(4,!0));if(n>=0&&n<f.length){f[n]}if(0==n||6==n||8==n)console.log("mov_start,mov_pause,mov_seek success");else if(10==n){if(a>36){var o=new Uint32Array(t,8,8),A="width:"+o[0]+" height:"+o[1];A="framerate:"+o[2]+" duration:"+o[3],A="playpos:"+o[4]+" filesize:"+o[5],c=A;var i=o[6],s=new Uint8Array(t,40,i),S=r(s);c.filename=S,C.emit(C.MOVIE_INFO_CHANGE,c)}}else if(11==n)console.log("ss_start success"),C.emit(C.SS_START);else if(24<=n&&26>=n){if(a>=4){var E=_.getUint32(8,!0);O=E.toString(),C.emit(C.VERSION_INFO_CHANGE,O)}}else if(55==n)console.log("ds_start success");else if(59==n)console.log("as start success");else if(83==n){if(console.log("get camera sucess"),a>4){var l=_.getUint32(8,!0),R=12;I.length=0;for(var p=0;p<l;p++){var L=_.getUint32(R,!0);R+=4;var g=new Uint8Array(t,R,L-1);R+=L;var y=r(g);I.push(y)}C.emit(C.CAMERA_INFO_CHANGE,I)}}else if(53==n){if(a>4){var v=_.getUint32(8,!0),R=12;T.length=0;for(var p=0;p<v;p++){var M=_.getUint32(R,!0);R+=4;var P=new Uint8Array(t,R,M-1);R+=M;var y=r(P);T.push(y)}C.emit(C.MIC_INFO_CHANGE,T)}}else if(85==n)console.log("cam_share success");else if(95==n){console.log("get_videoparam success");var N=new Uint8Array(t,8,t.byteLength-8-1),y=r(N);U=y,C.emit(C.VIDEO_INFO_CHANGE,U)}else if(105==n){console.log("get_rtmp_port_success");var N=new Uint8Array(t,8,t.byteLength-8-1),y=r(N);u=y,C.emit(C.RTMP_PORT_CHANGE,u)}else if(109==n){console.log("get_mic_vol success");var N=new Uint8Array(t,8,t.byteLength-8-1),y=r(N);d=y,C.emit(C.MIC_VOL_CHANGE,d)}else if(111<=n&&114>=n){var N=new Uint8Array(t,8,t.byteLength-8),V=r(N);console.log("url->",V)}else if(13==n)C.emit(C.SS_STOP);else{var N=new Uint8Array(t,8,t.byteLength-8),y=r(N);console.log("data ->",y)}}}}Object.defineProperty(t,"__esModule",{value:!0});var E=_(1),l=n(E),C=new l.default,f=["MOV_START_SUC","MOV_START_FAIL","MOV_STOP_SUC","MOV_STOP_FAIL","MOV_PAUSE_SUC","MOV_PAUSE_FAIL","MOV_RESUME_SUC","MOV_RESUME_FAIL","MOV_SEEK_SUC","MOV_SEEK_FAIL","MOV_PROPERTY","SS_START_SUC","SS_START_FAIL","SS_STOP_SUC","SS_STOP_FAIL","REC_START_SUC","REC_START_FAIL","REC_STOP_SUC","REC_STOP_FAIL","REC_PAUSE_SUC","REC_PAUSE_FAIL","REC_RESUME_SUC","REC_RESUME_FAIL","MOV_PLAY_FINISH","MOV_VERSION","SS_VERSION","REC_VERSION","MOV_SELECT_FILE_CANCEL","QAV_LOGIN_SUC","QAV_LOGIN_FAIL","QAV_LOGOUT_SUC","QAV_LOGOUT_FAIL","QAV_ENTERROOM_SUC","QAV_ENTERROOM_FAIL","QAV_LEAVEROOM_SUC","QAV_LEAVEROOM_FAIL","QAV_OPEN_MIC_SUC","QAV_OPEN_MIC_FAIL","QAV_OPEN_MIC_NODEV","QAV_CLOSE_MIC_SUC","QAV_CLOSE_MIC_FAIL","QAV_CLOSE_MIC_NODEV","QAV_OPEN_PLAYER_SUC","QAV_OPEN_PLAYER_FAIL","QAV_OPEN_PLAYER_NODEV","QAV_CLOSE_PLAYER_SUC","QAV_CLOSE_PLAYER_FAIL","QAV_CLOSE_PLAYER_NODEV","QAV_MUTE_AUDIO_SUC","QAV_MUTE_AUDIO_FAIL","QAV_UNMUTE_AUDIO_SUC","QAV_UNMUTE_AUDIO_FAIL","REC_SAVE_FILE_CANCEL","GET_MIC_SUC","GET_MIC_FAIL","DS_START_SUC","DS_START_FAIL","DS_STOP_SUC","DS_STOP_FAIL","AUD_START_SUC","AUD_START_FAIL","AUD_STOP_SUC","AUD_STOP_FAIL","AUD_DATA","SS_DATA","MOV_DATA","PEN_START_SUC","PEN_START_FAIL","PEN_STOP_SUC","PEN_STOP_FAIL","PEN_VERSION","QAV_DEVICE_SUC","QAV_DEVICE_FAIL","CBD_QUERY_SUC","CBD_QUERY_FAIL","CBD_GET_SUC","CBD_GET_FAIL","FILE_GET_SUC","FILE_GET_FAIL","FILE_SET_SUC","FILE_SET_FAIL","RESTART_SUC","RESTART_FAIL","GET_CAM_SUC","GET_CAM_FAIL","CAM_START_SUC","CAM_START_FAIL","CAM_STOP_SUC","CAM_STOP_FAIL","SWITCH_SCENE_SUC","SWITCH_SCENE_FAIL","PUSH_STREAM_FAIL","SHOW_UI_SUC","SET_VIDEO_PARAM_SUC","SET_VIDEO_PARAM_FAIL","GET_VIDEO_PARAM_SUC","GET_VIDEO_PARAM_FAIL","START_RECORD_SUC","START_RECORD_FAIL","STOP_RECORD_SUC","STOP_RECORD_FAIL","START_PUSH_SUC","START_PUSH_FAIL","STOP_PUSH_SUC","STOP_PUSH_FAIL","GET_RTMP_PORT_SUC","GET_RTMP_PORT_FAIL","SET_MIC_VOL_SUC","SET_MIC_VOL_FAIL","GET_MIC_VOL_SUC","GET_MIC_VOL_FAIL","RTMP_CONNECTING","RTMP_CONNECT_SUC","RTMP_CONNECT_FAIL","RTMP_CONNECT_CLOSED"],c=null,O="",I=[],T=[],U="",u="",d="",R=null,p="127.0.0.1",L=8090,g=0;C.infos={movieInfo:c,versionInfo:O,cameraInfo:I,micInfo:T,videoInfo:U,rtmpPort:u,micVol:d},C.MOVIE_INFO_CHANGE="MOVIE_INFO_CHANGE",C.VERSION_INFO_CHANGE="VERSION_INFO_CHANGE",C.CAMERA_INFO_CHANGE="CAMERA_INFO_CHANGE",C.MIC_INFO_CHANGE="MIC_INFO_CHANGE",C.VIDEO_INFO_CHANGE="VIDEO_INFO_CHANGE",C.RTMP_PORT_CHANGE="RTMP_PORT_CHANGE",C.MIC_VOL_CHANGE="MIC_VOL_CHANGE",C.SS_START="SS_START",C.SS_STOP="SS_STOP",C.OPEN="OPEN",C.CLOSE="CLOSE",C.ERROR="ERROR",C.getRTMPPort=function(){o("get_rtmp_port")},C.getMicInfo=function(){o("get_mic")},C.getCamInfo=function(){o("get_cam")},C.getMicVol=function(){o("get_mic_vol")},C.start=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"127.0.0.1",t=arguments[1];p=e,L=t,S()},C.stop=function(){s()},C.startShareScreen=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";o("ss_start",e)},C.stopShareScreen=function(){o("ss_stop")},t.default=C}])});