stream/audio.js

ModuleBase.define("Audio", ["Base", "Error"], function(Base, Error) {

	/**
	 * @desc 音频Audio构造函数。
	 * @constructor
	 * @alias Audio
	 * @param {String} id - 设备Id
	 * @param {String} name - 设备名称
	 */
	class Audio extends Base {
	  
	  constructor(id, name, roomHandle) {
	 	super(id, name);
		
		this.roomHandle = roomHandle;
		
		this.audioLevel = 0;  //语音激励
		
		this.isPubState = false; //防止重复发布,在发布过程中该状态为true
		
		this.isMonitorAudioLevel = false;

		this.monitorAudioLevelIntervalId = null;

		this.openTimer = null;

		this.closeTimer = null;  
		
		this.subscribleTimer =  null;

		this.unsubscribleTimer = null;
	 };
	
	
	/**
	 * @desc 打开音频及把流渲染进视频控件,同时进行publish操作。
	 * @async
	 * @param {Object} element - 音频控件对象
	 */
	openMicrophone = function(element) {
		log.info("===audio.openMicrophone()");
		var deferred = when.defer();
		
		var self = this;
        
        if(self.roomHandle.roomJoinState != RoomStateEnum.CONNECTED){
            var errObj = ErrorConstant.room_state_invalid
            errObj.message += ("(State: "+ self.roomHandle.roomJoinState +")")
            var err = new Error(errObj);
            log.debug("===audio.openMicrophone() 发布视频流异常, room state: " + self.roomHandle.roomJoinState);
            deferred.reject(err);
            return;
        }
		// var error = doFsCheck(FTConstant.audio, Error)
		// if(error) {
		// 	deferred.reject(error);
		// 	return deferred.promise;
		// }

		var orderId = getRandomNum(20000, 21000); //用于PubRoomResourceMsgRep中的ID
		
		if(self.track) {
			var microphoneUUID = self.roomHandle.setDeviceIdByUUID(2, self.id);
			var audioStream = self.getNewStreamByTrack();
			
			if(self.isPubState){
				if(self.status == StreamStatus.published){
					log.debug("===audio openMicrophone(self.track!=null),isPubState =true && self.status == StreamStatus.published to return");
					deferred.resolve();
					return deferred.promise;
				}else if(self.status == StreamStatus.muted){
					log.debug("===audio openMicrophone(self.track!=null),isPubState =true && self.status == StreamStatus.muted to audio.unmuteMicrophone()");
					self.unmuteMicrophone();
					deferred.resolve();
					return deferred.promise;
				}
			}
			
			if(self.isPubState){
				log.debug("===audio openMicrophone(self.track!=null),isPubState =true  to return");
				deferred.resolve();
				return deferred.promise;
			}
			
			
			self.isPubState = true;
			self.roomHandle.masterServer.audioPublishHandle(microphoneUUID, audioStream, orderId);
			
			clearTimeout(self.openTimer);
			self.openTimer = setTimeout(function() {
				self.isPubState = false;
				log.debug("===audio openMicrophone(self.track!=null),pub_roomresourcemsg_rep timeout");
                deferred.reject(new Error(ErrorConstant.operate_timeout.code, 'Release audio' + ErrorConstant.operate_timeout.message))
			}, 3000)

			self.roomHandle.addCallback(EngineCallback.pub_roomresourcemsg_rep_success, function(id) {
				if(id == orderId) {
					clearTimeout(self.openTimer);
					
					self.state = StreamStatus.opened;

					if(typeof(element) != 'undefined' && element && element != '') {
						self.element = element;
						element.srcObject = audioStream;
					}
					self.status = StreamStatus.published;
					if(!self.roomHandle.hasObject(self.roomHandle.pubAudios,self)){
						self.roomHandle.pubAudios.push(self);
					}
					
					log.info("===audio openMicrophone(),打开音频及发布流成功,callback microphone_status_notify  (self.track!=null),status:"+self.status+",audioId:"+ self.id+",userId:"+self.ownerId);
					avdEngineHandle.loggerReport.info("audio openMicrophone(),打开音频及发布流成功,(self.track!=null),audioId:"+ self.id+",userId:"+self.ownerId);
					self.roomHandle.selfUser.eventEmitter.emit(UserCallback.microphone_status_notify, self.status, self.id, self.name, self.roomHandle.selfUser.id);
					
					deferred.resolve();
				}
			});

			self.roomHandle.addCallback(EngineCallback.pub_roomresourcemsg_rep_error, function(error, id) {
				if(id == orderId) {
					clearTimeout(self.openTimer);
					
					self.isPubState = false;
					log.error("===audio openMicrophone(),打开音频及发布流失败,(self.track!=null),audioId:"+ self.id+",userId:"+self.ownerId+",error:"+JSON.stringify(error));
					avdEngineHandle.loggerReport.error("audio openMicrophone(),Failed to open audio and publish stream,(self.track!=null),audioId:"+ self.id+",userId:"+self.ownerId+",error:"+JSON.stringify(error));
					deferred.reject(error);
				}
			});

		} else  {
			obtainUserMedia(self, null).then(function(stream) {
					self.track = stream.audioStream.getAudioTracks()[0];
					
					if(self.roomHandle.selfUser.stream ==null){
						 self.roomHandle.selfUser.stream = stream.audioStream;
					}else{
						 self.roomHandle.selfUser.stream.addTrack(self.track);
					}
					
					self.state = StreamStatus.opened;
					
					var microphoneUUID = self.roomHandle.setDeviceIdByUUID(2, self.id);
					var audioStream = self.getNewStreamByTrack();
					
					if(self.isPubState){
						log.debug("===audio openMicrophone(self.track=null),isPubState =true  to return");
						deferred.resolve();
						return deferred.promise;
					}
					
					self.isPubState = true;
					self.roomHandle.masterServer.audioPublishHandle(microphoneUUID, audioStream, orderId);

                    clearTimeout(self.openTimer);
					self.openTimer = setTimeout(function() {
						self.isPubState = false;
						log.debug("===audio openMicrophone(self.track==null),pub_roomresourcemsg_rep timeout");
                        deferred.reject(new Error(ErrorConstant.operate_timeout.code, 'Release audio ' + ErrorConstant.operate_timeout.message))
					}, 3000)
					
					self.roomHandle.addCallback(EngineCallback.pub_roomresourcemsg_rep_success, function(id) {
						if(id == orderId) {
							clearTimeout(self.openTimer);
							
							if(typeof(element) != 'undefined' && element && element != '') {
								self.element = element;
								element.srcObject = audioStream;
							}

							self.status = StreamStatus.published;
							
							if(!self.roomHandle.hasObject(self.roomHandle.pubAudios,self)){
								self.roomHandle.pubAudios.push(self);
							}
							
							log.info("===audio openMicrophone(),打开音频及发布流成功,callback microphone_status_notify (self.track==null),status:"+self.status+",audioId:"+ self.id+",userId:"+self.ownerId);
							avdEngineHandle.loggerReport.info("audio openMicrophone(),打开音频及发布流成功,(self.track==null),audioId:"+ self.id+",userId:"+self.ownerId);
							self.roomHandle.selfUser.eventEmitter.emit(UserCallback.microphone_status_notify, self.status, self.id, self.name, self.roomHandle.selfUser.id);
							deferred.resolve();
						}
					});

					self.roomHandle.addCallback(EngineCallback.pub_roomresourcemsg_rep_error, function(error, id) {
						if(id == orderId) {
							clearTimeout(self.openTimer);
							
							self.isPubState = false;
							log.error("===audio openMicrophone(),打开音频及发布流失败,(self.track==null),audioId:"+ self.id+",userId:"+self.ownerId+",error:"+JSON.stringify(error));
							avdEngineHandle.loggerReport.error("audio openMicrophone(),Failed to open audio and publish stream,(self.track==null),audioId:"+ self.id+",userId:"+self.ownerId+",error:"+JSON.stringify(error));
					        deferred.reject(error);
						}
					});

				}).otherwise(function(e) {
					deferred.reject(e);
				});
		}
		
		return deferred.promise;
	};

                     
	/**
	 * @desc 关闭音频,同时进行unpublish操作。
	 * @async
	 */
	closeMicrophone = function() {
		log.info("===audio.closeMicrophone()");
		
		var deferred = when.defer();
		
		var self = this;
		var orderId = getRandomNum(21001, 22000);
		
		if(self.status == StreamStatus.published || self.status == StreamStatus.muted) {
			self.isPubState = false;
			
			arrayUtil.objectSplice(self.roomHandle.pubAudios, this.id);

			self.status = StreamStatus.init;
			self.roomHandle.selfUser.eventEmitter.emit(UserCallback.microphone_status_notify, self.status, self.id, self.name, self.roomHandle.selfUser.id);
			
			var microphoneUUID = self.roomHandle.setDeviceIdByUUID(2, self.id);
            var audioStream = self.getNewStreamByTrack();
			self.roomHandle.masterServer.audioUnpublishHandle(microphoneUUID, audioStream, orderId);
			
			clearTimeout(self.closeTimer);
			self.closeTimer = setTimeout(function() {
				self.isPubState = false;
				log.debug("===audio closeMicrophone,unpub_roomresourcemsg_rep timeout");
                deferred.reject(new Error(ErrorConstant.operate_timeout.code, 'Unpublish audio' + ErrorConstant.operate_timeout.message))
			}, 3000);
			
			self.roomHandle.addCallback(EngineCallback.unpub_roomresourcemsg_rep_success, function(id) {
				if(id == orderId) {
					clearTimeout(self.closeTimer);
					
					//第三方导入流closeMicrophone时,不对本地track清场,在user.deleteCustomAudioTrack()时统一清场。
					if(self.id.indexOf('custom_audio') !== -1 ){
						self.setAudioLevel(0);
						var stream = self.roomHandle.selfUser.stream;
						if(stream){
							stream.getTracks().forEach(function(track) {
								if(self.track && self.track.id == track.id){
									track.stop();
								}
							});
						}
								
						if(self.element) {
							var elementStream = self.element.srcObject;
							if(elementStream){
								elementStream.getTracks().forEach(function(track) {
									 track.stop();
								});
							}
							
							self.element.srcObject = null;
							self.element = null;
						}
								   
						self.track.stop();
						self.track = null;
					}
					
					log.info("===audio closeMicrophone(),关闭音频及取消发布流. audioId:"+ self.id+",userId:"+self.ownerId);
					avdEngineHandle.loggerReport.info("audio closeMicrophone(),关闭音频及取消发布流操作. audioId:"+ self.id+",userId:"+self.ownerId);
					
					setTimeout(function(){
						deferred.resolve();
					},50);
				}
			});
			
			self.roomHandle.addCallback(EngineCallback.unpub_roomresourcemsg_rep_error, function(error, id) {
				if(id == orderId) {
					clearTimeout(self.closeTimer);
					
					self.isPubState = false;
					log.error("===audio closeMicrophone(),关闭音频及发布流失败. audioId:"+ self.id+",userId:"+self.ownerId+",error:"+JSON.stringify(error));
					avdEngineHandle.loggerReport.error("audio closeMicrophone(),Failed to close the audio and publish stream. audioId:"+ self.id+",userId:"+self.ownerId+",error:"+JSON.stringify(error));
					deferred.reject(error);
				}
			});
		}
		
		return deferred.promise;
	};
	
	
	
	/**
	 * @desc 订阅音频流
	 * @async
	 */ 
	subscrible = function() {
		  log.info("===audio subscrible(),订阅音频流操作, audioId:"+ this.id+",userId:"+this.ownerId);
		  avdEngineHandle.loggerReport.info("audio subscrible(),订阅音频流操作, audioId:"+ this.id+",userId:"+this.ownerId);
		  
		  var deferred = when.defer();
		  
		  var orderId = getRandomNum(22001, 23000);
		  
		  var self = this;
		  self.roomHandle.masterServer.audioSubscribleHandle(self.resourceInfo,orderId); 
		  
		  clearTimeout(self.subscribleTimer);
		  self.subscribleTimer = setTimeout(function() {
		  	log.debug("===audio subscrible, sub_roomresourcemsg_rep_success timeout");
              deferred.reject(new Error(ErrorConstant.operate_timeout.code, 'Subscribe to audio' + ErrorConstant.operate_timeout.message))
		  }, 3000);
		  
		  self.roomHandle.addCallback(EngineCallback.sub_roomresourcemsg_rep_success, function(id) {
				if(id == orderId) {
					clearTimeout(self.subscribleTimer);
					
					setTimeout(function(){
						log.info("===audio subscrible(),订阅音频流成功,audioId:"+ self.id+",userId:"+self.ownerId);
						deferred.resolve();
					},50);
				}
		  });
		  
		  self.roomHandle.addCallback(EngineCallback.sub_roomresourcemsg_rep_error, function(error, id) {
				if(id == orderId) {
					clearTimeout(self.subscribleTimer);
					deferred.reject(error);
				}
		  });
		  
		  return deferred.promise;
	}
	
	

	/**
	 * @desc 取消订阅音频流
	 * @async
	 */
	unsubscrible = function() {
		log.info("===audio unsubscrible(),取消订阅音频流操作,audioId:"+ this.id+",userId:"+this.ownerId);
		avdEngineHandle.loggerReport.info("audio unsubscrible(),取消订阅音频流操作,audioId:"+ this.id+",userId:"+this.ownerId);
		
		var deferred = when.defer();
		var orderId = getRandomNum(23001, 24000);
		
		var self = this;
		
		//console.log("===audio unsubscrible(),this.resourceInfo.stream.stream_name:"+this.resourceInfo.stream.stream_name);
		self.roomHandle.masterServer.audioUnsubscribleHandle(this.resourceInfo,orderId);
		
		clearTimeout(self.unsubscribleTimer);
		self.unsubscribleTimer = setTimeout(function() {
			log.debug("===audio unsubscrible, unsub_roomresourcemsg_rep_success timeout");
            deferred.reject(new Error(ErrorConstant.operate_timeout.code, 'Unsubscribe Audio' + ErrorConstant.operate_timeout.message))
		}, 3000);
		
		self.roomHandle.addCallback(EngineCallback.unsub_roomresourcemsg_rep_success, function(id) {
			if(id == orderId) {
				clearTimeout(self.unsubscribleTimer);
				
				setTimeout(function(){
					log.info("===audio unsubscrible(),取消订阅音频流成功,audioId:"+ self.id+",userId:"+self.ownerId);
					deferred.resolve();
				},50);
			}
		});
		
		self.roomHandle.addCallback(EngineCallback.unsub_roomresourcemsg_rep_error, function(error, id) {
			if(id == orderId) {
				clearTimeout(self.unsubscribleTimer);
				deferred.reject(error);
			}
		});
		
		return deferred.promise;
	}
	


	/**
	 * @desc 禁音
	 */
	muteMicrophone = function() {
		log.info("===audio.muteMicrophone()");
		var self = this;
		if(this.status == StreamStatus.published) {
			this.status = StreamStatus.muted;
			self.roomHandle.selfUser.eventEmitter.emit(UserCallback.microphone_status_notify, this.status, this.id, this.name, self.roomHandle.selfUser.id);

            var stream = self.roomHandle.selfUser.stream;
			stream.getTracks().forEach(function(track) {
				if(track.id ==  self.track.id){
				  	track.enabled = false;
				}
			});
		
			if(self.element) {
				var elementStream = self.element.srcObject;
				if(elementStream){
					elementStream.getTracks().forEach(function(track) {
						if(track.id ==  self.track.id){
						   track.enabled = false;
						}
					});
				}
			}
			
            if(self.track){
            	self.track.enabled = false;
            }
			
			var senders = self.roomHandle.traceablePeerConnection.getToMCUPeerConnection().getSenders();
			//console.log("AAAAAAA00000000,senders:",senders);
			if(senders){
				for (var i = 0; i < senders.length; i++) {
                    var sender = senders[i];
                    //console.log("AAAAAAA1111111111111,sender:",sender);
                    if(sender && sender.track && sender.track.kind == "audio" && sender.track.id == self.track.id){
                        // console.log("AAAAAAA2222222222,sender.track.enabled:",sender.track.enabled);
                        sender.track.enabled = false;
                    }
				}
			}
			
			var microphoneUUID = self.roomHandle.setDeviceIdByUUID(2, this.id);
			self.roomHandle.masterServer.updateSpeakerMsg(self.roomHandle.selfUser.nodeId, microphoneUUID, this);
			
			log.info("===audio muteMicrophone(),禁音. Id:"+ self.id+",ownerId:"+self.ownerId+",status:"+self.status);
			avdEngineHandle.loggerReport.info("audio muteMicrophone(),禁音. Id:"+ self.id+",ownerId:"+self.ownerId+",status:"+self.status);
		}
	};


	/**
	 * @desc 取消禁音
	 */
	unmuteMicrophone = function() {
		log.info("===audio.unmuteMicrophone()");
		var self = this;
		if(this.status == StreamStatus.muted) {
			this.status = StreamStatus.published;
			self.roomHandle.selfUser.eventEmitter.emit(UserCallback.microphone_status_notify, this.status, this.id, this.name, self.roomHandle.selfUser.id);

            var stream = self.roomHandle.selfUser.stream;
			stream.getTracks().forEach(function(track) {
				  if(track.id ==  self.track.id){
				  	   track.enabled = true;
				  }
			});
		
			if(self.element) {
				var elementStream = self.element.srcObject;
				if(elementStream){
					elementStream.getTracks().forEach(function(track) {
						 if(track.id ==  self.track.id){
							track.enabled = true;
						 }
					});
				}
			}
			
            if(self.track){
            	self.track.enabled = true;
            }
			
			var senders = self.roomHandle.traceablePeerConnection.getToMCUPeerConnection().getSenders();
			if(senders){
				for (var i = 0; i < senders.length; i++) {
					 var sender = senders[i];
					 if(sender && sender.track && sender.track.kind == "audio" && sender.track.id == self.track.id){
                        sender.track.enabled = true;
					 } 
				}
			}
			
			var microphoneUUID = self.roomHandle.setDeviceIdByUUID(2, this.id);
			self.roomHandle.masterServer.updateSpeakerMsg(self.roomHandle.selfUser.nodeId, microphoneUUID, this);
			
			log.info("===audio unmuteMicrophone(),取消禁音. Id:"+ self.id+",ownerId:"+self.ownerId+",status:"+self.status);
			avdEngineHandle.loggerReport.info("audio unmuteMicrophone(),取消禁音. Id:"+ self.id+",ownerId:"+self.ownerId+",status:"+self.status);
		}
	};

	/**
	 * @desc 获取禁音状态
	 */
	ismuteMicrophone = function() {
		var ismute = false;
		if(this.status == StreamStatus.muted) {
			ismute = true;
		}
		return ismute;
	};
	
	
	
	
	/**
	 * @desc 设置语音激励级别
	 * @param {int} audioLevel -语音激励级别 
	 */
	setAudioLevel = function(audioLevel) {
		this.audioLevel = audioLevel;
	};
	
	
	/**
	 * @desc 获取语音激励级别
	 */
	getAudioLevel = function() {
		return this.audioLevel;
	};

  }
	return Audio;
});