李勇

Merge branch 'mcuClientBranch'

@@ -11,6 +11,7 @@ import Loger from 'Loger'; @@ -11,6 +11,7 @@ import Loger from 'Loger';
11 import ConferApe from 'apes/ConferApe'; 11 import ConferApe from 'apes/ConferApe';
12 import ChatApe from 'apes/ChatApe'; 12 import ChatApe from 'apes/ChatApe';
13 import VideoApe from 'apes/VideoApe'; 13 import VideoApe from 'apes/VideoApe';
  14 +import AudioApe from 'apes/AudioApe';
14 import DocApe from 'apes/DocApe'; 15 import DocApe from 'apes/DocApe';
15 import WhiteBoardApe from 'apes/WhiteBoardApe'; 16 import WhiteBoardApe from 'apes/WhiteBoardApe';
16 import EngineUtils from "EngineUtils"; 17 import EngineUtils from "EngineUtils";
@@ -29,6 +30,7 @@ let _mcu ; @@ -29,6 +30,7 @@ let _mcu ;
29 let _confer_ape; 30 let _confer_ape;
30 let _chat_ape; 31 let _chat_ape;
31 let _video_ape; 32 let _video_ape;
  33 +let _audio_ape;
32 let _doc_ape; 34 let _doc_ape;
33 let _whiteboard_ape; 35 let _whiteboard_ape;
34 36
@@ -68,7 +70,7 @@ export default class MessageEntrance extends Emiter { @@ -68,7 +70,7 @@ export default class MessageEntrance extends Emiter {
68 // 底层MCU消息层 70 // 底层MCU消息层
69 _mcu = Mcu; 71 _mcu = Mcu;
70 _mcu.on('*', (type, data) => this._emit(type, data)); 72 _mcu.on('*', (type, data) => this._emit(type, data));
71 - _mcu.on(MessageTypes.CLASS_JOIN_SUCCESS, this._joinClassSuccessHandler.bind(this));//加入MCU会议完成 73 + _mcu.on(MessageTypes.CLASS_JOIN_SUCCESS, this._mcuJoinClassSuccessHandler.bind(this));//加入MCU会议完成
72 74
73 75
74 // 注册所有应用Ape 76 // 注册所有应用Ape
@@ -87,11 +89,14 @@ export default class MessageEntrance extends Emiter { @@ -87,11 +89,14 @@ export default class MessageEntrance extends Emiter {
87 _video_ape.on('*', (type, data) => this._emit(type, data)); 89 _video_ape.on('*', (type, data) => this._emit(type, data));
88 _video_ape.on(MessageTypes.VIDEO_UPDATE, this.videoUpdate.bind(this)); 90 _video_ape.on(MessageTypes.VIDEO_UPDATE, this.videoUpdate.bind(this));
89 91
  92 + _audio_ape= new AudioApe();
  93 + _audio_ape.on('*', (type, data) => this._emit(type, data));
  94 + _audio_ape.on(MessageTypes.AUDIO_UPDATE, this.audioUpdate.bind(this));
  95 +
90 _whiteboard_ape = new WhiteBoardApe(); 96 _whiteboard_ape = new WhiteBoardApe();
91 _whiteboard_ape.on('*', (type, data) => this._emit(type, data)); 97 _whiteboard_ape.on('*', (type, data) => this._emit(type, data));
92 //_whiteboard_ape.on(MessageTypes.WHITEBOARD_ANNOTATION_UPDATE, this.annoUpdateHandler.bind(this)); 98 //_whiteboard_ape.on(MessageTypes.WHITEBOARD_ANNOTATION_UPDATE, this.annoUpdateHandler.bind(this));
93 99
94 -  
95 _doc_ape = new DocApe(); 100 _doc_ape = new DocApe();
96 _doc_ape.on('*', (type, data) => this._emit(type, data)); 101 _doc_ape.on('*', (type, data) => this._emit(type, data));
97 _doc_ape.on(MessageTypes.DOC_UPDATE, this.docUpdateHandler.bind(this)); 102 _doc_ape.on(MessageTypes.DOC_UPDATE, this.docUpdateHandler.bind(this));
@@ -115,13 +120,20 @@ export default class MessageEntrance extends Emiter { @@ -115,13 +120,20 @@ export default class MessageEntrance extends Emiter {
115 this.sendChatMsg = this._sendChatMsg; 120 this.sendChatMsg = this._sendChatMsg;
116 121
117 //videoApe 122 //videoApe
118 - this.getPlayVideoPath = this._getPlayVideoPath;  
119 - this.getPublishVideoPath = this._getPublishVideoPath; 123 + this.getVideoPlayPath = this._getPlayVideoPath;
  124 + this.getVideoPublishPath = this._getPublishVideoPath;
120 this.publishVideo = this._publishVideo; 125 this.publishVideo = this._publishVideo;
121 this.stopPublishVideo = this._stopPublishVideo; 126 this.stopPublishVideo = this._stopPublishVideo;
122 - this.sendVideoCommandMsg=this.sendVideoCommandMsg; 127 + this.sendVideoBroadcastMsg=this.sendVideoCommandMsg;
123 128
124 129
  130 + //audioApe
  131 + this.getAudioPlayPath = this._getPlayAudioPath;
  132 + this.getAudioPublishPath = this._getPublishAudioPath;
  133 + this.publishAudio = this._publishAudio;
  134 + this.stopPublishAudio = this._stopPublishAudio;
  135 + this.sendAudioBroadcastMsg=this.sendAudioCommandMsg;
  136 +
125 //whiteBoradApe 137 //whiteBoradApe
126 this.sendInsertAnnotaion = this._sendInsertAnnotaion; 138 this.sendInsertAnnotaion = this._sendInsertAnnotaion;
127 //this.sendDeleteAnnotaion=this._sendDeleteAnnotaion; 139 //this.sendDeleteAnnotaion=this._sendDeleteAnnotaion;
@@ -174,6 +186,7 @@ export default class MessageEntrance extends Emiter { @@ -174,6 +186,7 @@ export default class MessageEntrance extends Emiter {
174 _onClassStatusInfoChange(_param) { 186 _onClassStatusInfoChange(_param) {
175 this._sassSaveClassStatusInfo(); 187 this._sassSaveClassStatusInfo();
176 } 188 }
  189 +
177 //有人员离开 190 //有人员离开
178 _onClassDeleteRoster(_data){ 191 _onClassDeleteRoster(_data){
179 //{"nodeId":nodeId} 192 //{"nodeId":nodeId}
@@ -184,18 +197,25 @@ export default class MessageEntrance extends Emiter { @@ -184,18 +197,25 @@ export default class MessageEntrance extends Emiter {
184 if(_video_ape){ 197 if(_video_ape){
185 _video_ape.stopPublishVideo(_data); 198 _video_ape.stopPublishVideo(_data);
186 } 199 }
  200 + if(_audio_ape){
  201 + _audio_ape.stopPublishAudio(_data);
  202 + }
187 } 203 }
188 } 204 }
189 205
190 //当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel 206 //当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel
191 //的占用状态导致,对于这种情况,需要释放掉 207 //的占用状态导致,对于这种情况,需要释放掉
192 _onClassNonentityRoster(_param){ 208 _onClassNonentityRoster(_param){
193 - if(_param==null||_param.fromNodeId==null){ 209 + if(_param==null||_param.nodeId==null){
194 loger.warn("onClassNonentityRoster.参数错误") 210 loger.warn("onClassNonentityRoster.参数错误")
195 return; 211 return;
196 } 212 }
  213 + let data={"nodeId":_param.nodeId};
197 if(_video_ape){ 214 if(_video_ape){
198 - _video_ape.stopPublishVideo({"nodeId":_param.fromNodeId}); 215 + _video_ape.stopPublishVideo(data);
  216 + }
  217 + if(_audio_ape){
  218 + _audio_ape.stopPublishAudio(data);
199 } 219 }
200 } 220 }
201 221
@@ -219,12 +239,14 @@ export default class MessageEntrance extends Emiter { @@ -219,12 +239,14 @@ export default class MessageEntrance extends Emiter {
219 return; 239 return;
220 } 240 }
221 loger.log('init', _param); 241 loger.log('init', _param);
  242 +
222 //保存参数 243 //保存参数
223 GlobalConfig.classId = parseInt(_param.classId); 244 GlobalConfig.classId = parseInt(_param.classId);
224 GlobalConfig.portal = _param.portal; 245 GlobalConfig.portal = _param.portal;
225 GlobalConfig.userRole = _param.userRole || ApeConsts.normal; 246 GlobalConfig.userRole = _param.userRole || ApeConsts.normal;
226 GlobalConfig.userId = _param.userId || "0"; 247 GlobalConfig.userId = _param.userId || "0";
227 GlobalConfig.userName=_param.userName || ""; 248 GlobalConfig.userName=_param.userName || "";
  249 +
228 //获取课堂校验信息 250 //获取课堂校验信息
229 if (_sass) { 251 if (_sass) {
230 _sass.getJoinParams(GlobalConfig.getClassInfo()); 252 _sass.getJoinParams(GlobalConfig.getClassInfo());
@@ -253,7 +275,7 @@ export default class MessageEntrance extends Emiter { @@ -253,7 +275,7 @@ export default class MessageEntrance extends Emiter {
253 GlobalConfig.password = _param.password || ""; 275 GlobalConfig.password = _param.password || "";
254 GlobalConfig.hasCamera=(typeof _param.hasCamera=="boolean")? _param.hasCamera:false; 276 GlobalConfig.hasCamera=(typeof _param.hasCamera=="boolean")? _param.hasCamera:false;
255 GlobalConfig.hasMicrophone=(typeof _param.hasMicrophone=="boolean")? _param.hasMicrophone:false; 277 GlobalConfig.hasMicrophone=(typeof _param.hasMicrophone=="boolean")? _param.hasMicrophone:false;
256 - debugger; 278 + //debugger;
257 //开始校验 279 //开始校验
258 if (_sass) { 280 if (_sass) {
259 _sass.passwordAndMd5Checking(GlobalConfig.getClassInfo()); 281 _sass.passwordAndMd5Checking(GlobalConfig.getClassInfo());
@@ -269,13 +291,7 @@ export default class MessageEntrance extends Emiter { @@ -269,13 +291,7 @@ export default class MessageEntrance extends Emiter {
269 GlobalConfig.siteId = _data.siteId || ""; 291 GlobalConfig.siteId = _data.siteId || "";
270 GlobalConfig.classType = _data.meetingType || 0; 292 GlobalConfig.classType = _data.meetingType || 0;
271 293
272 - /*//host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的  
273 - if (GlobalConfig.userRole == "host") {  
274 - GlobalConfig.passwordRequired = true;  
275 - } else {  
276 - GlobalConfig.passwordRequired = _data.passwordRequired || false;  
277 - }  
278 - */ 294 + //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
279 GlobalConfig.passwordRequired = _data.passwordRequired || false;//md5验证的时候需要Sass返回的值,不能更改 295 GlobalConfig.passwordRequired = _data.passwordRequired || false;//md5验证的时候需要Sass返回的值,不能更改
280 296
281 loger.log('SASS平台获取入会验证信息成功.'); 297 loger.log('SASS平台获取入会验证信息成功.');
@@ -303,7 +319,7 @@ export default class MessageEntrance extends Emiter { @@ -303,7 +319,7 @@ export default class MessageEntrance extends Emiter {
303 } 319 }
304 } 320 }
305 321
306 - // 通过SASS平台验证 322 + // 通过SASS平台验证(密码和MD5)
307 _sassJoinSuccessHandler(_data) { 323 _sassJoinSuccessHandler(_data) {
308 //返回值 324 //返回值
309 /* flag 数值型 无 True:成功 325 /* flag 数值型 无 True:成功
@@ -330,42 +346,55 @@ export default class MessageEntrance extends Emiter { @@ -330,42 +346,55 @@ export default class MessageEntrance extends Emiter {
330 "maxAudioChannels": 1, 346 "maxAudioChannels": 1,
331 "h5_mcu_list": "123.56.73.119:7001;123.56.69.230:7001;112.126.80.182:7001" 347 "h5_mcu_list": "123.56.73.119:7001;123.56.69.230:7001;112.126.80.182:7001"
332 }*/ 348 }*/
333 - if (_data.h5_mcu_list) {  
334 - //MCU地址默认使用第一个  
335 - let server = _data.h5_mcu_list.split(";")[0];  
336 - GlobalConfig.MCUServerIP = server.split(":")[0];  
337 - GlobalConfig.MCUServerPort = server.split(":")[1];  
338 - }  
339 -  
340 - //视频推流播流地址  
341 - if (_data.ms) {  
342 - //MS地址默认使用第一个  
343 - let server = _data.ms.split(";")[0];  
344 - GlobalConfig.MSServerIP = server.split(":")[0];  
345 - GlobalConfig.MSServerPort = server.split(":")[1];  
346 - }  
347 -  
348 - //m3u8播流地址  
349 - if(_data.rs){  
350 - //RS地址默认使用第一个  
351 - let server = _data.rs.split(";")[0];  
352 - GlobalConfig.RSServerIP = server.split(":")[0];  
353 - GlobalConfig.RSServerPort = server.split(":")[1];  
354 - }  
355 -  
356 - GlobalConfig.docServer = _data.doc;  
357 - GlobalConfig.h5_mcu_list = _data.h5_mcu_list;  
358 - GlobalConfig.h5Module = _data.h5Module;  
359 - GlobalConfig.mcu = _data.mcu;  
360 - GlobalConfig.ms = _data.ms;  
361 - GlobalConfig.record = _data.record;  
362 - GlobalConfig.rs = _data.rs;  
363 - GlobalConfig.maxVideoChannels = _data.maxVideoChannels;  
364 - GlobalConfig.maxAudioChannels = _data.maxAudioChannels;  
365 - GlobalConfig.maxMediaChannels = _data.maxVideoChannels + _data.maxAudioChannels;  
366 349
  350 + /*
  351 + if (_data.h5_mcu_list) {
  352 + //MCU地址默认使用第一个
  353 + let server = _data.h5_mcu_list.split(";")[0];
  354 + GlobalConfig.MCUServerIP = server.split(":")[0];
  355 + GlobalConfig.MCUServerPort = server.split(":")[1];
  356 + }
  357 +
  358 + //视频推流播流地址
  359 + if (_data.ms) {
  360 + //MS地址默认使用第一个
  361 + let server = _data.ms.split(";")[0];
  362 + GlobalConfig.MSServerIP = server.split(":")[0];
  363 + GlobalConfig.MSServerPort = server.split(":")[1];
  364 + }
  365 +
  366 + //m3u8播流地址
  367 + if(_data.rs){
  368 + //RS地址默认使用第一个
  369 + let server = _data.rs.split(";")[0];
  370 + GlobalConfig.RSServerIP = server.split(":")[0];
  371 + GlobalConfig.RSServerPort = server.split(":")[1];
  372 + }
  373 +
  374 + GlobalConfig.docServer = _data.doc;
  375 + GlobalConfig.h5_mcu_list = _data.h5_mcu_list;
  376 + GlobalConfig.h5Module = _data.h5Module;
  377 + GlobalConfig.mcu = _data.mcu;
  378 + GlobalConfig.ms = _data.ms;
  379 + GlobalConfig.record = _data.record;
  380 + GlobalConfig.rs = _data.rs;
  381 + GlobalConfig.maxVideoChannels = _data.maxVideoChannels;
  382 + GlobalConfig.maxAudioChannels = _data.maxAudioChannels;
  383 +
  384 + */
  385 +
  386 +
  387 + /*
  388 + //这个接口获取的数据在getClassParam接口的数据中都有,内容重复,这个接口废弃
  389 + //获取会议基本信息
  390 + if (_sass) {
  391 + _sass.getClassDetail();
  392 + }
  393 + */
  394 +
  395 + //获取会议最完整的数据
367 if (_sass) { 396 if (_sass) {
368 - _sass.getClassDetail();//会议基本信息 397 + _sass.getClassParam();
369 } 398 }
370 } 399 }
371 400
@@ -398,7 +427,7 @@ export default class MessageEntrance extends Emiter { @@ -398,7 +427,7 @@ export default class MessageEntrance extends Emiter {
398 GlobalConfig.classBeginTime = _data.beginTime || ""; 427 GlobalConfig.classBeginTime = _data.beginTime || "";
399 GlobalConfig.classEndTime = _data.endTime || ""; 428 GlobalConfig.classEndTime = _data.endTime || "";
400 429
401 - //获取会议所有信息和以前保存的会议状态信息 430 + //获取会议所有信息和以前保存的会议状态信息(最全的信息)
402 if (_sass) { 431 if (_sass) {
403 _sass.getClassParam(); 432 _sass.getClassParam();
404 } 433 }
@@ -411,8 +440,15 @@ export default class MessageEntrance extends Emiter { @@ -411,8 +440,15 @@ export default class MessageEntrance extends Emiter {
411 // console.log(_data); 440 // console.log(_data);
412 //包含整个会议最全的信息,储存数据 441 //包含整个会议最全的信息,储存数据
413 if (_data) { 442 if (_data) {
  443 + GlobalConfig.className = _data.meetingName || "";
  444 + GlobalConfig.classBeginTime = _data.beginTime || "";
  445 + GlobalConfig.classEndTime = _data.endTime || "";
  446 +
  447 + GlobalConfig.maxVideoChannels = _data.maxVideoChannels;
  448 + GlobalConfig.maxAudioChannels = _data.maxAudioChannels;
  449 +
414 GlobalConfig.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表 450 GlobalConfig.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表
415 - GlobalConfig.setDocRecordList(_data.docRecordList);//录制回放地址?? 451 + GlobalConfig.setRecordList(_data.recordList);//录制回放地址
416 GlobalConfig.setDocList(_data.docList);//文档地址 452 GlobalConfig.setDocList(_data.docList);//文档地址
417 GlobalConfig.setMsList(_data.msList);//推流播流服务器地址 453 GlobalConfig.setMsList(_data.msList);//推流播流服务器地址
418 GlobalConfig.setRsList(_data.rsList);//播放m3u8格式的地址 454 GlobalConfig.setRsList(_data.rsList);//播放m3u8格式的地址
@@ -421,22 +457,45 @@ export default class MessageEntrance extends Emiter { @@ -421,22 +457,45 @@ export default class MessageEntrance extends Emiter {
421 GlobalConfig.setMusicListPrepare(_data.musicListPrepare);//提前上传的声音文件列表 457 GlobalConfig.setMusicListPrepare(_data.musicListPrepare);//提前上传的声音文件列表
422 458
423 459
  460 + if (_data.mcuList) {
  461 + //MCU地址默认使用第一个
  462 + GlobalConfig.MCUServerIP =_data.mcuList[0].ip||"";
  463 + GlobalConfig.MCUServerPort =_data.mcuList[0].port||"";
  464 + }
  465 +
  466 + //视频推流播流地址
  467 + if (_data.msList) {
  468 + //MS地址默认使用第一个
  469 + GlobalConfig.MSServerIP =_data.msList[0].ip||"";
  470 + GlobalConfig.MSServerPort =_data.msList[0].port||"";
  471 + }
  472 +
  473 + //m3u8播流地址
  474 + if(_data.rsList){
  475 + //RS地址默认使用第一个
  476 + GlobalConfig.RSServerIP =_data.rsList[0].ip||"";
  477 + GlobalConfig.RSServerPort =_data.rsList[0].port||"";
  478 + }
  479 +
  480 + //文档地址
  481 + if(_data.docList){
  482 + //doc地址默认使用第一个
  483 + GlobalConfig.DOCServerIP =_data.docList[0].ip||"";
  484 + GlobalConfig.DOCServerPort =_data.docList[0].port||"";
  485 + }
  486 +
  487 + //record
  488 + if(_data.recordList){
  489 + //地址默认使用第一个
  490 + GlobalConfig.RecordServerIP =_data.recordList[0].ip||"";
  491 + GlobalConfig.RecordServerPort =_data.recordList[0].port||"";
  492 + }
  493 +
424 } 494 }
  495 +
425 if (_data.currentInfo) { 496 if (_data.currentInfo) {
426 //根据从Sass获取的数据信息,同步最后一次保存的会议状态信息 497 //根据从Sass获取的数据信息,同步最后一次保存的会议状态信息
427 loger.log("同步最后一次保存过的会议状态信息"); 498 loger.log("同步最后一次保存过的会议状态信息");
428 -  
429 - /*//解析BASE64的数据  
430 - loger.log("11111111111111111111111111111111");  
431 - console.log(GlobalConfig.classStatusInfo);  
432 - //已经保存过会议状态信息,读取之前的数据  
433 - let _classStatusInfo=EngineUtils.objectFromBase64(_data.currentInfo);  
434 - loger.log("classStatusInfo",_classStatusInfo);  
435 - GlobalConfig.classStatusInfo=_classStatusInfo;  
436 - loger.log("2222222222222222222222222");  
437 - console.log(GlobalConfig.classStatusInfo);*/  
438 -  
439 - //console.log(_data.currentInfo);  
440 GlobalConfig.setClassStatusInfo(_data.currentInfo); 499 GlobalConfig.setClassStatusInfo(_data.currentInfo);
441 console.log(GlobalConfig.classStatusInfo) 500 console.log(GlobalConfig.classStatusInfo)
442 } else { 501 } else {
@@ -450,11 +509,6 @@ export default class MessageEntrance extends Emiter { @@ -450,11 +509,6 @@ export default class MessageEntrance extends Emiter {
450 //保存会议状态信息 509 //保存会议状态信息
451 _sassSaveClassStatusInfo() { 510 _sassSaveClassStatusInfo() {
452 if (GlobalConfig.isHost) { 511 if (GlobalConfig.isHost) {
453 - //用get保存数据,数据内容需要转为BASE64  
454 - //let _classStatusInfo=EngineUtils.objectToBase64(GlobalConfig.classStatusInfo);  
455 - //loger.log("保存会议状态信息",_classStatusInfo);  
456 - //_sass.saveClassStatusInfo({"classStatusInfo":_classStatusInfo});//保存会议状态信息  
457 -  
458 //只有加入会议之后才能保存数据 512 //只有加入会议之后才能保存数据
459 if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) { 513 if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) {
460 //POST 保存数据 514 //POST 保存数据
@@ -481,7 +535,7 @@ export default class MessageEntrance extends Emiter { @@ -481,7 +535,7 @@ export default class MessageEntrance extends Emiter {
481 } 535 }
482 536
483 // MCU 会议成功 537 // MCU 会议成功
484 - _joinClassSuccessHandler(_data) { 538 + _mcuJoinClassSuccessHandler(_data) {
485 loger.log('MCU 会议成功.'); 539 loger.log('MCU 会议成功.');
486 GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2); 540 GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);
487 541
@@ -490,17 +544,15 @@ export default class MessageEntrance extends Emiter { @@ -490,17 +544,15 @@ export default class MessageEntrance extends Emiter {
490 //返回给客户端初始化成功的数据 544 //返回给客户端初始化成功的数据
491 let initSuccessCallBackData = {}; 545 let initSuccessCallBackData = {};
492 546
493 - //GlobalConfig.MCUServerIP=_data.MCUServerIP;  
494 - // GlobalConfig.MCUServerPort=_data.MCUServerPort; 547 + initSuccessCallBackData.DOCServerIP =GlobalConfig.DOCServerIP;
  548 + initSuccessCallBackData.DOCServerPort =GlobalConfig.DOCServerPort;
495 549
496 - initSuccessCallBackData.docServer = GlobalConfig.docServer;//文档服务器地址  
497 initSuccessCallBackData.classId = GlobalConfig.classId; 550 initSuccessCallBackData.classId = GlobalConfig.classId;
498 initSuccessCallBackData.className = GlobalConfig.className; 551 initSuccessCallBackData.className = GlobalConfig.className;
499 initSuccessCallBackData.h5Module = GlobalConfig.h5Module; 552 initSuccessCallBackData.h5Module = GlobalConfig.h5Module;
500 initSuccessCallBackData.isHost = GlobalConfig.isHost; 553 initSuccessCallBackData.isHost = GlobalConfig.isHost;
501 initSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels; 554 initSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;
502 initSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels; 555 initSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;
503 - initSuccessCallBackData.maxMediaChannels = GlobalConfig.maxMediaChannels;  
504 initSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay; 556 initSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;
505 557
506 initSuccessCallBackData.msType = GlobalConfig.msType; 558 initSuccessCallBackData.msType = GlobalConfig.msType;
@@ -526,79 +578,6 @@ export default class MessageEntrance extends Emiter { @@ -526,79 +578,6 @@ export default class MessageEntrance extends Emiter {
526 loger.log('加入会议成功', initSuccessCallBackData); 578 loger.log('加入会议成功', initSuccessCallBackData);
527 _joinClassSuccessCallBackFun(initSuccessCallBackData); 579 _joinClassSuccessCallBackFun(initSuccessCallBackData);
528 } 580 }
529 -  
530 -  
531 - //loger.log('MCU 会议成功.');  
532 - //GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);  
533 - //if(_sass){  
534 - // _sass.getClassDetail();//会议信息  
535 - // _sass.getClassParam();//会议参数大全  
536 - //}  
537 - //  
538 - ////储存数据  
539 - //GlobalConfig.MCUServerIP=_data.MCUServerIP;  
540 - //GlobalConfig.MCUServerPort=_data.MCUServerPort;  
541 - //GlobalConfig.classId=_data.classId;  
542 - //GlobalConfig.h5Module=_data.h5Module;  
543 - //GlobalConfig.maxAudioChannels=_data.maxAudioChannels;  
544 - //GlobalConfig.maxVideoChannels=_data.maxVideoChannels;  
545 - //GlobalConfig.maxMediaChannels=_data.maxMediaChannels;  
546 - //GlobalConfig.mcuClassInfo=_data.mcuClassInfo;  
547 - //GlobalConfig.mcuDelay=_data.mcuDelay;  
548 - //GlobalConfig.md5=_data.md5;  
549 - //GlobalConfig.msType=_data.msType;  
550 - //GlobalConfig.nodeId=_data.nodeId;  
551 - //GlobalConfig.password=_data.password;  
552 - //GlobalConfig.portal=_data.portal;  
553 - //GlobalConfig.role=_data.role;  
554 - //GlobalConfig.siteId=_data.siteId;  
555 - //GlobalConfig.topNodeID=_data.topNodeID;  
556 - //GlobalConfig.userId=_data.userId;  
557 - //GlobalConfig.userName=_data.userName;  
558 - //GlobalConfig.userRole=_data.userRole;  
559 - //GlobalConfig.userType=_data.userType;  
560 - //  
561 - ////返回给客户数据  
562 - //if(_joinClassSuccessCallBackFun){  
563 - // //返回给客户端初始化成功的数据  
564 - // let initSuccessCallBackData={};  
565 - //  
566 - // //GlobalConfig.MCUServerIP=_data.MCUServerIP;  
567 - // // GlobalConfig.MCUServerPort=_data.MCUServerPort;  
568 - //  
569 - // initSuccessCallBackData.docServer=GlobalConfig.docServer;//文档服务器地址  
570 - // initSuccessCallBackData.classId=GlobalConfig.classId;  
571 - // initSuccessCallBackData.className=GlobalConfig.className;  
572 - // initSuccessCallBackData.h5Module=GlobalConfig.h5Module;  
573 - // initSuccessCallBackData.isHost=GlobalConfig.isHost;  
574 - // initSuccessCallBackData.maxAudioChannels=GlobalConfig.maxAudioChannels;  
575 - // initSuccessCallBackData.maxVideoChannels=GlobalConfig.maxVideoChannels;  
576 - // initSuccessCallBackData.maxMediaChannels=GlobalConfig.maxMediaChannels;  
577 - // initSuccessCallBackData.mcuDelay=GlobalConfig.mcuDelay;  
578 - //  
579 - // initSuccessCallBackData.msType=GlobalConfig.msType;  
580 - // initSuccessCallBackData.nodeId=GlobalConfig.nodeId;  
581 - // initSuccessCallBackData.password=GlobalConfig.password;  
582 - // initSuccessCallBackData.passwordRequired=GlobalConfig.passwordRequired;// 老师的默认是true  
583 - // //GlobalConfig.passwordRequired 老师的默认是true  
584 - // //GlobalConfig.portal=_data.portal;  
585 - // initSuccessCallBackData.role=GlobalConfig.role;  
586 - // initSuccessCallBackData.siteId=GlobalConfig.siteId;  
587 - // initSuccessCallBackData.topNodeID=GlobalConfig.topNodeID;  
588 - // initSuccessCallBackData.userId=GlobalConfig.userId;  
589 - // initSuccessCallBackData.userName=GlobalConfig.userName;  
590 - // initSuccessCallBackData.userRole=GlobalConfig.userRole;  
591 - // initSuccessCallBackData.userType=GlobalConfig.userType;  
592 - //  
593 - // initSuccessCallBackData.siteId=GlobalConfig.siteId;  
594 - // initSuccessCallBackData.classId=GlobalConfig.classId;  
595 - // initSuccessCallBackData.userRole=GlobalConfig.userRole;  
596 - // initSuccessCallBackData.userId=GlobalConfig.userId;  
597 - // initSuccessCallBackData.passwordRequired=GlobalConfig.passwordRequired;  
598 - // initSuccessCallBackData.classType=GlobalConfig.classType||ApeConsts.CLASS_TYPE_INTERACT;  
599 - // loger.log('加入会议成功',initSuccessCallBackData);  
600 - // _joinClassSuccessCallBackFun(initSuccessCallBackData);  
601 - //}  
602 } 581 }
603 582
604 //Sass删除文档数据 583 //Sass删除文档数据
@@ -653,6 +632,9 @@ export default class MessageEntrance extends Emiter { @@ -653,6 +632,9 @@ export default class MessageEntrance extends Emiter {
653 if(_video_ape){ 632 if(_video_ape){
654 _video_ape.stopPublishVideo(); 633 _video_ape.stopPublishVideo();
655 } 634 }
  635 + if(_audio_ape){
  636 + _audio_ape.stopPublishAudio();
  637 + }
656 //离开会议 638 //离开会议
657 if(_confer_ape){ 639 if(_confer_ape){
658 _confer_ape.leaveClass(); 640 _confer_ape.leaveClass();
@@ -714,6 +696,45 @@ export default class MessageEntrance extends Emiter { @@ -714,6 +696,45 @@ export default class MessageEntrance extends Emiter {
714 } 696 }
715 } 697 }
716 698
  699 + //AudioApe
  700 + audioUpdate(_data){
  701 + //音频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
  702 + if(_confer_ape){
  703 + _confer_ape.updaterRosterStatus(_data);
  704 + }
  705 + }
  706 +
  707 + sendAudioCommandMsg(_param){
  708 + if(_audio_ape){
  709 + return _audio_ape.sendAudioBroadcastMsg(_param);
  710 + }
  711 + }
  712 +
  713 + _getPlayAudioPath(_param){
  714 + if(_audio_ape){
  715 + return _audio_ape.getAudioPlayPath(_param);
  716 + }
  717 + }
  718 +
  719 + _getPublishAudioPath(_param){
  720 + if(_audio_ape){
  721 + return _audio_ape.getAudioPublishPath(_param);
  722 + }
  723 + }
  724 +
  725 + _publishAudio(_param){
  726 + if(_audio_ape){
  727 + return _audio_ape.publishAudio(_param);
  728 + }
  729 + }
  730 +
  731 + _stopPublishAudio(_param){
  732 + if(_audio_ape){
  733 + return _audio_ape.stopPublishAudio(_param);
  734 + }
  735 + }
  736 +
  737 +
717 //WhiteBoardApe 738 //WhiteBoardApe
718 // 添加标注,发送信息 739 // 添加标注,发送信息
719 _sendInsertAnnotaion(_param){ 740 _sendInsertAnnotaion(_param){
@@ -820,30 +841,32 @@ export default class MessageEntrance extends Emiter { @@ -820,30 +841,32 @@ export default class MessageEntrance extends Emiter {
820 if(GlobalConfig.isHost){ 841 if(GlobalConfig.isHost){
821 for (let value of GlobalConfig.docListPrepare){ 842 for (let value of GlobalConfig.docListPrepare){
822 if(value){ 843 if(value){
823 - //{  
824 - // "MD5": "f3feb3fac8cd3a953bded00e07a0c66b",  
825 - // "absoluteLocation": "http://101.200.150.192/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",  
826 - // "createUserID": "972",  
827 - // "createUserIP": "114.241.81.175",  
828 - // "createUserName": "base",  
829 - // "dynamicPPT": 0,  
830 - // "dynamicTransferStatic": "",  
831 - // "id": "8ab3b0ed5a00f2fa015a0219a3df016c",  
832 - // "meetingNumber": "",  
833 - // "name": "McuClient_v.1.0.1_API.pdf",  
834 - // "orderStr": "",  
835 - // "pdfSize": 5,  
836 - // "processEndTime": "2017-02-03 11:54:31",  
837 - // "processRate": 0,  
838 - // "processStartTime": "2017-02-03 11:54:27",  
839 - // "relativeLocation": "/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",  
840 - // "siteID": "h5test",  
841 - // "size": 360920,  
842 - // "status": 3,  
843 - // "type": "pdf",  
844 - // "uploadEndTime": "2017-02-03 11:54:27",  
845 - // "uploadStartTime": "2017-02-03 11:54:27"  
846 - //} 844 + /* //提前上传的文档文档信息的结构
  845 + {
  846 + "MD5": "f3feb3fac8cd3a953bded00e07a0c66b",
  847 + "absoluteLocation": "http://101.200.150.192/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
  848 + "createUserID": "972",
  849 + "createUserIP": "114.241.81.175",
  850 + "createUserName": "base",
  851 + "dynamicPPT": 0,
  852 + "dynamicTransferStatic": "",
  853 + "id": "8ab3b0ed5a00f2fa015a0219a3df016c",
  854 + "meetingNumber": "",
  855 + "name": "McuClient_v.1.0.1_API.pdf",
  856 + "orderStr": "",
  857 + "pdfSize": 5,
  858 + "processEndTime": "2017-02-03 11:54:31",
  859 + "processRate": 0,
  860 + "processStartTime": "2017-02-03 11:54:27",
  861 + "relativeLocation": "/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
  862 + "siteID": "h5test",
  863 + "size": 360920,
  864 + "status": 3,
  865 + "type": "pdf",
  866 + "uploadEndTime": "2017-02-03 11:54:27",
  867 + "uploadStartTime": "2017-02-03 11:54:27"
  868 + }*/
  869 +
847 loger.log("判断是否需要把提前上传的文档上传到mcu",value); 870 loger.log("判断是否需要把提前上传的文档上传到mcu",value);
848 let paramInfo={ 871 let paramInfo={
849 "pageNum": value.pdfSize, 872 "pageNum": value.pdfSize,
@@ -30,7 +30,9 @@ class GlobalConfig { @@ -30,7 +30,9 @@ class GlobalConfig {
30 static getClassDetail(){ 30 static getClassDetail(){
31 return this.classDetail; 31 return this.classDetail;
32 } 32 }
33 - 33 + static setClassDetail(_data){
  34 + this.classDetail=_data;
  35 + }
34 static getClassInfo (){ 36 static getClassInfo (){
35 let classInfo={}; 37 let classInfo={};
36 classInfo.siteId= this.siteId; 38 classInfo.siteId= this.siteId;
@@ -55,7 +57,6 @@ class GlobalConfig { @@ -55,7 +57,6 @@ class GlobalConfig {
55 classInfo.MCUServerPort=this.MCUServerPort; 57 classInfo.MCUServerPort=this.MCUServerPort;
56 classInfo.maxVideoChannels= this.maxVideoChannels; 58 classInfo.maxVideoChannels= this.maxVideoChannels;
57 classInfo.maxAudioChannels=this.maxAudioChannels; 59 classInfo.maxAudioChannels=this.maxAudioChannels;
58 - classInfo.maxMediaChannels= this.maxMediaChannels;  
59 60
60 return classInfo; 61 return classInfo;
61 62
@@ -175,13 +176,13 @@ class GlobalConfig { @@ -175,13 +176,13 @@ class GlobalConfig {
175 static getDocListPrepare(){ 176 static getDocListPrepare(){
176 return this.docListPrepare; 177 return this.docListPrepare;
177 } 178 }
178 - //储存文档录制列表  
179 - static setDocRecordList(_data){ 179 + //储存录制列表
  180 + static setRecordList(_data){
180 if(_data==null) return; 181 if(_data==null) return;
181 - this.docRecordList=_data; 182 + this.recordList=_data;
182 } 183 }
183 - static getDocRecordList(){  
184 - return this.docRecordList; 184 + static getRecordList(){
  185 + return this.recordList;
185 } 186 }
186 187
187 //文档服务器列表 188 //文档服务器列表
@@ -247,11 +248,12 @@ GlobalConfig.md5=""; @@ -247,11 +248,12 @@ GlobalConfig.md5="";
247 GlobalConfig.msType=1;//目前固定用这个 248 GlobalConfig.msType=1;//目前固定用这个
248 GlobalConfig.mcuDelay=3000;//默认的延迟时间 249 GlobalConfig.mcuDelay=3000;//默认的延迟时间
249 GlobalConfig.docDelay=1600;//文档模块加入成功之后延迟发送送成功的消息给主模块 250 GlobalConfig.docDelay=1600;//文档模块加入成功之后延迟发送送成功的消息给主模块
250 -GlobalConfig.portal="112.126.80.182:80";  
251 -GlobalConfig.ip="112.126.80.182";  
252 -GlobalConfig.port="80"; 251 +GlobalConfig.portal="112.126.80.182:80";//Sass IP
  252 +
  253 +//GlobalConfig.ip="112.126.80.182";
  254 +//GlobalConfig.port="80";
  255 +
253 GlobalConfig.MCUServerIP="114.215.195.70"; 256 GlobalConfig.MCUServerIP="114.215.195.70";
254 -GlobalConfig.docServer="";//当前的文档地址加载的服务器地址  
255 GlobalConfig.MCUServerPort=9003; 257 GlobalConfig.MCUServerPort=9003;
256 258
257 GlobalConfig.MSServerIP = "";//推流 播流的地址 259 GlobalConfig.MSServerIP = "";//推流 播流的地址
@@ -261,9 +263,16 @@ GlobalConfig.MSServerPort =""; @@ -261,9 +263,16 @@ GlobalConfig.MSServerPort ="";
261 GlobalConfig.RSServerIP =""; 263 GlobalConfig.RSServerIP ="";
262 GlobalConfig.RSServerPort =""; 264 GlobalConfig.RSServerPort ="";
263 265
  266 +//DOC
  267 +GlobalConfig.DOCServerIP ="";
  268 +GlobalConfig.DOCServerPort ="";
  269 +
  270 +GlobalConfig.RecordServerIP ="";
  271 +GlobalConfig.RecordServerPort ="";
  272 +
264 GlobalConfig.maxVideoChannels=0; 273 GlobalConfig.maxVideoChannels=0;
265 GlobalConfig.maxAudioChannels=0; 274 GlobalConfig.maxAudioChannels=0;
266 -GlobalConfig.maxMediaChannels=0; 275 +
267 GlobalConfig.isDebug=false; 276 GlobalConfig.isDebug=false;
268 GlobalConfig.deBugData={}; 277 GlobalConfig.deBugData={};
269 278
@@ -315,7 +324,7 @@ GlobalConfig.classAllParam={};//Sass直接返回的所有会议信息(最全) @@ -315,7 +324,7 @@ GlobalConfig.classAllParam={};//Sass直接返回的所有会议信息(最全)
315 GlobalConfig.classDetail={};//Sass直接返回的当前课堂基本信息 324 GlobalConfig.classDetail={};//Sass直接返回的当前课堂基本信息
316 325
317 GlobalConfig.docListPrepare=[]; // 已经提前上传的文档,进入课堂后需要自动加载 326 GlobalConfig.docListPrepare=[]; // 已经提前上传的文档,进入课堂后需要自动加载
318 -GlobalConfig.docRecordList=[];//录制服务器地址集合 327 +GlobalConfig.recordList=[];//录制服务器地址集合
319 GlobalConfig.docList=[];//文档服务器地址集合 328 GlobalConfig.docList=[];//文档服务器地址集合
320 GlobalConfig.mcuList=[];//录制服务器地址集合 329 GlobalConfig.mcuList=[];//录制服务器地址集合
321 GlobalConfig.msList=[];//ms服务器地址集合 330 GlobalConfig.msList=[];//ms服务器地址集合
@@ -323,21 +332,5 @@ GlobalConfig.musicList=[];//music服务器地址集合 @@ -323,21 +332,5 @@ GlobalConfig.musicList=[];//music服务器地址集合
323 GlobalConfig.musicListPrepare=[];//提提前上传的music集合 332 GlobalConfig.musicListPrepare=[];//提提前上传的music集合
324 GlobalConfig.rsList=[]; 333 GlobalConfig.rsList=[];
325 334
326 -// client type  
327 -//点对点会议版本  
328 - GlobalConfig.CT_P2PMEETING = 0;  
329 -/**  
330 - * 直播教育版本和大型直播版本  
331 - */  
332 -GlobalConfig.CT_LIVEEDUCATION = 1;  
333 -/**  
334 - * 录制播放器  
335 - */  
336 -GlobalConfig.CT_RECORDPLAYER = 2;  
337 -/**  
338 - * 实时流版本  
339 - */  
340 -GlobalConfig. CT_LIVESTREAMING = 3;  
341 -GlobalConfig.clientType =0;  
342 335
343 export default GlobalConfig; 336 export default GlobalConfig;
  1 +//对外暴露的对象
  2 +
  3 +
1 import EngineEntrance from 'EngineEntrance'; 4 import EngineEntrance from 'EngineEntrance';
2 import MessageTypes from 'MessageTypes'; 5 import MessageTypes from 'MessageTypes';
3 6
4 -const MCU_CLIENT=new EngineEntrance(); 7 +const MCU_CLIENT=new EngineEntrance();//入口文件
5 8
6 export function createMcuClient() { 9 export function createMcuClient() {
7 return MCU_CLIENT; 10 return MCU_CLIENT;
8 } 11 }
9 12
  13 +//监听是事件名和异常定义
10 export {MessageTypes}; 14 export {MessageTypes};
@@ -29,7 +29,12 @@ MessageTypes.CHAT_RECEIVE = 'chat.receive'; @@ -29,7 +29,12 @@ MessageTypes.CHAT_RECEIVE = 'chat.receive';
29 29
30 //视频模块事件定义 30 //视频模块事件定义
31 MessageTypes.VIDEO_UPDATE = 'video.update'; 31 MessageTypes.VIDEO_UPDATE = 'video.update';
32 -MessageTypes.VIDEO_COMMAND= 'video.command'; 32 +MessageTypes.VIDEO_BROADCAST= 'video.broadcast';
  33 +
  34 +//音频模块事件定义
  35 +MessageTypes.AUDIO_UPDATE = 'audio.update';
  36 +MessageTypes.AUDIO_BROADCAST= 'audio.broadcast';
  37 +
33 38
34 //文档模块事件定义 39 //文档模块事件定义
35 MessageTypes.DOC_DELETE='document.delete';//删除文档 40 MessageTypes.DOC_DELETE='document.delete';//删除文档
@@ -82,10 +82,13 @@ ApeConsts.USER_MIC_OPEN = 0x0040; // 麦克风开启 @@ -82,10 +82,13 @@ ApeConsts.USER_MIC_OPEN = 0x0040; // 麦克风开启
82 ApeConsts.USER_CAMERA_OPEN = 0x0080; // 视频开启 82 ApeConsts.USER_CAMERA_OPEN = 0x0080; // 视频开启
83 83
84 84
  85 +
85 //VIDEO MIC 流媒体消息操作控制类型 86 //VIDEO MIC 流媒体消息操作控制类型
86 ApeConsts.MEDIA_ACTION_DEFAULT=0; 87 ApeConsts.MEDIA_ACTION_DEFAULT=0;
  88 +
87 ApeConsts.MEDIA_ACTION_OPEN_CAMERA=1;// "open.camera"; 89 ApeConsts.MEDIA_ACTION_OPEN_CAMERA=1;// "open.camera";
88 ApeConsts.MEDIA_ACTION_CLOSE_CAMERA=2;// "close.camera"; 90 ApeConsts.MEDIA_ACTION_CLOSE_CAMERA=2;// "close.camera";
  91 +
89 ApeConsts.MEDIA_ACTION_OPEN_MIC= 3;//"open.mic"; 92 ApeConsts.MEDIA_ACTION_OPEN_MIC= 3;//"open.mic";
90 ApeConsts.MEDIA_ACTION_CLOSE_MIC= 4;//"close.mic"; 93 ApeConsts.MEDIA_ACTION_CLOSE_MIC= 4;//"close.mic";
91 94
@@ -99,12 +102,16 @@ ApeConsts.MEDIA_TYPE_DEFAULT=0;//没有类型 @@ -99,12 +102,16 @@ ApeConsts.MEDIA_TYPE_DEFAULT=0;//没有类型
99 ApeConsts.MEDIA_TYPE_VIDEO=1;//视频流(包含音频) 102 ApeConsts.MEDIA_TYPE_VIDEO=1;//视频流(包含音频)
100 ApeConsts.MEDIA_TYPE_AUDIO=2;//音频流 103 ApeConsts.MEDIA_TYPE_AUDIO=2;//音频流
101 104
102 -//FLASH中使用下面4个  
103 -ApeConsts.CGS_RELEASED = 0;///< 无人占用状态  
104 -ApeConsts.CGS_PENDING = 1;///< 占用成功,等待打开  
105 -ApeConsts.CGS_OPENNED = 2;///< 打开成功  
106 -ApeConsts.CGS_GRABBING = 3; ///< 准备占用中, 属于本地状态机需要用的状态,在多点数据库中不存在。 105 +//return返回值状态
  106 +ApeConsts.RETURN_SUCCESS=0;//成功
  107 +ApeConsts.RETURN_FAILED=1;//失败
107 108
  109 +////FLASH中使用下面4个
  110 +//ApeConsts.CGS_RELEASED = 0;///< 无人占用状态
  111 +//ApeConsts.CGS_PENDING = 1;///< 占用成功,等待打开
  112 +//ApeConsts.CGS_OPENNED = 2;///< 打开成功
  113 +//ApeConsts.CGS_GRABBING = 3; ///< 准备占用中, 属于本地状态机需要用的状态,在多点数据库中不存在。
  114 +//
108 115
109 116
110 ApeConsts.INVALIDATE_CHANNEL_ID = -1; 117 ApeConsts.INVALIDATE_CHANNEL_ID = -1;
  1 +// //////////////////////////////////////////////////////////////////////////////
  2 +//音频模块
  3 +// //////////////////////////////////////////////////////////////////////////////
  4 +
  5 +import Ape from './Ape';
  6 +import ApeConsts from './ApeConsts';
  7 +import pdu from 'pdus';
  8 +import Loger from 'Loger';
  9 +import MessageTypes from 'MessageTypes';
  10 +import GlobalConfig from 'GlobalConfig';
  11 +import EngineUtils from 'EngineUtils';
  12 +import MediaModule from "./MediaModule";
  13 +
  14 +let loger = Loger.getLoger('AudioApe');
  15 +
  16 +class AudioApe extends Ape {
  17 + constructor() {
  18 + super(
  19 + ApeConsts.AUDIO_SESSION_ID,
  20 + ApeConsts.AUDIO_SESSION_NAME,
  21 + ApeConsts.AUDIO_SESSION_TAG
  22 + );
  23 +
  24 + this.mediaModule=new MediaModule();
  25 + this.mediaModule.MEDIA_OBJ_TABLE_ID=ApeConsts.AUDIO_OBJ_TABLE_ID;
  26 + this.mediaModule.mediaChannels={};
  27 + // Ape Models
  28 + this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
  29 + this.registerObj(pdu.RCPDU_REG_REGISTER_TABLE, ApeConsts.AUDIO_OBJ_TABLE_ID, ApeConsts.AUDIO_OBJ_TABLE_NAME, ApeConsts.AUDIO_OBJ_TABLE_TAG, 0, new ArrayBuffer);
  30 +
  31 + // 广播消息,用户之间的消息传递
  32 + this.on(pdu.RCPDU_AUDIO_SEND_DATA_REQUEST, this.receiveAudiooCommandHandler.bind(this));
  33 + }
  34 + //ape加入成功
  35 + onJoinChannelHandlerSuccess(){
  36 + //这个设置很重要,因为只有Sass流程完成之后,APE才能取得GlobalConfig中的数据
  37 + this.mediaModule.maxMediaChannel=GlobalConfig.maxAudioChannels;
  38 + }
  39 +
  40 + /////////////发送数据操作////////////////////////////////////////////
  41 + //获取播流地址
  42 + getAudioPlayPath(_param) {
  43 + loger.log('getAudioPlayPath');
  44 + return this.mediaModule.getMediaPlayPath(_param);
  45 + }
  46 +
  47 + //获取推流地址
  48 + getAudioPublishPath(_param) {
  49 + loger.log('getAudioPublishPath');
  50 + return this.mediaModule.getMediaPublishPath(_param);
  51 + }
  52 +
  53 + //推流
  54 + publishAudio(_param) {
  55 + if (_param == null||_param.channelId == null||
  56 + _param.classId == null||_param.userId == null||
  57 + _param.siteId == null|| _param.timestamp==null)
  58 + {
  59 + loger.warn('publishAudio,参数错误', _param);
  60 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
  61 + return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"};
  62 + }
  63 +
  64 + //同一个nodeId只允许推一个流,如果已经推了就不能再推
  65 + if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){
  66 + loger.warn("publishAudio,已经存在一个流,不能再推");
  67 + return {"code": ApeConsts.RETURN_FAILED, "data": "已经存在一个流,不能再推"};
  68 + }
  69 +
  70 + //判断当前是否还有空闲的channle
  71 + let freeChannel = this.mediaModule.getFreeMediaChannel();
  72 + if (freeChannel == 0) {
  73 + loger.warn("publishAudio,没有空闲的channel ");
  74 + return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"};
  75 + }
  76 +
  77 + //判断当前的频道是否已经占用
  78 + if(this.mediaModule.checkChannelIsOpening(_param.channelId)){
  79 + loger.warn(_param.channelId,"频道已经被占用");
  80 + return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!"};
  81 + }
  82 +
  83 + let channelInfo={};
  84 + channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING;
  85 + channelInfo.fromNodeId=GlobalConfig.nodeId;
  86 + channelInfo.channelId=_param.channelId;//freeChannel
  87 + channelInfo.timestamp=_param.timestamp;//EngineUtils.creatTimestamp();
  88 + channelInfo.classId=_param.classId;//GlobalConfig.classId;
  89 + channelInfo.siteId=_param.siteId;//GlobalConfig.siteId;
  90 + channelInfo.toNodeId=0;
  91 + channelInfo.mediaType=ApeConsts.MEDIA_TYPE_AUDIO;
  92 + this.sendTableUpdateHandler(channelInfo);
  93 + return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!"}
  94 + }
  95 +
  96 + //停止推流,
  97 + stopPublishAudio(_param) {
  98 + loger.log('stopPublishAudio');
  99 + //_param如果为空,那么默认就是当前自己的nodeId,否则用_param
  100 + let nodeId;
  101 + if(_param&&parseInt(_param.nodeId)>=0){
  102 + nodeId=parseInt(_param.nodeId);
  103 + }else {
  104 + nodeId=GlobalConfig.nodeId;
  105 + }
  106 +
  107 + let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId);
  108 + if (openingChannel == 0) {
  109 + loger.warn(nodeId,"stopPublishAudio,没有占用channel,不需要关闭");
  110 + return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel,不需要关闭"};
  111 + }
  112 +
  113 + let channelInfo={};
  114 + channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
  115 + channelInfo.fromNodeId=0;
  116 + channelInfo.channelId=openingChannel;
  117 + channelInfo.timestamp=0;
  118 + channelInfo.classId=GlobalConfig.classId;
  119 + channelInfo.toNodeId=0;
  120 + channelInfo.mediaType=ApeConsts.MEDIA_TYPE_DEFAULT;
  121 + this.sendTableUpdateHandler(channelInfo);
  122 + }
  123 +
  124 + sendAudioBroadcastMsg(_param) {
  125 + if (this._classInfo === null || EngineUtils.isEmptyObject(this._classInfo)) {
  126 + loger.log('sendAudioBroadcastMsg.McuClient还未初始化数据!');
  127 + if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
  128 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
  129 + return {"code": ApeConsts.RETURN_FAILED, "data": "sendAudioBroadcastMsg.McuClient还未初始化数据"};
  130 + }
  131 + return {"code": ApeConsts.RETURN_FAILED, "data": "sendAudioBroadcastMsg.McuClient还未初始化数据"};
  132 + }
  133 + if (_param == null) {
  134 + loger.warn('sendAudioBroadcastMsg,参数错误', _param);
  135 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
  136 + return {"code": ApeConsts.RETURN_FAILED, "data": "sendAudioBroadcastMsg,参数错误"};
  137 + }
  138 + // to, message
  139 + loger.log('发送Audio消息.', _param);
  140 +
  141 + if (_param.actionType != null && _param.actionType == ApeConsts.MEDIA_ACTION_OPEN_CAMERA) {
  142 + //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
  143 + let freeChannel = this.mediaModule.getFreeMediaChannel();
  144 + if (freeChannel == 0) {
  145 + loger.warn('sendAudioBroadcastMsg,不能再打开更多的设备', _param);
  146 + return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"};
  147 + }
  148 + }
  149 +
  150 +
  151 + let audioSendPdu = new pdu['RCAudioSendDataRequestPdu'];
  152 + audioSendPdu.type = pdu.RCPDU_AUDIO_SEND_DATA_REQUEST;
  153 + audioSendPdu.isPublic = true;
  154 +
  155 + audioSendPdu.fromNodeId = GlobalConfig.nodeId;//发起人
  156 + audioSendPdu.toNodeId = parseInt(_param.toNodeID) || 0;//接收者,0就是所有人
  157 + audioSendPdu.actionType = parseInt(_param.actionType) || ApeConsts.MEDIA_ACTION_DEFAULT;
  158 +
  159 + audioSendPdu.data = this._rCArrayBufferUtil.strToUint8Array("h5" + _param.data);//开头两个字会乱码
  160 +
  161 + if (!audioSendPdu.isPublic && 0 != audioSendPdu.toNodeId) {
  162 + //发送给制定的人
  163 + loger.log('发送私聊消息.');
  164 + this.send(audioSendPdu);
  165 + } else {
  166 + //发送给所有人
  167 + loger.log('发送公聊消息.');
  168 + this.sendChatUniform(audioSendPdu);
  169 + }
  170 + return {"code": ApeConsts.RETURN_SUCCESS, "data": ""};
  171 + }
  172 +
  173 + sendTableUpdateHandler(_channelInfo) {
  174 + loger.log("audio,sendTableUpdateHandler ");
  175 + let updateModelPdu = this.packPdu(_channelInfo, _channelInfo.channelId);
  176 + if(updateModelPdu==null){
  177 + loger.warn("sendTableUpdateHandler error,updateModelPdu=null");
  178 + return;
  179 + }
  180 +
  181 + let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
  182 + tableItemPdu.itemIdx = _channelInfo.channelId;
  183 + tableItemPdu.owner = 0;//收到flash的是这个值,不清楚先写固定
  184 + tableItemPdu.itemData = updateModelPdu.toArrayBuffer();
  185 +
  186 + //insert
  187 + let tableInsertItemPdu = new pdu['RCRegistryTableUpdateItemPdu'];
  188 + //optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
  189 + //repeated RCRegistryTableItemPdu items = 2;
  190 + tableInsertItemPdu.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;//
  191 + tableInsertItemPdu.items.push(tableItemPdu);
  192 +
  193 + let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
  194 + updateObjPdu.objId = ApeConsts.AUDIO_OBJ_TABLE_ID;//
  195 + updateObjPdu.subType = tableInsertItemPdu.type;
  196 + updateObjPdu.userData = tableInsertItemPdu.toArrayBuffer();
  197 +
  198 + //同步
  199 + let adapterItemPdu = new pdu['RCAdapterItemPdu'];
  200 + adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
  201 + adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
  202 +
  203 + let adapterPdu = new pdu['RCAdapterPdu'];
  204 + adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
  205 + adapterPdu.item.push(adapterItemPdu);
  206 +
  207 + loger.log("发送更新AUDIO.itemIdx=" + tableItemPdu.itemIdx);
  208 + this.sendUniform(adapterPdu, true);
  209 + }
  210 +
  211 + /////收到消息处理//////////////////////////////////////////////////
  212 +
  213 + // 消息处理,内部处理,不需要告诉应用层
  214 + receiveAudiooCommandHandler(_data) {
  215 + let audioReceivePdu = pdu['RCAudioSendDataRequestPdu'].decode(_data);
  216 + if (audioReceivePdu == null) {
  217 + loger.warn("音频消息处理,收到的消息为null,不做处理");
  218 + return;
  219 + }
  220 + audioReceivePdu.data = this._rCArrayBufferUtil.uint8ArrayToStr(audioReceivePdu.data, 2);//开头两个字会乱码
  221 + loger.log('音频消息处理 receiveAudiooCommandHandler.', audioReceivePdu);
  222 +
  223 + //判断接收者的id,如果不是0,并且也不是自己的nodeId,那么消息不做处理
  224 + if (audioReceivePdu.toNodeId != 0 && audioReceivePdu.toNodeId != GlobalConfig.nodeId) {
  225 + loger.log('音频消息不处理 toNodeId=', audioReceivePdu.toNodeId, "my nodeId=", GlobalConfig.nodeId);
  226 + } else {
  227 + this._emit(MessageTypes.AUDIO_BROADCAST, audioReceivePdu);
  228 + }
  229 + }
  230 +
  231 + tableUpdateHandler(owner, itemIdx, itemData) {
  232 + // debugger;
  233 + let updateChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
  234 +
  235 + this.mediaModule.mediaChannels[itemIdx] = updateChannelInfo;
  236 +
  237 + this._emit(MessageTypes.AUDIO_UPDATE, updateChannelInfo);
  238 + }
  239 +
  240 + ///////数据的封包和解包/////////////////////////////////////////
  241 + packPdu(_param, _itemIdx) {
  242 + loger.log("packPdu ");
  243 + //验证坐标点集合数组是否合法
  244 + if (_param == null || _itemIdx == null) {
  245 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
  246 + return null;
  247 + }
  248 +
  249 + //判断type类型,根据type设置不同的参数
  250 + let packPduModel = new pdu['RCAudioChannelInfoPdu'];
  251 + packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED;
  252 + packPduModel.channelId = _itemIdx;
  253 + packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId;
  254 + packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId);
  255 + packPduModel.userId =_param.userId||"0";
  256 + packPduModel.mediaType =_param.mediaType|| ApeConsts.MEDIA_TYPE_AUDIO;
  257 + packPduModel.timestamp =_param.timestamp||EngineUtils.creatTimestamp();
  258 + packPduModel.fromNodeId = GlobalConfig.nodeId;
  259 + packPduModel.toNodeId = 0;
  260 + console.log("packPdu",packPduModel);
  261 + return packPduModel;
  262 + }
  263 +
  264 + unPackPdu(owner, itemIdx, itemData) {
  265 + loger.log("unPackPdu ");
  266 + if (owner == null || itemIdx == null || itemData == null) {
  267 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
  268 + return null;
  269 + }
  270 + try {
  271 + let packChannelInfo = pdu['RCAudioChannelInfoPdu'].decode(itemData);
  272 + loger.log("unPackPdu",packChannelInfo);
  273 + return packChannelInfo;
  274 + } catch (err) {
  275 + loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message);
  276 + }
  277 + return null;
  278 + }
  279 +
  280 +}
  281 +
  282 +export default AudioApe;
  283 +
@@ -454,8 +454,8 @@ class ConferApe extends Ape { @@ -454,8 +454,8 @@ class ConferApe extends Ape {
454 //视频模块发生更新,人员状态需要更新 454 //视频模块发生更新,人员状态需要更新
455 updaterRosterStatus(_param){ 455 updaterRosterStatus(_param){
456 if(_param){ 456 if(_param){
457 - loger.log("视频模块发生更新,人员状态需要更新,fromNodeId->",_param.fromNodeId);  
458 - loger.log(_param.status,_param.fromNodeId,this.rosters[_param.fromNodeId]); 457 + loger.log("媒体模块发生更新,人员状态需要更新,fromNodeId->",_param.fromNodeId);
  458 + loger.log(_param.status,_param.fromNodeId);
459 //console.log(_param.fromNodeId); 459 //console.log(_param.fromNodeId);
460 //如果是自己。改变自己的状态同步到MCU 460 //如果是自己。改变自己的状态同步到MCU
461 //if(_param.fromNodeId==GlobalConfig.nodeId){ 461 //if(_param.fromNodeId==GlobalConfig.nodeId){
@@ -465,8 +465,8 @@ class ConferApe extends Ape { @@ -465,8 +465,8 @@ class ConferApe extends Ape {
465 465
466 //如果视频消息中channel的占用人 fromNodeId在人员列表中不存在,需要释放这channel,因为这个有可能是之前没释放成功的 466 //如果视频消息中channel的占用人 fromNodeId在人员列表中不存在,需要释放这channel,因为这个有可能是之前没释放成功的
467 if(_param.status==ApeConsts.CHANNEL_STATUS_OPENING&&this.rosters[_param.fromNodeId]==null){ 467 if(_param.status==ApeConsts.CHANNEL_STATUS_OPENING&&this.rosters[_param.fromNodeId]==null){
468 - loger.log("视频模块被占用,占有人已经不存在课堂中,释放Channel,_param->",_param);  
469 - this._emit(MessageTypes.CLASS_NONENTITY_ROSTER,_param.fromNodeId); 468 + loger.log("媒体模块被占用,占有人已经不存在课堂中,释放Channel,_param->",_param);
  469 + this._emit(MessageTypes.CLASS_NONENTITY_ROSTER,{"nodeId":_param.fromNodeId});
470 } 470 }
471 } 471 }
472 } 472 }
@@ -145,7 +145,8 @@ class DocApe extends Ape { @@ -145,7 +145,8 @@ class DocApe extends Ape {
145 return ""; 145 return "";
146 } 146 }
147 147
148 - let fullPath=GlobalConfig.docServer+_param.relativeUrl; 148 + let port = (GlobalConfig.DOCServerPort == "" || GlobalConfig.DOCServerPort == null) ? "":":" + GlobalConfig.DOCServerPort;
  149 + let fullPath=GlobalConfig.DOCServerIP+port+_param.relativeUrl;
149 var index; 150 var index;
150 switch (_param.type){ 151 switch (_param.type){
151 case "jpg": 152 case "jpg":
  1 +// //////////////////////////////////////////////////////////////////////////////
  2 +// VideoApe、AudioApe 共用的方法单独提取处理
  3 +// //////////////////////////////////////////////////////////////////////////////
  4 +
  5 +import ApeConsts from './ApeConsts';
  6 +import Loger from 'Loger';
  7 +import MessageTypes from 'MessageTypes';
  8 +import GlobalConfig from 'GlobalConfig';
  9 +import EngineUtils from 'EngineUtils';
  10 +
  11 +let loger = Loger.getLoger('MediaModule');
  12 +
  13 +class MediaModule {
  14 + constructor() {
  15 + this.mediaChannels = {};
  16 + this.maxMediaChannel=0;
  17 + this.MEDIA_OBJ_TABLE_ID=0;
  18 + }
  19 +
  20 + //获取播流地址
  21 + getMediaPlayPath(_param) {
  22 + loger.log('getMediaPlayPath');
  23 + if (_param == null||_param.siteId == null||
  24 + _param.classId == null||_param.userId == null||
  25 + _param.channelId == null|| _param.timestamp==null)
  26 + {
  27 + loger.warn('getMediaPlayPath,参数错误', _param);
  28 + this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
  29 + return {"code": ApeConsts.RETURN_FAILED, "data": ""};
  30 + }
  31 +
  32 + let path = "";
  33 + let port="";
  34 + if (_param.type == "m3u8") {
  35 + //M3U8
  36 + //http://123.56.73.119:6001/hls/h5dev_403074980_0_983041_1487663265/index.m3u8
  37 + port = (GlobalConfig.RSServerPort == "" || GlobalConfig.RSServerPort == null) ? "":":" + GlobalConfig.RSServerPort;
  38 + path = "http://" + GlobalConfig.RSServerIP
  39 + + port + "/live/"
  40 + + _param.siteId
  41 + + "_" + _param.classId
  42 + + "_" + _param.userId
  43 + + "_" + _param.channelId
  44 + + "_" + _param.timestamp
  45 + + "/index.m3u8";
  46 + } else {
  47 + port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "":":" + GlobalConfig.MSServerPort;
  48 + path = "rtmp://" + GlobalConfig.MSServerIP
  49 + + port + "/live/"
  50 + + _param.siteId
  51 + + "_" + _param.classId
  52 + + "_" + _param.userId
  53 + + "_" + _param.channelId
  54 + + "_" + _param.timestamp;
  55 + }
  56 + return {"code": ApeConsts.RETURN_SUCCESS, "data": "","playUrl": path};
  57 + }
  58 +
  59 + //获取推流地址
  60 + getMediaPublishPath(_param) {
  61 + loger.log('getMediaPublishPath');
  62 + //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
  63 + let freeChannel = this.getFreeMediaChannel();
  64 + if (freeChannel == 0) {
  65 + return {"code":ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"};
  66 + }
  67 +
  68 + //默认方式推流
  69 + let pubType="live";
  70 + //flash推流
  71 + if(_param&&_param.type=="flash"){
  72 + pubType ="flash";
  73 + }
  74 +
  75 + //端口,有端口就显示 ":xxx",没有端口就是""
  76 + let port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "":":" + GlobalConfig.MSServerPort;
  77 + //时间戳
  78 + let timestamp = EngineUtils.creatTimestamp();
  79 +
  80 + //生成推流地址和推流数据(同步数据的时候用)
  81 + let publishUrl = "rtmp://" + GlobalConfig.MSServerIP
  82 + + port + "/"+pubType+"/" +GlobalConfig.siteId+"_"
  83 + + GlobalConfig.classId + "_"+GlobalConfig.userId
  84 + +"_" + freeChannel + "_" + timestamp;
  85 + return {"code": ApeConsts.RETURN_SUCCESS,
  86 + "data":"",
  87 + "siteId":GlobalConfig.siteId,
  88 + "classId":GlobalConfig.classId,
  89 + "userId":GlobalConfig.userId,
  90 + "channelId": freeChannel,
  91 + "timestamp": timestamp,
  92 + "publishUrl": publishUrl
  93 + };
  94 + }
  95 +
  96 + //获取当前空闲的channel,返回值为0代表没有空闲的,否则返回的就是空闲的channelId
  97 + getFreeMediaChannel() {
  98 + let counter = 0;
  99 + for (let key in this.mediaChannels) {
  100 + let item = this.mediaChannels[key];
  101 + if (item && item.status == ApeConsts.CHANNEL_STATUS_RELEASED) {
  102 + return item.channelId;
  103 + }
  104 + counter++;
  105 + }
  106 + loger.log("getFreeMediaChannel","maxMediaChannel",this.maxMediaChannel,"counter:",counter);
  107 + console.log(this.mediaChannels);
  108 + if (counter < this.maxMediaChannel) {
  109 + return this.MEDIA_OBJ_TABLE_ID + (counter);
  110 + }
  111 + return 0;//没有空闲的
  112 + }
  113 +
  114 + //获取当前属于nodeId的已经打开的的channel,返回值为0代表没有打开的,否则返回的就是打开的channelId
  115 + getOpeningMediaChannel(_nodeId){
  116 + if(_nodeId==null||_nodeId==0){
  117 + return 0;
  118 + }
  119 + for (let key in this.mediaChannels) {
  120 + let item = this.mediaChannels[key];
  121 + if (item && item.status == ApeConsts.CHANNEL_STATUS_OPENING&&item.fromNodeId==_nodeId) {
  122 + return item.channelId;
  123 + }
  124 + }
  125 + return 0;
  126 + }
  127 +
  128 + //检查频道是否已经被占用
  129 + checkChannelIsOpening(_channelId){
  130 + if(_channelId==null){
  131 + loger.warn("checkChannelIsOpening error,channel=",_channelId);
  132 + return true;
  133 + }
  134 + let channelInfo=this.mediaChannels[_channelId];
  135 + if(channelInfo==null||channelInfo.status==ApeConsts.CHANNEL_STATUS_RELEASED){
  136 + return false;
  137 + }
  138 + return true;
  139 + }
  140 +}
  141 +
  142 +export default MediaModule;
  143 +
1 // ////////////////////////////////////////////////////////////////////////////// 1 // //////////////////////////////////////////////////////////////////////////////
2 -//  
3 -// Copyright (C) 2016-present All Rights Reserved.  
4 -// Licensed under the Apache License, Version 2.0 (the "License");  
5 -// http://www.apache.org/licenses/LICENSE-2.0  
6 -//  
7 -// Github Home: https://github.com/AlexWang1987  
8 -// Author: AlexWang  
9 -// Date: 2016-08-23 18:07:28  
10 -// QQ Email: 1669499355@qq.com  
11 -// Last Modified time: 2016-09-06 11:13:59  
12 -// Description: LiveClass-VideoApe  
13 -// 2 +//视频模块
14 // ////////////////////////////////////////////////////////////////////////////// 3 // //////////////////////////////////////////////////////////////////////////////
15 4
16 import Ape from './Ape'; 5 import Ape from './Ape';
@@ -20,10 +9,11 @@ import Loger from 'Loger'; @@ -20,10 +9,11 @@ import Loger from 'Loger';
20 import MessageTypes from 'MessageTypes'; 9 import MessageTypes from 'MessageTypes';
21 import GlobalConfig from 'GlobalConfig'; 10 import GlobalConfig from 'GlobalConfig';
22 import EngineUtils from 'EngineUtils'; 11 import EngineUtils from 'EngineUtils';
  12 +import MediaModule from "./MediaModule";
23 13
24 -let loger = Loger.getLoger('VideoChat'); 14 +let loger = Loger.getLoger('VideoApe');
25 15
26 -class VideoChat extends Ape { 16 +class VideoApe extends Ape {
27 constructor() { 17 constructor() {
28 super( 18 super(
29 ApeConsts.VIDEO_SESSION_ID, 19 ApeConsts.VIDEO_SESSION_ID,
@@ -31,8 +21,9 @@ class VideoChat extends Ape { @@ -31,8 +21,9 @@ class VideoChat extends Ape {
31 ApeConsts.VIDEO_SESSION_TAG 21 ApeConsts.VIDEO_SESSION_TAG
32 ); 22 );
33 23
34 - //Attributes  
35 - this.videoChannels = {}; 24 + this.mediaModule=new MediaModule();
  25 + this.mediaModule.MEDIA_OBJ_TABLE_ID=ApeConsts.VIDEO_OBJ_TABLE_ID;
  26 + this.mediaModule.mediaChannels={};
36 27
37 // Ape Models 28 // Ape Models
38 this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer); 29 this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
@@ -41,84 +32,23 @@ class VideoChat extends Ape { @@ -41,84 +32,23 @@ class VideoChat extends Ape {
41 // videoApe 监听视频控制消息,用户之间的消息传递 32 // videoApe 监听视频控制消息,用户之间的消息传递
42 this.on(pdu.RCPDU_VIDEO_SEND_DATA_REQUEST, this.receiveVideoCommandHandler.bind(this)); 33 this.on(pdu.RCPDU_VIDEO_SEND_DATA_REQUEST, this.receiveVideoCommandHandler.bind(this));
43 } 34 }
  35 + //ape加入成功
  36 + onJoinChannelHandlerSuccess(){
  37 + //这个设置很重要,因为只有Sass流程完成之后,APE才能取得GlobalConfig中的数据
  38 + this.mediaModule.maxMediaChannel=GlobalConfig.maxVideoChannels;
  39 + }
44 40
45 /////////////发送数据操作//////////////////////////////////////////// 41 /////////////发送数据操作////////////////////////////////////////////
46 //获取播流地址 42 //获取播流地址
47 getPlayVideoPath(_param) { 43 getPlayVideoPath(_param) {
48 loger.log('getPlayVideoPath'); 44 loger.log('getPlayVideoPath');
49 - if (_param == null||_param.siteId == null||  
50 - _param.classId == null||_param.userId == null||  
51 - _param.channelId == null|| _param.timestamp==null)  
52 - {  
53 - loger.warn('getPlayVideoPath,参数错误', _param);  
54 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);  
55 - return {"code": 1, "data": ""};  
56 - }  
57 -  
58 - let path = "";  
59 - let port="";  
60 - if (_param.type == "m3u8") {  
61 - //M3U8  
62 - //http://123.56.73.119:6001/hls/h5dev_403074980_0_983041_1487663265/index.m3u8  
63 - port = (GlobalConfig.RSServerPort == "" || GlobalConfig.RSServerPort == null) ? "":":" + GlobalConfig.RSServerPort;  
64 - path = "http://" + GlobalConfig.RSServerIP  
65 - + port + "/live/"  
66 - + _param.siteId  
67 - + "_" + _param.classId  
68 - + "_" + _param.userId  
69 - + "_" + _param.channelId  
70 - + "_" + _param.timestamp  
71 - + "/index.m3u8";  
72 - } else {  
73 - port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "":":" + GlobalConfig.MSServerPort;  
74 - path = "rtmp://" + GlobalConfig.MSServerIP  
75 - + port + "/live/"  
76 - + _param.siteId  
77 - + "_" + _param.classId  
78 - + "_" + _param.userId  
79 - + "_" + _param.channelId  
80 - + "_" + _param.timestamp;  
81 - }  
82 - return {"code": 0, "data": path}; 45 + return this.mediaModule.getMediaPlayPath(_param);
83 } 46 }
84 47
85 //获取推流地址 48 //获取推流地址
86 getPublishVideoPath(_param) { 49 getPublishVideoPath(_param) {
87 loger.log('getPublishVideoPath'); 50 loger.log('getPublishVideoPath');
88 -  
89 - //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启  
90 - let freeChannel = this.getFreeVideoChannel();  
91 - if (freeChannel == 0) {  
92 - return {"code": 1, "data": "不能再打开更多的设备"};  
93 - }  
94 -  
95 - //默认方式推流  
96 - let pubType="live";  
97 - //flash推流  
98 - if(_param&&_param.type=="flash"){  
99 - pubType ="flash";  
100 - }  
101 -  
102 - //端口,有端口就显示 ":xxx",没有端口就是""  
103 - let port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "":":" + GlobalConfig.MSServerPort;  
104 - //时间戳  
105 - let timestamp = EngineUtils.creatTimestamp();  
106 -  
107 - //生成推流地址和推流数据(同步数据的时候用)  
108 - let publishUrl = "rtmp://" + GlobalConfig.MSServerIP  
109 - + port + "/"+pubType+"/" +GlobalConfig.siteId+"_"  
110 - + GlobalConfig.classId + "_"+GlobalConfig.userId  
111 - +"_" + freeChannel + "_" + timestamp;  
112 - return {"code": 0,  
113 - "data":  
114 - { "siteId":GlobalConfig.siteId,  
115 - "classId":GlobalConfig.classId,  
116 - "userId":GlobalConfig.userId,  
117 - "channelId": freeChannel,  
118 - "timestamp": timestamp,  
119 - "publishUrl": publishUrl  
120 - }  
121 - }; 51 + return this.mediaModule.getMediaPublishPath(_param);
122 } 52 }
123 53
124 //推流 54 //推流
@@ -129,28 +59,28 @@ class VideoChat extends Ape { @@ -129,28 +59,28 @@ class VideoChat extends Ape {
129 { 59 {
130 loger.warn('publishVideo,参数错误', _param); 60 loger.warn('publishVideo,参数错误', _param);
131 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); 61 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
132 - return {"code": 1, "data": ""}; 62 + return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"};
133 } 63 }
134 64
135 loger.log('publishVideo -> maxVideoChannels', GlobalConfig.maxVideoChannels); 65 loger.log('publishVideo -> maxVideoChannels', GlobalConfig.maxVideoChannels);
136 66
137 //同一个nodeId只允许推一个流,如果已经推了就不能再推 67 //同一个nodeId只允许推一个流,如果已经推了就不能再推
138 - if(this.getOpeningVideoChannel(GlobalConfig.nodeId)!=0){ 68 + if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){
139 loger.warn("publishVideo,已经存在一个流,不能再推"); 69 loger.warn("publishVideo,已经存在一个流,不能再推");
140 - return; 70 + return {"code": ApeConsts.RETURN_FAILED, "data": "已经存在一个流,不能再推"};
141 } 71 }
142 72
143 //判断当前是否还有空闲的channle 73 //判断当前是否还有空闲的channle
144 - let freeChannel = this.getFreeVideoChannel(); 74 + let freeChannel = this.mediaModule.getFreeMediaChannel();
145 if (freeChannel == 0) { 75 if (freeChannel == 0) {
146 loger.warn("publishVideo,没有空闲的channel "); 76 loger.warn("publishVideo,没有空闲的channel ");
147 - return {"code": 1, "data": "不能再打开更多的设备"}; 77 + return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"};
148 } 78 }
149 79
150 //判断当前的频道是否已经占用 80 //判断当前的频道是否已经占用
151 - if(this.checkChannelIsOpening(_param.channelId)){ 81 + if(this.mediaModule.checkChannelIsOpening(_param.channelId)){
152 loger.warn(_param.channelId,"频道已经被占用"); 82 loger.warn(_param.channelId,"频道已经被占用");
153 - return {"code":1,"data":"频道已经被占用!"}; 83 + return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!"};
154 } 84 }
155 85
156 let channelInfo={}; 86 let channelInfo={};
@@ -163,7 +93,7 @@ class VideoChat extends Ape { @@ -163,7 +93,7 @@ class VideoChat extends Ape {
163 channelInfo.toNodeId=0; 93 channelInfo.toNodeId=0;
164 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_VIDEO; 94 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_VIDEO;
165 this.sendTableUpdateHandler(channelInfo); 95 this.sendTableUpdateHandler(channelInfo);
166 - return {"code":0,"data":"推流成功!"} 96 + return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!"}
167 } 97 }
168 98
169 //停止推流, 99 //停止推流,
@@ -177,10 +107,10 @@ class VideoChat extends Ape { @@ -177,10 +107,10 @@ class VideoChat extends Ape {
177 nodeId=GlobalConfig.nodeId; 107 nodeId=GlobalConfig.nodeId;
178 } 108 }
179 109
180 - let openingChannel = this.getOpeningVideoChannel(nodeId); 110 + let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId);
181 if (openingChannel == 0) { 111 if (openingChannel == 0) {
182 - loger.warn(nodeId,"stopPublishVideo,没有打开的channel,不需要关闭");  
183 - return {"code": 1, "data": "没有打开的channel,不需要关闭"}; 112 + loger.warn(nodeId,"stopPublishVideo,没有占用channel,不需要关闭");
  113 + return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel,不需要关闭"};
184 } 114 }
185 115
186 let channelInfo={}; 116 let channelInfo={};
@@ -201,23 +131,22 @@ class VideoChat extends Ape { @@ -201,23 +131,22 @@ class VideoChat extends Ape {
201 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN); 131 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
202 return {"code": 1, "data": "不能发送Video消息.McuClient还未初始化数据"}; 132 return {"code": 1, "data": "不能发送Video消息.McuClient还未初始化数据"};
203 } 133 }
204 - return {"code": 1, "data": "不能发送Video消息.McuClient还未初始化数据"}; 134 + return {"code": ApeConsts.RETURN_FAILED, "data": "不能发送Video消息.McuClient还未初始化数据"};
205 } 135 }
206 if (_param == null) { 136 if (_param == null) {
207 loger.warn('sendVideoCommandMsg失败,参数错误', _param); 137 loger.warn('sendVideoCommandMsg失败,参数错误', _param);
208 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); 138 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
209 - return {"code": 1, "data": "sendVideoCommandMsg失败,参数错误"};  
210 - ; 139 + return {"code": ApeConsts.RETURN_FAILED, "data": "sendVideoCommandMsg失败,参数错误"};
211 } 140 }
212 // to, message 141 // to, message
213 loger.log('发送Video消息.', _param); 142 loger.log('发送Video消息.', _param);
214 143
215 if (_param.actionType != null && _param.actionType == ApeConsts.MEDIA_ACTION_OPEN_CAMERA) { 144 if (_param.actionType != null && _param.actionType == ApeConsts.MEDIA_ACTION_OPEN_CAMERA) {
216 //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启 145 //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
217 - let freeChannel = this.getFreeVideoChannel(); 146 + let freeChannel = this.mediaModule.getFreeMediaChannel();
218 if (freeChannel == 0) { 147 if (freeChannel == 0) {
219 loger.warn('sendVideoCommandMsg,不能再打开更多的设备', _param); 148 loger.warn('sendVideoCommandMsg,不能再打开更多的设备', _param);
220 - return {"code": 1, "data": "不能再打开更多的设备"}; 149 + return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"};
221 } 150 }
222 } 151 }
223 /* message RCVideoSendDataRequestPdu { 152 /* message RCVideoSendDataRequestPdu {
@@ -246,7 +175,7 @@ class VideoChat extends Ape { @@ -246,7 +175,7 @@ class VideoChat extends Ape {
246 loger.log('发送公聊Video消息.'); 175 loger.log('发送公聊Video消息.');
247 this.sendChatUniform(videoSendPdu); 176 this.sendChatUniform(videoSendPdu);
248 } 177 }
249 - return {"code": 0, "data": ""}; 178 + return {"code": ApeConsts.RETURN_SUCCESS, "data": ""};
250 } 179 }
251 180
252 sendTableUpdateHandler(_channelInfo) { 181 sendTableUpdateHandler(_channelInfo) {
@@ -314,45 +243,15 @@ class VideoChat extends Ape { @@ -314,45 +243,15 @@ class VideoChat extends Ape {
314 if (videoReceivePdu.toNodeId != 0 && videoReceivePdu.toNodeId != GlobalConfig.nodeId) { 243 if (videoReceivePdu.toNodeId != 0 && videoReceivePdu.toNodeId != GlobalConfig.nodeId) {
315 loger.log('视频消息不处理 toNodeId=', videoReceivePdu.toNodeId, "my nodeId=", GlobalConfig.nodeId); 244 loger.log('视频消息不处理 toNodeId=', videoReceivePdu.toNodeId, "my nodeId=", GlobalConfig.nodeId);
316 } else { 245 } else {
317 - this._emit(MessageTypes.VIDEO_COMMAND, videoReceivePdu); 246 + this._emit(MessageTypes.VIDEO_BROADCAST, videoReceivePdu);
318 } 247 }
319 } 248 }
320 249
321 tableUpdateHandler(owner, itemIdx, itemData) { 250 tableUpdateHandler(owner, itemIdx, itemData) {
322 // debugger; 251 // debugger;
323 let videoChannelInfo = this.unPackPdu(owner, itemIdx, itemData); 252 let videoChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
324 - //videoChannelInfo.owner = owner;  
325 - //videoChannelInfo.channelId = itemIdx;  
326 - //videoChannelInfo.status = owner === 0 ? ApeConsts.CHANNEL_STATUS_RELEASED : videoChannelInfo.status;  
327 - //loger.log('视频消息处理 tableUpdateHandler.',videoChannelInfo);  
328 - this.videoChannels[itemIdx] = videoChannelInfo;  
329 - 253 + this.mediaModule.mediaChannels[itemIdx] = videoChannelInfo;
330 this._emit(MessageTypes.VIDEO_UPDATE, videoChannelInfo); 254 this._emit(MessageTypes.VIDEO_UPDATE, videoChannelInfo);
331 - /* switch (videoChannelInfo.status) {  
332 - case ApeConsts.CHANNEL_STATUS_RELEASED:  
333 - // 只能关闭自己的流  
334 - if (this.activeChannelId === videoChannelInfo.channelId) {  
335 - this.activeChannelId = 0;  
336 - this.activeURL = '';  
337 - this.emitVideoChange();  
338 - }  
339 - break;  
340 - case ApeConsts.CHANNEL_STATUS_OPENING:  
341 - //_playUrl = "rtmfp://" + Config.mediaServerAddr + ":" + Config.mediaServerPort + "/message/" + _streamName;  
342 - //_cdnUrl = "rtmp://" + Config.mediaCDNServerAddr + ":" + Config.mediaCDNServerPort + "/message/" + _streamName;  
343 - //this.activeChannelId = videoChannelInfo.channelId;  
344 - //// AMS/FMS  
345 - //if (this._classInfo.msType ==ApeConsts.MS_TYPE_FMS) {  
346 - // this.activeURL = `http://dazhi.3mang.com/live/${this._classInfo.classId}/${this._classInfo.classId}_${videoChannelInfo.channelId}_flash_cam_mic_aac/playlist.m3u8`;  
347 - //}else {  
348 - // this.activeURL = `http://hls.3mang.com/live/${this._classInfo.classId}_${videoChannelInfo.channelId}_flash_cam_mic_aac/playlist.m3u8`;  
349 - //}  
350 - // 任何人都可以打开流  
351 - this.emitVideoChange();  
352 - break;  
353 - default:  
354 - break;  
355 - }*/  
356 } 255 }
357 256
358 ///////数据的封包和解包///////////////////////////////////////// 257 ///////数据的封包和解包/////////////////////////////////////////
@@ -364,14 +263,6 @@ class VideoChat extends Ape { @@ -364,14 +263,6 @@ class VideoChat extends Ape {
364 return null; 263 return null;
365 } 264 }
366 265
367 - /* message RCVideoChannelInfoPdu {  
368 - optional uint32 status = 1;//开启的状态  
369 - optional uint32 channel_id = 2;//唯一的频道id  
370 - optional uint32 timestamp = 3;//更新的时间戳  
371 - optional uint32 from_node_id = 4;//发起者的id  
372 - optional uint32 to_node_id = 5;//接收者的id,(如果是0,所有人都接收)  
373 - }*/  
374 -  
375 //判断type类型,根据type设置不同的参数 266 //判断type类型,根据type设置不同的参数
376 let packPduModel = new pdu['RCVideoChannelInfoPdu']; 267 let packPduModel = new pdu['RCVideoChannelInfoPdu'];
377 packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED; 268 packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED;
@@ -403,53 +294,7 @@ class VideoChat extends Ape { @@ -403,53 +294,7 @@ class VideoChat extends Ape {
403 } 294 }
404 return null; 295 return null;
405 } 296 }
406 -  
407 - //获取当前空闲的channel,返回值为0代表没有空闲的,否则返回的就是空闲的channelId  
408 - getFreeVideoChannel() {  
409 - loger.log("getFreeVideoChannel");  
410 - console.log(this.videoChannels);  
411 - let counter = 0;  
412 - for (let key in this.videoChannels) {  
413 - let item = this.videoChannels[key];  
414 - if (item && item.status == ApeConsts.CHANNEL_STATUS_RELEASED) {  
415 - return item.channelId;  
416 - }  
417 - counter++;  
418 - }  
419 - if (counter < GlobalConfig.maxVideoChannels) {  
420 - return ApeConsts.VIDEO_OBJ_TABLE_ID + (counter);  
421 - }  
422 - return 0;//没有空闲的  
423 - }  
424 -  
425 - //获取当前属于nodeId的已经打开的的channel,返回值为0代表没有打开的,否则返回的就是打开的channelId  
426 - getOpeningVideoChannel(_nodeId){  
427 - if(_nodeId==null||_nodeId==0){  
428 - return 0;  
429 - }  
430 - for (let key in this.videoChannels) {  
431 - let item = this.videoChannels[key];  
432 - if (item && item.status == ApeConsts.CHANNEL_STATUS_OPENING&&item.fromNodeId==_nodeId) {  
433 - return item.channelId;  
434 - }  
435 - }  
436 - return 0;  
437 - }  
438 -  
439 - //检查频道是否已经被占用  
440 - checkChannelIsOpening(_channelId){  
441 - if(_channelId==null){  
442 - loger.warn("checkChannelIsOpening error,channel=",_channelId);  
443 - return true;  
444 - }  
445 -  
446 - let channelInfo=this.videoChannels[_channelId];  
447 - if(channelInfo==null||channelInfo.status==ApeConsts.CHANNEL_STATUS_RELEASED){  
448 - return false;  
449 - }  
450 - return true;  
451 - }  
452 } 297 }
453 298
454 -export default VideoChat; 299 +export default VideoApe;
455 300
@@ -740,10 +740,16 @@ message RCGiftSendDataRequestPdu { @@ -740,10 +740,16 @@ message RCGiftSendDataRequestPdu {
740 optional bytes user_data = 5; 740 optional bytes user_data = 5;
741 } 741 }
742 742
743 -message RCAudioSendDataRequestPdu { 743 +message RCAudioSendDataRequestPdu1 {
744 optional uint32 initiator = 1; 744 optional uint32 initiator = 1;
745 required bytes user_data = 2; 745 required bytes user_data = 2;
746 } 746 }
  747 +message RCAudioSendDataRequestPdu {
  748 + required uint32 from_node_id = 1;//发起人
  749 + optional uint32 to_node_id = 2;//接收人,如果是0就是所有人都接收
  750 + optional uint32 actionType = 3;//消息指令类型;
  751 + optional bytes data = 4;//其他数据,这个根据actionType来确定数据的结构
  752 +}
747 753
748 message RCVideoSendDataRequestPdu { 754 message RCVideoSendDataRequestPdu {
749 required uint32 from_node_id = 1;//发起人 755 required uint32 from_node_id = 1;//发起人
@@ -759,6 +765,17 @@ message RCAudioChannelInfoRecordPdu { @@ -759,6 +765,17 @@ message RCAudioChannelInfoRecordPdu {
759 required uint32 bitrate = 4; 765 required uint32 bitrate = 4;
760 required uint32 codec = 5; 766 required uint32 codec = 5;
761 } 767 }
  768 +message RCAudioChannelInfoPdu {
  769 + optional uint32 status = 1;//开启的状态
  770 + optional uint32 channel_id = 2;//唯一的频道id
  771 + optional uint32 timestamp = 3;//更新的时间戳
  772 + optional uint32 from_node_id = 4;//发起者的id
  773 + optional uint32 to_node_id = 5;//接收者的id,(如果是0,所有人都接收)
  774 + optional uint32 media_type = 6;//媒体类型:视频(包含音频)或音频
  775 + optional uint32 class_id = 7;//课堂号
  776 + optional string site_id = 8;//站点号
  777 + optional string user_id = 9;//用户的userId
  778 +}
762 779
763 message RCVideoChannelInfoPdu { 780 message RCVideoChannelInfoPdu {
764 optional uint32 status = 1;//开启的状态 781 optional uint32 status = 1;//开启的状态
@@ -907,6 +924,7 @@ message RCClassStatusInfoPdu { @@ -907,6 +924,7 @@ message RCClassStatusInfoPdu {
907 optional uint32 active_doc_cur_page=21;//当前激活的文档的当前页 924 optional uint32 active_doc_cur_page=21;//当前激活的文档的当前页
908 } 925 }
909 926
  927 +
910 //end 928 //end
911 `; 929 `;
912 930