1 /**
  2  * IMPORTANT NOTES ON CLASS
  3  *
  4 
  5 Used to listen to call control Zebra
  6 Should be off by default to avoid interfering with Flash / Mobile existing implementations
  7 Should be enabled as needed
  8 Methods called in Platform in case in future used on other platforms.
  9 ZEBRA <?xml version="1.0"  encoding="UTF-8" ?><zebra fmt="2.0" username="VB2ZHDKROEBXZA7U5HCS2QROAP92WZ9RZT6SL7W7PO" service="saypage" event="SERVER_REDIRECT" error_code="0" anchor="" seq=""><zconfig></zconfig><zevent><connectmode>2</connectmode><destination>zen:VS7</destination><isP2P>true</isP2P><openfire></openfire><tracker>ZBE</tracker><type>VIDEODIAL</type><zenonserver></zenonserver></zevent></zebra> 
 10 
 11 **/
 12 /**
 13                 @name CallManager
 14                 @class  This class allows you to place and receive voice and video calls as well as mute and speaker controls.
 15 **/
 16 CallManager = EventDispatcher.extendAsSingleton({
 17     AUTO_ANSWER: true,
 18     ZUID: 1,
 19     CALL_HANDLING: false,
 20     CAM_MIC: "cammic",
 21     MIC: "mic",
 22     VOICE: "VOICE",
 23     VIDEO: "VIDEO",
 24     W2SPort: "10060",
 25     _callToken: null,
 26     _ss_window: null,
 27     _type: "VIDEO",
 28     _destination: null,
 29     _mcuCall: false,
 30     _initCallInner: null,
 31     _initCallInnerSetTime: null,
 32     _initCallInnerTimeout: 60 * 1000,
 33     _establishMonitorId: null,
 34     _showLVDelayId: null,
 35     _establishMonitorTimeout: 1 * 60 * 1000,
 36     _showLVDelayIdTimeout: 1.3 * 1000,
 37     _keepConnected: null,
 38     _sendPhoneParam: true,
 39     _videoMuted: false,
 40     _playMedia: false,
 41     _selfX: -1,
 42     _selfY: -1,
 43     _selfWidth: -1,
 44     _selfHeight: -1,
 45     _selfXCache: -1,
 46     _selfYCache: -1,
 47     _selfWidthCache: -1,
 48     _selfHeightCache: -1,
 49     _videoWidth: -1,
 50     _videoHeight: -1,
 51     _hangUpIfNoSR: false,
 52     _hangUpIfNoSRTS: 10000,
 53     _flashEnabled: false,
 54     _establish:false,
 55     _srCommandID:-1,
 56     recordwb:true,
 57 
 58     Event: {
 59                   /**
 60                         @name CallManager#Event_INCOMING_CALL
 61                         @description Event fired on incoming call
 62                         @type object
 63                   **/
 64         INCOMING_CALL: "INCOMING_CALL", //data: nil
 65                   /**
 66                         @name CallManager#Event_CONNECTED
 67                         @description Event fired on call connected
 68                         @type object
 69                   **/
 70         CONNECTED: "CONNECTED", //data: nil
 71                   /**
 72                         @name CallManager#Event_CONNECTING
 73                         @description Event fired on call connecting
 74                         @type object
 75                   **/
 76         CONNECTING: "CONNECTING", //data: nil
 77                   /**
 78                         @name CallManager#Event_INIT
 79                         @description Event fired on call manager initialized
 80                         @type object
 81                   **/
 82         INIT: "INIT", //data: nil
 83                   /**
 84                         @name CallManager#Event_FAILED
 85                         @description Event fired on call failed
 86                         @type object
 87                   **/
 88         FAILED: "FAILED", //data: nil
 89                   /**
 90                         @name CallManager#Event_ENDED
 91                         @description Event fired on call ended
 92                         @type object
 93                   **/
 94         ENDED: "ENDED", //data: nil
 95                   /**
 96                         @name CallManager#Event_RINGING
 97                         @description Event fired on remote ringing
 98                         @type object
 99                   **/
100         RINGING: "RINGING", //data: nil
101         SET_LV: "SET_LV", //data: nil
102         HIDE_LV: "HIDE_LV", //data: nil
103 		/**
104 			@name CallManager#Event_RECONNECTING
105 			@description Event fired on call switching between p2p and server
106 			@type object
107 		**/
108 	TIME_ELAPSED: "TIME_ELAPSED",
109 		/**
110 			@name CallManager#Event_TIME_ELAPSED
111 			@description Event fired as call time changes
112 			@type object
113 		**/
114 	RECONNECTING: "RECONNECTING",//data: nil
115 		/**
116 			@name CallManager#Event_RECONNECTED
117 			@description Event fired on call switching between p2p and server
118 			@type object
119 		**/
120 	RECONNECTED: "RECONNECTED", //data: nil		
121         ZEBRA: function(zebraEvent) {
122             return "ZEBRA:" + zebraEvent;
123         } //data: zebra
124     },
125     /**
126      * Constructor
127      **/
128     init: function() {
129         this._super();
130         //public APIs to add/remove listeners
131         this.addListener = this._addListener;
132         this.removeListener = this._removeListener;
133         this.removeAllListenersForEvent = this._removeAllListenersForEvent;
134         // listen for incoming Zebra, if auto answer do it else fireevent	
135         ConnectionManager.addListener("ZEBRA:IncomingCall", this, this.incomingCall);
136         ConnectionManager.addListener("ZEBRA:SERVER_REDIRECT", this, this.serverRedirect);
137         ConnectionManager.addListener("MCUDISCONNECT", this, this.disconnectCall);
138         ConnectionManager.addListener("ZENONWAKEFAIL", this, this.disconnectCall);
139         ConnectionManager.addListener("ZWRTC_SIP_CALL_FAILED", this, this.endCall);
140         ConnectionManager.addListener("ZWRTC_SIP_CALL_TERMINATED", this, this.endCall);
141         ConnectionManager.addListener("FLASH_CALL_TERMINATED", this, this.endCall);
142         ConnectionManager.addListener("ZWRTC_P2P_ESTABLISHED", this, this.p2pEstablished);
143         ConnectionManager.addListener("ZWRTC_CALL_ESTABLISHED", this, this.callEstablished);
144 	ConnectionManager.addListener("RECORDING_CALL", this, this.recordingCall);
145         ConnectionManager.addListener("ZWRTC_P2P_FAILED", this, this.p2pFailed);
146         ConnectionManager.addListener("ZWRTC_SET_WEBCAM_ACTIVE", this, this.setWebCamActive);
147         ConnectionManager.addListener("ZWRTC_AUDIO_MUTE_TOGGLED", this, this.audioToggled);
148         ConnectionManager.addListener("ZWRTC_VIDEO_MUTE_TOGGLED", this, this.videoToggled);
149         ConnectionManager.addListener("SHARE_SCREEN_START", this, this.shareScreenStart);
150         ConnectionManager.addListener("SHARE_SCREEN_STOP", this, this.shareScreenStop);
151         ConnectionManager.addListener("ZEBRA:SHARE_SCREEN_STOPPED", this, this.shareScreenStopped);
152         ConnectionManager.addListener("SHARE_SCREEN_STOPPED", this, this.shareScreenStopped);
153         ConnectionManager.addListener(ConnectionManager.Event.ZS_STATE_CHANGED, this, this.checkCall);
154         ConnectionManager.addListener("ZEBRA:RESET_OCCURRED", this, this.checkCall);
155         ConnectionManager.addListener("ZEBRA:MULTI_ALTERNATIVE_STREAM", this, this.mapt);
156         this.addListener(this.Event.CONNECTING, this, this.mapt);
157         this.addListener(this.Event.CONNECTED, this, this.mapt);
158 		this.addListener(this.Event.RECONNECTING, this, this.mapt);
159         this.addListener(this.Event.RECONNECTED, this, this.mapt);
160     },
161     mapt: function(zebra) {
162 
163     	var isZebra=false;
164    	if (zebra && (typeof zebra.getZEvent !='undefined'))
165 		isZebra=true;
166 
167 	var pauseMove=false;
168 	if (isZebra) {
169 		if (zebra.getZEvent("view_mode") && zebra.getZEvent("view_mode").value=="media") {
170 			CallManager._playMedia=true;
171 		} else {
172 			CallManager._playMedia=false;
173 		}
174 		pauseMove=true;
175 		if ( zebra.getZEvent("selfX") && zebra.getZEvent("selfX").value && parseInt(zebra.getZEvent("selfX").value)>=0 ) {
176                         CallManager._selfXCache=parseInt(zebra.getZEvent("selfX").value);
177                         CallManager._selfYCache=parseInt(zebra.getZEvent("selfY").value);
178                         CallManager._selfWidthCache=parseInt(zebra.getZEvent("selfWidth").value);
179                         CallManager._selfHeightCache=parseInt(zebra.getZEvent("selfHeight").value);
180 		} else {
181                         CallManager._selfXCache=-1;
182                         CallManager._selfYCache=-1;
183                         CallManager._selfWidthCache=-1;
184                         CallManager._selfHeightCache=-1;
185 		}
186 		if (zebra.getZEvent("videoWidth") && zebra.getZEvent("videoWidth").value && parseInt(zebra.getZEvent("videoWidth").value)>=0) {
187                         	CallManager._videoWidth=parseInt(zebra.getZEvent("videoWidth").value);
188                         	CallManager._videoHeight=parseInt(zebra.getZEvent("videoHeight").value);
189 		}
190     }
191 
192 	if (CallManager._videoWidth==-1) {
193 		CallManager._videoWidth=zwrtc.cam_width;
194         CallManager._videoHeight=zwrtc.cam_height;
195 	}
196 
197 	if (zwrtc._video &&  zwrtc.isConnected() && zwrtc.isMCU()) {
198                         CallManager._selfX=CallManager._selfXCache;
199                         CallManager._selfY=CallManager._selfYCache;
200                         CallManager._selfWidth=CallManager._selfWidthCache;
201                         CallManager._selfHeight=CallManager._selfHeightCache;
202         }else{
203                         CallManager._selfX=-1;
204                         CallManager._selfY=-1;
205                         CallManager._selfWidth=-1;
206                         CallManager._selfHeight=-1;
207 	}
208 
209 	
210 	// if pauseMove send hide LV and schedule a set LV time out which can be cancelled if another comes along in time 
211 
212 		if (pauseMove) {
213             CallManager._showLVDelayId = DateTimeUtil.getNow();
214             var update_ = CallManager._showLVDelayId;
215             setTimeout(function() {
216                 if (update_ == CallManager._showLVDelayId) {
217 					CallManager._dispatchEvent(CallManager.Event.SET_LV);
218                 }
219             }, CallManager._showLVDelayIdTimeout);
220 			CallManager._dispatchEvent(CallManager.Event.HIDE_LV);
221 		} else {
222 			CallManager._dispatchEvent(CallManager.Event.SET_LV);
223 		}
224     },
225     startScreenShare: function(username) {
226         if (username == null)
227             username = DataStore.getUserData("username", "");
228         var mcuIPPort = this.getServerIP() + ":" + DataStore.getUserData("mcu_sip_port", "");
229         var screenURL = "https://" + window.location.host + "/user/portal/share.jsp?session=" + "SHADOW_SCREEN_" + username + "&port=" + CallManager.W2SPort + "&mcu=" + mcuIPPort;
230         this._ss_window = window.open(screenURL, 'tr', 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,left=60,top=60,width=450,height=200');
231         CallManager._videoMuted = webRTC.isVideoMuted;
232         if (!webRTC.isVideoMuted) {
233             webRTC.disableVideo();
234         }
235     },
236     switchViewOnly: function() {
237         //we can directly call zwrtc.switchViewOnly() or dispatch SWITCH_VIEW_ONLY event
238         ConnectionManager._dispatchEvent("SWITCH_VIEW_ONLY", {
239             'msg': ''
240         });
241     },
242     shareScreenStart: function(evt) {
243         this.shareScreenStop();
244         this.startScreenShare(null);
245     },
246     isSharingScreen: function() {
247         return (this._ss_window != null);
248     },
249     shareScreenStop: function(evt) {
250         if (this._ss_window) {
251             this._ss_window.close();
252             this._ss_window = null;
253         }
254     },
255     shareScreenStopped: function(evt) {
256         showMessage("Screen Share Ended", "", false, null, null, null, true, 1500);
257         if (!CallManager._videoMuted) {
258             webRTC.enableVideo();
259             CallManager._videoMuted = false;
260         }
261     },
262     setWebCamActive: function(evt) {
263         Platform.log("CallManager setWebCamActive:" + evt.isVideoMuted);
264         var active = "yes";
265         if (evt.isVideoMuted)
266             active = "no";
267         Platform.httpRequest(
268             "POST", CallManager.getEndPoint() + (ConnectionManager.ZSServlet || ""),
269             null,
270             "comm=sendMessageToMCU" +
271             "&command=setwebcamactive" +
272             "&value=" + active +
273             "&username=" + (DataStore.getUserData("username", "")) +
274             "&service=" + (ConnectionManager.service || ""),
275             null
276         );
277     },
278     videoToggled: function(evt) {
279         var zebra = new Zebra("com.requestec.smg.apps.ZenDevice#setCam");
280         if (evt.mute)
281             zebra.setZEvent("cam", "false");
282         else
283             zebra.setZEvent("cam", "true");
284         ConnectionManager.sendZebra(zebra);
285     },
286     audioToggled: function(evt) {
287         var zebra = new Zebra("com.requestec.smg.apps.ZenDevice#setMic");
288         if (evt.mute)
289             zebra.setZEvent("mic", "false");
290         else
291             zebra.setZEvent("mic", "true");
292         ConnectionManager.sendZebra(zebra);
293     },
294     p2pEstablished: function() {
295 		if(zwrtc.isMCU()){
296 			//mcu call going on
297 			Platform.log("CallManager p2pEstablished:Sending SERVER_REDIRECT_STATUS:OK to mcu");
298 			var zebra = new Zebra("SERVER_REDIRECT_STATUS");
299 			zebra.setZEvent("status", "OK");
300 			zebra.setZEvent("command_id", this._srCommandID);
301 			ConnectionManager.sendZebraToMCU(zebra);
302 			Platform.log("_srCommandID:"+this._srCommandID);
303 			zwrtc.switchedToP2P();
304 			CallManager._dispatchEvent(CallManager.Event.RECONNECTED, {'type':'p2p'});
305 		}else
306 			CallManager._dispatchEvent(CallManager.Event.CONNECTED, {'type':'p2p'});
307 	Platform.log("CallManager p2pEstablished");
308 	this.sendPlaceCall(true);
309 	this.callEstablished();
310     },
311     p2pFailed: function() {
312         Platform.log("CallManager p2pFailed");
313         var video = true;
314         if (CallManager._type == "VOICE")
315             video = false;
316         this.connectToMCU(video);
317         this.sendPlaceCall(false);
318     },
319 	getZEvent:function(zebra,param){
320 		var val=null;
321 		try{
322 			val=zebra.getZEvent(param).value;
323 		}catch(err){}
324 		return val;
325 	},
326 	serverRedirect: function(zebra) {
327 		if (!CallManager.CALL_HANDLING || CallManager._flashEnabled) return;
328 		Platform.log("CallManager serverRedirect");
329 		if(zebra)
330 			Platform.log("CallManager serverRedirect:"+zebra.toXML());
331 		var video = true;
332 		if (zebra.getZEvent("mcu") && zebra.getZEvent("mcu").value == "true") {
333 			ConnectionManager._dispatchEvent('MCU_SR_RECVD', {
334 			'msg': 'Connecting to mcu'
335 		});
336 		CallManager._hangUpIfNoSR = false;
337 		if (ConnectionManager.inCall()) {
338 			zwrtc.hangup(true);
339 			CallManager._dispatchEvent(CallManager.Event.RECONNECTING, {'type':'mcu'});
340 		}else
341 			CallManager._dispatchEvent(CallManager.Event.CONNECTING, {'type':'mcu'});
342 			if (CallManager._type == "VOICE")
343 				video = false;
344 			this.connectToMCU(video);
345 		} else {
346 			CallManager._mcuCall = false;
347 			var type = this.getZEvent(zebra,"type");
348 			var connectmode = this.getZEvent(zebra,"connectmode");
349 			var destination = this.getZEvent(zebra,"destination");
350 			var isP2P = this.getZEvent(zebra,"isP2P");
351 			var zenonserver = this.getZEvent(zebra,"zenonserver");
352 			var callerP2PAddress = this.getZEvent(zebra,"callerP2PAddress");
353 			var srCommandID = this.getZEvent(zebra,"command_id");
354 
355 			if(srCommandID)
356 				CallManager._srCommandID=srCommandID;
357 			else
358 				CallManager._srCommandID=-1;
359 
360 			if(type==null)
361 				type=CallManager.VIDEO;
362 			type = type.replace("DIAL", "");
363 			if (type == "NONE" || type == "VOICE") {
364 				video = false;
365 			}
366 			CallManager._type = type;
367 			if(ConnectionManager.inCall()){
368 				//already in call and mcu want to establish p2p
369 				var p2pAddr = CallManager.getWrtcAddress(callerP2PAddress);
370 				if (p2pAddr != null) {
371 					zwrtc.placeP2PCall(p2pAddr, video);
372 				}
373 			}else if (connectmode == "2" || connectmode == "0") {
374 				var p2p = zwrtc.getP2PAddress();
375 				destination = destination.replace("VS7", "VS1");
376 				if (destination.indexOf("#") == -1 && destination.indexOf("%23") == -1) {
377 					destination = destination + "%23" + LineStatesModel.getNextAvailableLine();
378 				}
379 				Platform.log("Calling initiateCall:" + p2p);
380 				zwrtc.updateCallType(video);
381 				this.initCall(type, destination, "-1", true, 0, "Demo Call", null, p2p);
382 			} else if (connectmode == "1") {
383 				this.endCall();
384 			}
385 		}
386 	},
387                 /**
388                         @name CallManager#setZUI
389                         @function
390                         @description
391 								Initialize the CallManager for being able to place and receive calls using a ZUI object.
392 
393                         @param {string} zui The ZUI Object which renders the UI components
394                         @param {string} confirmAV prompt user for cam and mic (CallManager.CAM_MIC) or just mic (CallManager.MIC)
395                         @param {string} viewOnly call using viewOnly mode, i.e. no media access or transmission
396 
397                 **/
398 	setZUI: function(zui,confirmAV,viewOnly) {
399 		if(zui.getAttribute("forceFlash")=="true"){
400 			CallManager._flashEnabled=true;
401 		}
402 		if(zui.getAttribute("flashBgColor")){
403 			flashClient.setBGColor(zui.getAttribute("flashBgColor"));
404 		}
405 		flashClient.setTimerOnRV(true);
406 		flashClient.showToolBar();
407 		CallManager.zinit(zui.getLV(),zui.getRV(),zui.getAudio(),confirmAV,viewOnly,$("#sp_flash_container"),"sp_flash");
408 	},
409 	onStatusMsg: function(msg){
410 		flashClient.onStatusMsg(msg);
411 	},
412 	
413                 /**
414                         @name CallManager#zinit
415                         @function
416                         @description
417 								Initialize the CallManager for being able to place and receive calls 
418 
419                         @param {string} localVideo DOM element to display the local video
420                         @param {string} remoteVideoArray Array of DOM elements for displaying the remote video streams
421                         @param {string} remoteAudio element to play remote audio
422                         @param {string} confirmAV prompt user for cam and mic (CallManager.CAM_MIC) or just mic (CallManager.MIC)
423                         @param {string} viewOnly call using viewOnly mode, i.e. no media access or transmission
424 
425                 **/
426     zinit: function(localVideo,remoteVideoArray,remoteAudio,confirmAV,viewOnly,flashClientContainer,flashContainerName) {
427 	 CallManager.CALL_HANDLING = true;
428     	if(ConnectionManager.isLoggedIn())  {
429 		CallManager.zinitInner(localVideo,remoteVideoArray,remoteAudio,confirmAV,viewOnly,flashClientContainer,flashContainerName);
430 	}else{
431 		ConnectionManager.addListener("LOGIN_SUCCESS", this, function(){
432 			CallManager.zinitInner(localVideo,remoteVideoArray,remoteAudio,confirmAV,viewOnly,flashClientContainer,flashContainerName);
433 		});
434 	}
435     },
436     zinitInner: function(localVideo,remoteVideoArray,remoteAudio,confirmAV,viewOnly,flashClientContainer,flashContainerName) {
437 	if(!CallManager._flashEnabled){
438 		//check if webrtc supported by browser or not
439 		try{
440 			if(((typeof mozRTCPeerConnection!="undefined") && mozRTCPeerConnection) || ((typeof webkitRTCPeerConnection!="undefined") && webkitRTCPeerConnection)){
441 				//webrtc supported
442 			}else
443 				CallManager._flashEnabled=true;
444 		}catch(err){
445 			CallManager._flashEnabled=true;
446 		}
447 	}
448 	if(CallManager._flashEnabled){
449 		flashClient.init(flashClientContainer,flashClient,false);
450 	}else{
451 	      	if(viewOnly)
452         		zwrtc.viewOnly=true;
453 
454 		var uname=DataStore.getUserData("username", "");
455 		DataStore.getUserData("username", "");
456 		if(uname && uname.indexOf("SHADOW_")==-1)
457         	    uname="SHADOW_"+uname;
458 		var turn=DataStore.getUserData("stun_turn", "[{ url: 'stun:stun.l.google.com:19302'}]");
459 		eval("turn = "+turn);
460 		zwrtc.init(uname,null,null,localVideo,remoteVideoArray,remoteAudio,null,true,"both",confirmAV,turn,"");
461 	}
462     },
463                 /**
464                         @name CallManager#placeCall
465                         @function
466                         @description Place a call
467                         @param {string} type CallManager.VIDEO | CallManager.VOICE
468                         @param {string} destination Addrress to dial. Can be a user or room.
469                         @param {string} displayName String to display e.g. Meeting title
470                         @param {boolean} keepConnected Redial if connection dropped due to poor internet. Default false.
471 
472                 **/
473     placeCall: function(type, dest, displayName, keepConnected) {
474 		if(CallManager._flashEnabled){
475 			flashClient.placeCall(type, dest);
476 		}else{
477 			CallManager.initCall(type, dest, "-1", true, 0, displayName, null, zwrtc.getP2PAddress(), keepConnected);
478 		}
479     },
480 	initCall: function(type, dest, chat_session_id, showVS, itemId, displayName, alternative_username, p2pAddress, keepConnected) {
481 		// ensure safe placing of call when state waiting - allow up to 60 seconds to happen
482 		CallManager._initCallInner = function() {
483 			CallManager._type = type;
484 			CallManager._destination = dest;
485 			CallManager._mcuCall = false;
486 			// 1) monitor call is actually placed 
487 			// allow time to establish else initCall again
488 			CallManager._establishMonitorId = DateTimeUtil.getNow();
489 			var update_ = CallManager._establishMonitorId;
490 			setTimeout(function() {
491 				if (update_ == CallManager._establishMonitorId) {
492 					Platform.log("CallManager CallManager._establishMonitorId starting Call again");
493 					ConnectionManager._dispatchEvent("ZWRTC_PLACING_CALL_STEPS", {
494 					'msg': ' ESTABLISH MONITOR ALARM'
495 					});
496 					CallManager.sendEndCall();
497 					zwrtc.hangup();
498 					CallManager.initCall(type, dest, chat_session_id, showVS, itemId, displayName, alternative_username, p2pAddress, keepConnected);
499 				}
500 			}, CallManager._establishMonitorTimeout);
501 			if (dest && dest.indexOf("#") == -1 && dest.indexOf("%23") == -1) {
502 				dest = dest + "%23" + LineStatesModel.getNextAvailableLine();
503 			}
504 			Platform.initiateCall(type, dest, chat_session_id, showVS, itemId, displayName, alternative_username, p2pAddress);
505 			ConnectionManager._dispatchEvent('PLACECALL_ZEBRA_SENT', {
506 				'msg': 'inner'
507 			});
508 		};
509 		CallManager._initCallInnerSetTime = new Date().getTime();
510 		CallManager.checkCall();
511 		// 2) once established 
512 		CallManager._keepConnected = null;
513 		if (keepConnected) {
514 			CallManager._keepConnected = function() {
515 				Platform.log("CallManager CallManager._keepConnected starting Call again");
516 				ConnectionManager._dispatchEvent("ZWRTC_PLACING_CALL_STEPS", {
517 				'msg': ' KEEP CONNECTED MONITOR ALARM'
518 				});
519 				zwrtc.hangup();
520 				CallManager.initCall(type, dest, chat_session_id, showVS, itemId, displayName, alternative_username, p2pAddress, keepConnected);
521 			};
522 		}
523 	},
524 	checkCall: function() {
525 		Platform.log("checkCall:"+ConnectionManager.zsState);
526 		if (ConnectionManager.zsState == "waiting") {
527 			if (CallManager._initCallInner != null) {
528 				if ((new Date().getTime()) - CallManager._initCallInnerSetTime < CallManager._initCallInnerTimeout)
529 					CallManager._initCallInner();
530 				else
531 					Platform.log("CallManager checkCall timed out");
532 				CallManager._initCallInner = null;
533 			} else if (CallManager._keepConnected && CallManager._establishMonitorId == null) {
534 				// if waiting or reset && CallManager._keepConnected && its established 
535 				Platform.log("CallManager call keep connected");
536 				CallManager._keepConnected();
537 			}
538 		}
539 	},
540 	cancelCall: function() {
541 		Platform.log("CallManager CallManager.cancelCall");
542 		CallManager._establishMonitorId = null;
543 		CallManager._keepConnected = null;
544 		CallManager._establish=false;
545 	},
546 	isEstablished: function() {
547 		return CallManager._establish;
548 	},
549 	
550     callEstablished: function() {
551         Platform.log("CallManager CallManager._establishMonitorId callEstablished");
552         CallManager._establishMonitorId = null;
553 	CallManager._establish=true;
554     },
555     recordingCall: function() {
556 	this.callEstablished();
557     },
558     disconnectCall: function() {
559         if (!CallManager.CALL_HANDLING) return;
560         CallManager._mcuCall = false;
561         CallManager._callToken = null;
562         CallManager._hangUpIfNoSR = false;
563         CallManager._type = CallManager.VIDEO;
564         Platform.log("CallManager disconnectCall");
565         zwrtc.hangup();
566         CallManager.cancelCall();
567         CallManager._dispatchEvent(CallManager.Event.ENDED);
568         CallManager.shareScreenStop();
569     },
570     connectToMCU: function(videoCall) {
571         if (CallManager._mcuCall) {
572             Platform.log("CallManager connectToMCU, ignoring as mcu call already going on");
573             return;
574         }
575         CallManager._mcuCall = true;
576         var dest = "rtcshadow";
577         if (!videoCall)
578             dest = "rtcshadowaudio";
579         Platform.log("sip:" + dest + "@" + this.getServerIP() + ":" + DataStore.getUserData("mcu_sip_port", ""));
580         zwrtc.placeCall(videoCall, "sip:" + dest + "@" + this.getServerIP() + ":" + DataStore.getUserData("mcu_sip_port", ""), 1, this.getServerIP());
581     },
582     getEndPoint: function() {
583         return (window.zcallerHostname || DataStore.getUserData("endpoint", "") || ConnectionManager.CLS);
584     },
585     getServerIP: function() {
586         //var endpoint = (window.zcallerHostname || DataStore.getUserData("endpoint", "") || ConnectionManager.CLS);
587         var endpoint = CallManager.getEndPoint();
588         endpoint = endpoint.replace("http://", "");
589         endpoint = endpoint.replace("https://", "");
590         endpoint = endpoint.replace(":80", "");
591         return endpoint;
592     },
593     hangUpLine: function(lineNumber) {
594         var zebra = new Zebra("CALL_CONTROL");
595         zebra.setZEvent("action", "HANGUP");
596         zebra.setZEvent("line_number", lineNumber);
597         ConnectionManager.sendZebraToMCU(zebra);
598     },
599     onUnload: function(){
600 	if (!CallManager.CALL_HANDLING) return;
601 	Platform.log("CallManager onUnload");
602 	CallManager.clearCall();
603 	Platform.httpRequest(
604             "POST", CallManager.getEndPoint() + (ConnectionManager.ZSServlet || ""),
605             null,
606             "comm=unregister" +
607             "&username=" + (DataStore.getUserData("username", "")) +
608             "&service=" + (ConnectionManager.service || ""),
609             null
610         );
611     },
612     clearCall: function(){
613 	CallManager.cancelCall();
614         CallManager._dispatchEvent(CallManager.Event.ENDED);
615 	ConnectionManager._dispatchEvent('MCUDISCONNECT', {
616             'reason': '0'
617         });
618     },
619 	sendEndCall:function(){
620 		Platform.httpRequest(
621 			"POST", CallManager.getEndPoint() + (ConnectionManager.ZSServlet || ""),
622 			null,
623 			"comm=endcall" +
624 			"&username=" + (DataStore.getUserData("username", "")) +
625 			"&service=" + (ConnectionManager.service || ""),
626 			null
627 		);
628 	},
629                 /**
630                         @name CallManager#endCall
631                         @function
632                         @description End the current call
633 
634                 **/
635     endCall: function() {
636         if (!CallManager.CALL_HANDLING) return;
637         Platform.log("CallManager endCall");
638 	CallManager.clearCall();
639 	CallManager.sendEndCall();
640     },
641     incomingCall: function(zebra) {
642         if (!CallManager.CALL_HANDLING) return;
643         Platform.log("CallManager incomingCall");
644         var callToken = zebra.getZEvent("callToken").value; // b0530111-dfcb-e211-883d-0050569f2828
645         var caller = zebra.getZEvent("caller").value; // Gonzo Clone
646         var callerAudioCodecs = zebra.getZEvent("callerAudioCodecs").value; // SPEEX,ASAO
647         var callerMaxDownload = zebra.getZEvent("callerMaxDownload").value; // 400000
648         var callerP2PAddress = zebra.getZEvent("callerP2PAddress").value; // apt:1801751084_6632
649         var callerVBSession = zebra.getZEvent("callerVBSession").value; // VB7SNDUZ0FFB5LWJO7OTNYHTTECL7BZBFHOP9LW0ZSSPWNZ0WYUYIR2URNWMI3
650         var callerVideoCodecs = zebra.getZEvent("callerVideoCodecs").value; // SORENSON,H264
651         var callerVideoHeight = zebra.getZEvent("callerVideoHeight").value; // 288
652         var callerVideoWidth = zebra.getZEvent("callerVideoWidth").value; // 352
653         var chat_session_id = zebra.getZEvent("chat_session_id").value; // 
654         var contactaddress = zebra.getZEvent("contactaddress").value; // 
655         var contactid = zebra.getZEvent("contactid").value; // 100381084
656         var contactname = zebra.getZEvent("contactname").value; // 
657         var contacttype = zebra.getZEvent("contacttype").value; // 
658         var type = zebra.getZEvent("type").value; // VIDEO
659         var zenonserver = zebra.getZEvent("zenonserver").value; // 
660 	CallManager._dispatchEvent(CallManager.Event.INCOMING_CALL);
661         if (this.AUTO_ANSWER)
662             CallManager.acceptCall(callToken, caller, callerAudioCodecs, callerMaxDownload, callerP2PAddress, callerVBSession, callerVideoCodecs, callerVideoHeight, callerVideoWidth, chat_session_id, contactaddress, contactid, contactname, contacttype, type, zenonserver);
663         else {
664             // play audio
665             // showDialog
666             // if ok call accept and stop ringing
667             // if not ok or cancel stop ringing
668             if (ConnectionManager.Platform.isSayPageApp) {
669                 showMessage("Incoming Call", "Call from " + caller, true, null, "Answer", function() {
670                     CallManager.acceptCall(callToken, caller, callerAudioCodecs, callerMaxDownload, callerP2PAddress, callerVBSession, callerVideoCodecs, callerVideoHeight, callerVideoWidth, chat_session_id, contactaddress, contactid, contactname, contacttype, type, zenonserver)
671                 }, false, null, "Ignore");
672             } else {
673                 Z.jqm.showNJQMChoiceDialog("Accept call from " + caller, function() {
674                     CallManager.acceptCall(callToken, caller, callerAudioCodecs, callerMaxDownload, callerP2PAddress, callerVBSession, callerVideoCodecs, callerVideoHeight, callerVideoWidth, chat_session_id, contactaddress, contactid, contactname, contacttype, type, zenonserver)
675                 }, 60 * 1000);
676             }
677         }
678     },
679     getWrtcAddress: function(p2pAddress) {
680         if (p2pAddress) {
681             var addresses = p2pAddress.split(",");
682             for (var i = 0; i < addresses.length; i++) {
683                 var addr = addresses[i].split(":");
684                 if (addr[0] == "wrtc")
685                     return addr[1];
686             }
687         }
688         return null;
689     },
690     acceptCall: function(callToken, caller, callerAudioCodecs, callerMaxDownload, callerP2PAddress, callerVBSession, callerVideoCodecs, callerVideoHeight, callerVideoWidth, chat_session_id, contactaddress, contactid, contactname, contacttype, type, zenonserver) {
691         //send ACCEPT first before placing call
692         Platform.httpRequest(
693             "POST", CallManager.getEndPoint() + (ConnectionManager.ZSServlet || ""),
694             null,
695             "comm=zsmessage" +
696             "&command=ZENONWAKERESPONSE" +
697             "&value=ACCEPT%23" + LineStatesModel.getNextAvailableLine() +
698             "&username=" + (DataStore.getUserData("username", "")) +
699             "&service=" + (ConnectionManager.service || ""),
700             null
701         );
702         zwrtc.stopSound();
703         // placeCall with token and possible isP2P true/false depending on ding dong
704         if (!ConnectionManager.inCall()) {
705             var p2pAddr = CallManager.getWrtcAddress(callerP2PAddress);
706             CallManager._callToken = callToken;
707             CallManager._type = type;
708             var video = true;
709             if (type == "VOICE")
710                 video = false;
711             if (CallManager._flashEnabled) {
712                 ConnectionManager._dispatchEvent("FLASH_INIT_INCOMING_CALL", {
713                     'callerP2PAddress': callerP2PAddress,
714                     'type': type,
715                     'zenonserver': zenonserver,
716                     'callToken': callToken
717                 });
718             } else {
719                 if (p2pAddr != null) {
720                     CallManager._mcuCall = false;
721                     zwrtc.placeP2PCall(p2pAddr, video);
722                 } else {
723                     this.connectToMCU(video);
724                     this.sendPlaceCall(false);
725                 }
726             }
727         }
728     },
729     sendPlaceCall: function(isP2P) {
730         Platform.log("CallManager sendPlaceCall:" + CallManager._callToken + " p2p:" + isP2P);
731         if (CallManager._callToken != null) {
732             var zebra = new Zebra("org.zenon.server.zebra.ZebraHandler#placeCall");
733             zebra.setZEvent("callToken", CallManager._callToken);
734             zebra.setZEvent("avfrw", "false");
735             zebra.setZEvent("isP2P", isP2P);
736             var wid = 176;
737             var hei = 144;
738             try {
739                 wid = zwrtc.in_video_width;
740                 hei = zwrtc.in_video_height;
741             } catch (err) {}
742             zebra.setZEvent("width", wid);
743             zebra.setZEvent("height", hei);
744 	    zebra.setZEvent("client", "webrtc");
745             //ConnectionManager.sendZebraToZS(zebra);
746             ConnectionManager.sendZSZebraCommand("placeCall", zebra);
747             CallManager._callToken = null;
748         }
749     }
750 });
751