{"version":3,"sources":["node_modules/browser-pack/_prelude.js","js/libs/globals.js","wtcp-client-api.js","js/libs/wtcp-types/ErrorResponse.js","js/libs/wtcp-types/requests/AnchorInfo.js","js/libs/wtcp-types/requests/PrivateTextMessageRequest.js","js/libs/wtcp.client.js","js/libs/wtcp.locator.js","js/libs/wtcp.util.js","js/libs/wtcp.wtcpaudio.js","node_modules/guid/guid.js","node_modules/ua-parser-js/src/ua-parser.js"],"names":["r","e","n","t","o","i","f","c","require","u","a","Error","code","p","exports","call","length","module","String","prototype","endsWith","suffix","this","indexOf","Date","now","getTime","Object","assign","defineProperty","enumerable","configurable","writable","value","target","TypeError","to","arguments","nextSource","keysArray","keys","nextIndex","len","nextKey","desc","getOwnPropertyDescriptor","undefined","wtcpJs","ErrorResponse","constructor","errorCode","errorMessage","WtcpJs","AnchorInfo","type","before","after","guid","PrivateTextMessageRequest","obj","conversationId","label","participants","metaData","mimeType","data","destination","userName","displayName","callAlias","create","global","wtcpUtil","wtcp","util","audio","locService","uaParser","eventList","proxyInstanceCnt","proxyGlobals","transCounter","wtcpJsClientErrors","PTT_NOT_READY","err","WTCPJS_CLIENT_OFFSET","pushCallbacks","map","res","rej","set","resolve","reject","getCallback","key","cb","has","size","wtcpInfo","toString","k","get","delete","ua","window","navigator","userAgent","Client","clientOptions","clientWorker","locator","local","socketActive","serverUrlPattern","httpsPattern","settings","pttDownPending","pttUpPending","pttUpSuccess","pttUpFailure","pttOn","callbacks","socketConnectedCallbacks","Map","sendCredentialsCallbacks","getChannelPropsCallbacks","setChannelPropsCallbacks","getEndpointLookupCallbacks","getEndpointPropsCallbacks","setEndpointPropsCallbacks","setActiveChannelsCallbacks","setActivePhoneLinesCallbacks","pttDownCallbacks","muteChannelCallbacks","dtmfSendCallbacks","callPTTOnCallbacks","callPTTOffCallbacks","addressBookCallbacks","textMessageCallbacks","endpointFilteringCallbacks","endpointPropFilteringCallbacks","openSessionCallbacks","closeSessionCallbacks","channelActivityCallbacks","callMakeRequestCallbacks","callHangupRequestCallbacks","callAnswerRequestCallbacks","clearEndpointFilterCallbacks","privateMediaMessageCallbacks","eventDispatcher","events","on","event","callback","handlers","push","splice","trigger","forEach","handler","wtcpError","message","EventSubscriber","subscribe","workerError","workerMessage","cmd","tranid","clearCallStates","profileId","pingInterval","initialVolume","audioPlayerActive","loggingLevel","exportOutboundAudio","processorNodeBufferSize","outboundAudioFile","deviceId","applicationName","licenseUUID","setLoggingLevel","path","getScriptPath","audioHandler","WTCPAudio","messageHandlers","id","instanceId","wtcpWorker","terminate","postMessage","version","proxyServerID","getStatus","PlayerEnabled","newValue","console","info","LibraryVersion","teardownClient","sendMessage","transfer","sendCredentials","tranId","userId","password","profile","uuid","login","usr","pwd","Promise","pingIntervalOption","platformString","os","name","cpu","architecture","then","args","sendPttUp","sendMessagePromise","promiseTimeout","result","catch","awaitPttUp","awaitPromise","errr","sendCallPttUp","callId","getDefaultOptions","options","hasOwnProperty","important","setEndpointPropertiesResponse","signalingSyntaxError","openSessionResponse","openSessionError","closeSessionResponse","closeSessionUnsolResponse","sendCredentialsResponse","sendCredentialsError","setActiveChannelsResponse","hasErrors","channelResponses","failedChannelResponses","unsolProxyUpdate","getChannelPropertiesUnsol","getChannelPropertiesResponse","getChannelPropertiesError","setChannelPropertiesResponse","setChannelPropertiesError","channelActivityResponse","channelActivityError","channelActivityUnsolicited","endpointLookupResponse","endpointLookupError","getEndpointLookup","getEndpointPropertiesResponse","getEndpointPropertiesError","getEndpointPropertiesUnsolicited","setEndpointPropertiesError","pttResponse","sendAudio","pttError","pttOff","setActivePhoneLinesResponse","setActivePhoneLinesError","phoneLineStatusUnsol","callProgressUnsol","muteChannelResponse","muteChannelError","pingResponse","pongResponse","pingRequest","dtmfResponse","dtmfError","dtmfUnsol","callPttOnResponse","callPttOnError","callPttOnUnsol","callPttOffResponse","d","callPttOffError","callPttOffUnsol","addressBookGetResponse","textMessageResponse","textMsgConfirmedDate","textMessageError","textMessageUnsol","privateMediaMessageResponse","privateMediaMessageError","privateMediaMessageUnsol","callMakeResponse","callHangupResponse","callAnswerResponse","callHangupUnsol","callOfferUnsol","setEndpointPropertiesFilterResponse","setEndpointPropertiesFilterError","setEndpointFilterResponse","setEndpointFilterError","clearEndpointFilterResponse","clearEndpointFilterError","playAudio","audioArrayBuffer","audioLength","connectionInfoUpdated","wsConnected","wsClosed","closeEvent","wsError","onConnectionClosed","onSessionClosed","onProxyUpdated","onChannelPropertiesReceived","onChannelActivity","onEndpointPropertiesReceived","onPhoneLineStatusChanged","onCallProgressReceived","onCallHangupReceived","onCallOfferReceived","onPTTOff","onDTMFReceived","onCallPTTOnReceived","onCallPTTOffReceived","onTextMessageReceived","onPrivateMediaMessageReceived","onPingResponse","onConnectionInfoUpdated","connect","serverUrl","username","onerror","onmessage","Worker","wtcpjsPath","Locator","match","webSocketServer","getProxy","_address","wsPort","address","setProfile","closeSession","setActiveChannels","channelIds","getChannelProperties","channelId","setChannelProperties","props","getChannelActivity","endpointLookup","includeFlags","excludeFlags","pageSize","pageNumber","nameBeginsWith","EndpointFlags","getEndpointProperties","endpointId","propList","msgBody","setEndpointProperties","PTTDown","PTTUp","endAudio","wtcInfo","wtcpDebug","callPTTOn","callPTTOff","setActivePhoneLines","phoneLines","fail","line","makeCall","source","answerCall","hangupCall","muteAllChannels","unmuteAllChannels","muteChannels","channels","dtmfSendRequest","dtmf","getAddressBook","pageNum","filter","sendTextMessage","sendP2PMessage","privateTextMessageRequest","setEndpointFilter","filterId","endpointFilter","propFilter","threshold","anchor","propertyFilter","notificationThreshold","anchorInfo","setEndpointChannelFilter","setEndpointSPCFilter","setEndpointAddressBookFilter","clearEndpointFilter","isNaN","setEndpointPropertiesFilter","setEndpointPropertiesPrivateCallFilter","setEndpointPropertiesTextMessageFilter","setEndpointPropertiesChannelActivityFilter","setEndpointPropertiesPrivateMessageFilter","visualizeAudio","canvas","visualize","setVolume","volume","destroy","SendMessage","self","locatorModule","getNonce","Math","floor","random","JXON","getJXONTree","oXMLParent","hasAttributes","vResult","nLength","sCollectedTxt","oAttrib","attributes","item","toLowerCase","parseText","trim","hasChildNodes","oNode","sProp","vContent","nItem","childNodes","nodeType","nodeValue","prefix","nodeName","Array","keyValue","sValue","test","isFinite","parseFloat","parse","proxyIndex","port","softwareVersionCheckUrl","controlVersion","httpStatusCode","proxyurl","_proxyurl","tryToGetProxy","error","targetUrl","locatorUrl","_this","oReq","XMLHttpRequest","onload","currentTarget","status","response","responseXML","serverresponse","proxy","statusText","open","send","ex","doc","decoder","loggingLevels","none","warn","debug","document","scriptPath","scriptEls","getElementsByTagName","scriptSrc","src","substr","lastIndexOf","buffer","littleEndian","ArrayBuffer","DataView","setInt16","Int16Array","WtcpUtil","logLevel","formatLogMsg","fn","msg","Number","isInteger","wtcpWarn","debugWindow","messageClass","date","time","getHours","getMinutes","getSeconds","getMilliseconds","loadScript","filename","scriptElem","createElement","setAttribute","appendChild","byteWriter","view","val","offset","shift","x","stringReader","position","TextDecoder","str","Uint8Array","strView","decode","exc","byteReader","addBitrange","valToAdd","bitLength","lshBytes","pow","mergeArrayBuffers","bufferInfo1","bufferInfo2","ta","Int8Array","tb","bitReader","bitPos","numBytes","parseWtcpHeader","int8View","h","sequence","payloadLength","ms","promise","timerId","timedPromise","setTimeout","race","clearTimeout","log","Moderator","Speaking","Typing","AudioTxMute","TextMute","Unavailable","Visible","AudioRxMute","TxSilence","RxSilence","EmergencyTx","Self","P2P","Gone","client","context","gainNode","visCanvas","analyser","micStream","microphone","scriptNode","biquadFilter","channelData","sampleRate","audioEndTime","times","endAudioSuccess","endAudioFailure","audioSamplesStarted","audioSamplesEnded","initStatus","micEnabled","sendingAudio","audioPlaying","playerActive","isVisualizing","audioQueueTimeout","audioQueue","audioQueueBufferLength","audioBufferSourceNodeEnded","setGain","pct","gain","draw","bufferLength","frequencyBinCount","sliceWidth","width","y","drawCtx","getContext","clearRect","height","lineWidth","strokeStyle","beginPath","getByteTimeDomainData","moveTo","lineTo","stroke","startAudio","currentTime","start","duration","requestAnimationFrame","isEnabled","createBufferSource","onended","b","createBuffer","copyToChannel","Float32Array","createMediaStreamSource","halting","createScriptProcessor","createBiquadFilter","frequency","Q","onaudioprocess","inputBuffer","copyFromChannel","flush","disconnect","AudioContext","webkitAudioContext","OfflineAudioContext","webkitOfflineAudioContext","createGain","createAnalyser","minDecibels","maxDecibels","smoothingTimeConstant","fftSize","mediaDevices","getUserMedia","stream","webkitGetUserMedia","mozGetUserMedia","msGetUserMedia","init","validator","RegExp","gen","count","out","substring","Guid","EMPTY","isGuid","equals","other","isEmpty","toJSON","join","raw","FUNC_TYPE","UNDEF_TYPE","OBJ_TYPE","STR_TYPE","MODEL","NAME","TYPE","VENDOR","VERSION","ARCHITECTURE","CONSOLE","MOBILE","TABLET","SMARTTV","WEARABLE","EMBEDDED","extend","regexes","extensions","mergedRegexes","concat","str1","str2","lowerize","major","replace","split","mapper","rgx","arrays","j","q","matches","regex","exec","maps","browser","oldSafari","oldEdge","windows","ME","XP","Vista","RT","device","engine","UAParser","getResult","_ua","_rgxmap","getBrowser","_browser","getCPU","_cpu","getDevice","_device","vendor","model","getEngine","_engine","getOS","_os","getUA","setUA","BROWSER","MAJOR","CPU","DEVICE","ENGINE","OS","define","amd","$","jQuery","Zepto","parser","uastring","prop"],"mappings":"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","file":"wtcp-client-api.min.js","sourcesContent":["(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i\r\n/// \r\n/// \r\n\r\nconst wtcpUtil = require('./wtcp.util.js');\r\n\r\nglobal.WtcpJs = global.WtcpJs || {};\r\n\r\n(function (wtcp) {\r\n \"use strict\";\r\n\r\n var util = require('./wtcp.util.js');\r\n var resp = require('./wtcp-types/ErrorResponse.js');\r\n var ai = require('./wtcp-types/requests/AnchorInfo.js');\r\n var pmReq = require('./wtcp-types/requests/PrivateTextMessageRequest.js');\r\n var audio = require('./wtcp.wtcpaudio.js');\r\n var locService = require('./wtcp.locator.js');\r\n var uaParser = require('ua-parser-js');\r\n\r\n const WTCPJS_CLIENT_OFFSET = 0x1B58;\r\n\r\n var eventList = {\r\n PROXY_UPDATED: \"pu1\",\r\n CHANNEL_PROPS_RECEIVED: \"cp1\",\r\n CHANNEL_ACTIVITY: \"ca1\",\r\n ENDPOINT_PROPS_RECEIVED: \"ep1\",\r\n PTT_OFF: \"po1\",\r\n DTMF_RECEIEVED: \"dr1\",\r\n CALL_PTT_ON_RECEIVED: \"cpor1\",\r\n CALL_PTT_OFF_RECEIVED: \"cpor2\",\r\n TXT_MSG_RECEIVED: \"tm1\",\r\n OPEN_SESSION_RECEIVED: \"sr1\",\r\n SESSION_CLOSED_RECEIVED: \"scr1\",\r\n PING_PONG_RESPONSE: \"ppr\",\r\n SOCKET_CLOSED: \"sc1\",\r\n SIGNAL_RECEIVED: \"sr2\",\r\n PHONE_LINE_STATUS_CHANGED: \"plsc\",\r\n CALL_PROGRESS_RECEIVED: \"cpr\",\r\n CALL_HANGUP_RECEIVED: \"chr\",\r\n CALL_OFFER_RECEIVED: \"cor\",\r\n CONNECTION_INFO_UPDATED: \"lu\",\r\n PRIV_MEDIA_MSG_RECEIVED: \"pmmr\"\r\n };\r\n\r\n var proxyInstanceCnt = 0;\r\n var proxyGlobals = {};\r\n var transCounter = 0; // transaction counter 1..36767\r\n\r\n var wtcpJsClientErrors = {\r\n \"PTT_NOT_READY\": (() => {\r\n let err = new WtcpJs.ErrorResponse();\r\n err.errorCode = WTCPJS_CLIENT_OFFSET | 1;\r\n err.errorMessage = \"You cannot PTT again until the WtpcjJs client handles the PTTUp response\";\r\n\r\n return err;\r\n })()\r\n };\r\n\r\n var registerInstance = function registerInstance() {\r\n var id = \"proxy_instance_\" + proxyInstanceCnt++;\r\n proxyGlobals[id] = {};\r\n\r\n return id;\r\n };\r\n\r\n var pushCallbacks = function pushCallbacks(map, res, rej) {\r\n // use transaction counter as a key for the map \r\n // use one counter for all maps (don't need to have individual counter for every map) \r\n // some leftover key will be gone after one cycle loop due to a missing response\r\n transCounter = (transCounter + 1) % 36768; \r\n // valid transaction range is [1..36767] \r\n if(transCounter == 0) transCounter = 1; \r\n map.set(transCounter,{ resolve: res, reject: rej })\r\n return transCounter; \r\n };\r\n\r\n var getCallback = function getCallback(map, key) {\r\n var cb;\r\n if (!map.has(key)) {\r\n if (map.size > 0) { // pick the last one -- this is a bad code smell (bug 46475) it appears that unit test will make this bad situation.\r\n wtcpUtil.wtcpInfo(`ALERT: number of keys : ${map.size} map = ${map.toString()}`);\r\n for(let k of map.keys())\r\n key = k;\r\n wtcpUtil.wtcpInfo(\"ALERT: Fetch the last key instead for given key:\", key)\r\n }\r\n }\r\n // if key is still missing, return undefined \r\n cb = map.get(key);\r\n map.delete(key)\r\n return cb; \r\n };\r\n\r\n var ua = null;\r\n if(window && window.navigator) {\r\n ua = uaParser(navigator.userAgent);\r\n }\r\n\r\n wtcp.Client = function (clientOptions, clientWorker) {\r\n\r\n if (!(this instanceof wtcp.Client)) return new wtcp.Client(clientOptions);\r\n\r\n /* --- Private variables --- */\r\n\r\n var local = {};\r\n var defaults = {\r\n profileId: \"\",\r\n pingInterval: 30,\r\n initialVolume: 100,\r\n audioPlayerActive: true,\r\n loggingLevel: 0,\r\n exportOutboundAudio: false,\r\n processorNodeBufferSize: 8192,\r\n outboundAudioFile: 'audio.wav',\r\n deviceId: \"HTML5 capable browser\",\r\n applicationName: 'MOT-WTCPJS-1.1',\r\n licenseUUID: \"{436C743D-896D-456e-A61B-6F564F3D2C78}\" // default to WAVE_LICENSE_WTC_SDK\r\n };\r\n\r\n var socketActive = false;\r\n var locator;\r\n var serverUrlPattern = /^ws{1,2}:\\/\\//;\r\n var httpsPattern = /^https:\\/\\//;\r\n var settings = {};\r\n var pttDownPending = false;\r\n var pttUpPending = false;\r\n var pttUpSuccess = null;\r\n var pttUpFailure = null;\r\n var pttOn = false;\r\n var requestTimeoutId;\r\n\r\n var callbacks = {\r\n socketConnectedCallbacks: new Map(),\r\n sendCredentialsCallbacks: new Map(),\r\n getChannelPropsCallbacks: new Map(),\r\n setChannelPropsCallbacks: new Map(),\r\n getEndpointLookupCallbacks: new Map(),\r\n getEndpointPropsCallbacks: new Map(),\r\n setEndpointPropsCallbacks: new Map(),\r\n setActiveChannelsCallbacks: new Map(),\r\n setActivePhoneLinesCallbacks: new Map(),\r\n pttDownCallbacks: new Map(),\r\n muteChannelCallbacks: new Map(),\r\n dtmfSendCallbacks: new Map(),\r\n callPTTOnCallbacks: new Map(),\r\n callPTTOffCallbacks: new Map(),\r\n addressBookCallbacks: new Map(),\r\n textMessageCallbacks: new Map(),\r\n endpointFilteringCallbacks: new Map(),\r\n endpointPropFilteringCallbacks: new Map(),\r\n openSessionCallbacks: new Map(),\r\n closeSessionCallbacks: new Map(),\r\n channelActivityCallbacks: new Map(),\r\n callMakeRequestCallbacks: new Map(),\r\n callHangupRequestCallbacks: new Map(),\r\n callAnswerRequestCallbacks: new Map(),\r\n clearEndpointFilterCallbacks: new Map(),\r\n privateMediaMessageCallbacks: new Map()\r\n };\r\n\r\n var eventDispatcher = {\r\n events: {},\r\n on: function on(event, callback) {\r\n var handlers = this.events[event] || [];\r\n handlers.push(callback);\r\n this.events[event] = handlers;\r\n\r\n return function() {\r\n for (var i = 0; i < handlers.length; i++) {\r\n if (callback === handlers[i]) {\r\n handlers.splice(i, 1);\r\n break;\r\n }\r\n }\r\n };\r\n },\r\n trigger: function trigger(event, data) {\r\n var handlers = this.events[event];\r\n\r\n if (!handlers || handlers.length < 1) return;\r\n\r\n [].forEach.call(handlers, function (handler) {\r\n try {\r\n handler(data);\r\n } catch (e) {\r\n util.wtcpError(\"An error occurred in the callback subscribed to \" + event + \": \" + e.message);\r\n }\r\n });\r\n }\r\n };\r\n\r\n var EventSubscriber = function(event) {\r\n return {\r\n subscribe: function (callback) {\r\n return eventDispatcher.on(event, callback);\r\n }\r\n }\r\n }\r\n\r\n var workerError = function workerError(e) {\r\n util.wtcpError(\" in Worker: \" + e.message);\r\n };\r\n\r\n var workerMessage = function workerMessage(e) {\r\n try {\r\n if (local[e.data.cmd].length < 2) local[e.data.cmd](e.data.value); else local[e.data.cmd](e.data.value, e.data.tranid);\r\n } catch (e) {\r\n if (typeof e.data !== \"undefined\") util.wtcpError(\"Unknown function called from worker: \", e.data.cmd); else {\r\n util.wtcpError(\"Worker exception thrown\", e);\r\n }\r\n }\r\n };\r\n\r\n var clearCallStates = function() {\r\n // Clear PTT pending flags since the call is no longer active\r\n pttUpPending = false;\r\n pttDownPending = false;\r\n pttOn = false;\r\n }\r\n\r\n Object.assign(settings, defaults, clientOptions);\r\n util.setLoggingLevel(settings.loggingLevel);\r\n\r\n var path = util.getScriptPath();\r\n\r\n // In future release there will be some criteria provided by locator to determine which audio handler to use\r\n // The correct one will be dynamically loaded at run time. For now defaulting to WTCPAudio\r\n var audioHandler = new audio.WTCPAudio(this, settings);\r\n\r\n Object.assign(local, audioHandler.messageHandlers);\r\n\r\n var cb;\r\n var instanceId = registerInstance();\r\n var wtcpWorker = {\r\n terminate: function terminate() { },\r\n postMessage: function postMessage() {\r\n throw \"worker not initialized, you must first connect to a WAVE Proxy\";\r\n }\r\n };\r\n\r\n /* --- Public properties --- */\r\n Object.defineProperty(this, \"LibraryVersion\", { get: function () {\r\n // this gets replaced by gulp at build-time\r\n return \"1.0.0-2090.5bbd4d1\";\r\n }});\r\n Object.defineProperty(this, \"WTCPVersion\", { get: function () { return locator.version; } });\r\n Object.defineProperty(this, \"ServerId\", { get: function () { return locator.proxyServerID; } });\r\n Object.defineProperty(this, \"IsClientActive\", { get: function () { return socketActive; } });\r\n Object.defineProperty(this, \"WTCPAudioStatus\", { get: function () { return audioHandler.getStatus(); } });\r\n Object.defineProperty(this, \"AudioPlayerActive\", {\r\n get: function () { return audioHandler.PlayerEnabled; },\r\n set: function (newValue) {\r\n settings.audioPlayerActive = newValue;\r\n audioHandler.PlayerEnabled = newValue;\r\n }\r\n });\r\n\r\n console.info('WctpJS v' + this.LibraryVersion);\r\n console.info('logging level: ' + settings.loggingLevel);\r\n // Private Function definitions\r\n\r\n var teardownClient = function teardownClient() {\r\n locator = null;\r\n wtcpWorker.terminate(); // Consider having worker close itself to give it a chance to shutdown gracefully\r\n delete proxyGlobals[instanceId];\r\n\r\n util.wtcpInfo(\"WtcpJs Client worker teardown complete\");\r\n };\r\n\r\n var sendMessage = function sendMessage(cmd, tranid, value, transfer) {\r\n if (!socketActive && !(cmd === \"init\" || cmd === \"connect\")) throw \"Can't call \" + cmd + \", Socket is not active! You must call connect() before using the Client object\";\r\n value = value || {};\r\n tranid = tranid || 1;\r\n\r\n if (!transfer) transfer = [];\r\n\r\n wtcpWorker.postMessage({\r\n \"tranid\": tranid,\r\n \"cmd\": cmd,\r\n \"value\": value\r\n }, transfer);\r\n };\r\n\r\n var init = function init() { };\r\n\r\n var initWorker = function initWorker() {\r\n\r\n sendMessage(\"init\", 1, {\r\n wtcpjsPath: path + \"wtcpjs.js\",\r\n settings: settings\r\n });\r\n };\r\n\r\n var openSession = function openSession() {\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"openSession\", pushCallbacks(callbacks.openSessionCallbacks, resolve, reject), {\r\n pingIntervalOption: settings.pingInterval,\r\n deviceId: settings.deviceId,\r\n platformString: ua ? `${settings.applicationName}-${ua.os.name}-${ua.os.version}-${ua.cpu.architecture}` : `${settings.applicationName}-?-?-?`\r\n });\r\n });\r\n };\r\n\r\n var sendCredentials = function sendCredentials(tranId, userId, password, profile) {\r\n //WTCP Protocol Specification says to MD5 the password, but that doesn't seem to work on proxy...\r\n //var md5hash = CryptoJS.MD5(password);\r\n\r\n if (!profile) profile = \"\";\r\n\r\n sendMessage(\"sendCredentials\", tranId, {\r\n userId: userId,\r\n password: password,\r\n profile: profile,\r\n uuid: settings.licenseUUID\r\n });\r\n };\r\n\r\n var login = function login(usr, pwd, profileId) {\r\n util.wtcpInfo(\"Connect Success\");\r\n\r\n return openSession().then(function (args) {\r\n return new Promise(function (resolve, reject) {\r\n let tranId = pushCallbacks(callbacks.sendCredentialsCallbacks, resolve, reject);\r\n\r\n if (profileId) sendCredentials(tranId, usr, pwd, profileId); else sendCredentials(tranId, usr, pwd, \"\");\r\n }, function (args) {\r\n //options.error.call(this, args);\r\n });\r\n });\r\n };\r\n\r\n /* --- Worker.onmessage functions --- */\r\n\r\n local.setEndpointPropertiesResponse = function (data, t) {\r\n\r\n cb = getCallback(callbacks.setEndpointPropsCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"setEndpointPropertiesResponse\", data);\r\n };\r\n\r\n local.signalingSyntaxError = function (data) {\r\n eventDispatcher.trigger(eventList.SIGNAL_RECEIVED, data);\r\n util.wtcpInfo(\"Signaling op-code 1: Syntax Error received\", data);\r\n };\r\n\r\n local.openSessionResponse = function (data, t) {\r\n\r\n cb = getCallback(callbacks.openSessionCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"OpenSessionResponse\", data);\r\n };\r\n\r\n local.openSessionError = function (data, t) {\r\n socketActive = false;\r\n cb = getCallback(callbacks.openSessionCallbacks, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n util.wtcpInfo(\"openSessionError\", data);\r\n };\r\n\r\n local.closeSessionResponse = function (data, t) {\r\n teardownClient();\r\n cb = getCallback(callbacks.closeSessionCallbacks, t);\r\n if (cb) cb.resolve(); \r\n\r\n util.wtcpInfo(\"Proxy session closed\");\r\n };\r\n\r\n local.closeSessionUnsolResponse = function (data) {\r\n eventDispatcher.trigger(eventList.SESSION_CLOSED_RECEIVED, data);\r\n util.wtcpError(\"closeSessionError\", data);\r\n };\r\n\r\n local.sendCredentialsResponse = function (data, t) {\r\n cb = getCallback(callbacks.sendCredentialsCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n // Need to add cb here\r\n util.wtcpInfo(\"sendCredentialsResponse\", data);\r\n };\r\n\r\n local.sendCredentialsError = function (data, t) {\r\n cb = getCallback(callbacks.sendCredentialsCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"sendCredentialsResponse\", data);\r\n // Need to add callbacks here\r\n };\r\n\r\n local.setActiveChannelsResponse = function (data, t) {\r\n cb = getCallback(callbacks.setActiveChannelsCallbacks, t);\r\n if (cb) {\r\n if (data.hasErrors && data.channelResponses.length === 0) cb.reject(data.failedChannelResponses);\r\n else cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"setChannelsResponse\", data);\r\n };\r\n\r\n local.unsolProxyUpdate = function (data) {\r\n eventDispatcher.trigger(eventList.PROXY_UPDATED, data);\r\n util.wtcpInfo(\"unsolicitedProxyUpdate\", data);\r\n };\r\n\r\n local.getChannelPropertiesUnsol = function (data) {\r\n eventDispatcher.trigger(eventList.CHANNEL_PROPS_RECEIVED, data);\r\n util.wtcpInfo(\"getChannelPropertiesUnsol\", data);\r\n };\r\n\r\n local.getChannelPropertiesResponse = function (data, t) {\r\n cb = getCallback(callbacks.getChannelPropsCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"getChannelPropertiesResponse\", data);\r\n };\r\n\r\n local.getChannelPropertiesError = function (data, t) {\r\n cb = getCallback(callbacks.getChannelPropsCallbacks, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n util.wtcpError(\"getChannelPropertiesError\", data);\r\n };\r\n\r\n local.setChannelPropertiesResponse = function (data, t) {\r\n cb = getCallback(callbacks.setChannelPropsCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"setChannelPropertiesResponse\", data);\r\n };\r\n\r\n local.setChannelPropertiesError = function (data, t) {\r\n cb = getCallback(callbacks.setChannelPropsCallbacks, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n util.wtcpError(\"setChannelPropertiesError\", data);\r\n };\r\n\r\n local.channelActivityResponse = function (data, t) {\r\n cb = getCallback(callbacks.channelActivityCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"channelActivityResponse\", data);\r\n };\r\n\r\n local.channelActivityError = function (err, t) {\r\n cb = getCallback(callbacks.channelActivityCallbacks, t);\r\n if (cb) {\r\n cb.reject(err);\r\n }\r\n util.wtcpError(\"channelActivityError\", err);\r\n };\r\n\r\n local.channelActivityUnsolicited = function (data) {\r\n eventDispatcher.trigger(eventList.CHANNEL_ACTIVITY, data);\r\n util.wtcpInfo(\"channelActivityUnsolicited\", data);\r\n };\r\n\r\n local.endpointLookupResponse = function (data, t) {\r\n cb = getCallback(callbacks.getEndpointLookupCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"endpointLookUpResponse\", data);\r\n };\r\n\r\n local.endpointLookupError = function (data, t) {\r\n cb = getCallback(callbacks.getEndpointLookup, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n };\r\n\r\n local.getEndpointPropertiesResponse = function (data, t) {\r\n cb = getCallback(callbacks.getEndpointPropsCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n };\r\n\r\n local.getEndpointPropertiesError = function (data, t) {\r\n cb = getCallback(callbacks.getEndpointPropsCallbacks, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n };\r\n\r\n local.getEndpointPropertiesUnsolicited = function (data) {\r\n // Not sure if this opCode is ever sent from Proxy. Test it... if not, combine this with _RESP directly above\r\n eventDispatcher.trigger(eventList.ENDPOINT_PROPS_RECEIVED, data);\r\n util.wtcpInfo(\"getEndpointPropertiesUnsolicited\", data);\r\n };\r\n\r\n local.setEndpointPropertiesError = function (data, t) {\r\n cb = getCallback(callbacks.setEndpointPropsCallbacks, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n util.wtcpError(\"setEndpointPropertiesError\", data);\r\n };\r\n\r\n local.pttResponse = function (data, t) {\r\n pttDownPending = false;\r\n cb = getCallback(callbacks.pttDownCallbacks, t);\r\n if (cb) {\r\n if (!pttUpPending) {\r\n cb.resolve(data);\r\n if (audioHandler && data.channelResponses.length > 0 && data.channelResponses[0].errorCode === 0) {\r\n audioHandler.sendAudio();\r\n\r\n util.wtcpInfo(\"PTT On\", data);\r\n } else {\r\n pttOn = false;\r\n util.wtcpInfo(\"PTT Off\", data);\r\n }\r\n } else {\r\n // PTTUp was called before the PTTDown response came back\r\n pttUpPending = false;\r\n util.wtcpInfo(\"Cancelling PTTDown because PTTUp request came before PTTDown response was received from proxy\");\r\n cb.reject(wtcpJsClientErrors[\"PTT_NOT_READY\"]);\r\n sendPttUp()\r\n .then((data) => {\r\n // TBD: This is not working correctly. PTT while another channel is clocking waiting for response\r\n // leads to bad state on the channel you are trying to PTT on\r\n pttUpSuccess(data);\r\n })\r\n .catch((err) => {\r\n pttUpFailure(err);\r\n });\r\n }\r\n }\r\n };\r\n\r\n local.pttError = function (err, t) {\r\n cb = getCallback(callbacks.pttDownCallbacks, t);\r\n if (cb) {\r\n cb.reject(err);\r\n }\r\n\r\n pttOn = false;\r\n pttUpPending = false;\r\n\r\n util.wtcpError(\"PTT Down Error\", err);\r\n };\r\n\r\n local.pttOff = function (data, t) { // Unsolicited PTT Off message\r\n pttOn = false;\r\n eventDispatcher.trigger(eventList.PTT_OFF, data);\r\n util.wtcpInfo(\"PTT Off\", data);\r\n };\r\n\r\n local.setActivePhoneLinesResponse = function (data, t) {\r\n cb = getCallback(callbacks.setActivePhoneLinesCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"setActivePhoneLinesResponse\", data);\r\n };\r\n\r\n local.setActivePhoneLinesError = function (data, t) {\r\n cb = getCallback(callbacks.setActivePhoneLinesCallbacks, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n util.wtcpError(\"ActivePhoneLineError\", data);\r\n };\r\n\r\n local.phoneLineStatusUnsol = function (data, t) {\r\n util.wtcpInfo(\"phoneLineStatusUnsol\", data);\r\n eventDispatcher.trigger(eventList.PHONE_LINE_STATUS_CHANGED, data);\r\n };\r\n\r\n local.callProgressUnsol = function(data, t) {\r\n util.wtcpInfo(\"callProgressUnsol\", data);\r\n eventDispatcher.trigger(eventList.CALL_PROGRESS_RECEIVED, data);\r\n };\r\n\r\n local.muteChannelResponse = function (data, t) {\r\n cb = getCallback(callbacks.muteChannelCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n util.wtcpInfo(\"Mute Channel Response\", data);\r\n };\r\n\r\n local.muteChannelError = function (data, t) {\r\n cb = getCallback(callbacks.muteChannelCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Mute Channel Error\", data);\r\n };\r\n\r\n local.pingResponse = function (data, t) {\r\n util.wtcpInfo(\"Proxy Pong\", data);\r\n };\r\n\r\n local.pongResponse = function (data) {\r\n eventDispatcher.trigger(eventList.PING_PONG_RESPONSE, data);\r\n util.wtcpInfo(\"Proxy Pong response to client Ping\", data);\r\n };\r\n\r\n local.pingRequest = function (data, t) {\r\n util.wtcpInfo(\"Proxy Ping\", data);\r\n };\r\n\r\n local.dtmfResponse = function (t) {\r\n cb = getCallback(callbacks.dtmfSendCallbacks, t);\r\n if (cb) cb.resolve();\r\n\r\n util.wtcpInfo(\"DTMF Send Response\");\r\n };\r\n\r\n local.dtmfError = function (data, t) {\r\n cb = getCallback(callbacks.dtmfSendCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"DTMF Send Error\", data);\r\n };\r\n\r\n local.dtmfUnsol = function (data) {\r\n eventDispatcher.trigger(eventList.DTMF_RECEIEVED, data);\r\n\r\n util.wtcpInfo(\"DTMF Received\", data);\r\n };\r\n\r\n local.callPttOnResponse = function (data, t) {\r\n\r\n pttDownPending = false;\r\n cb = getCallback(callbacks.pttDownCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n if (!pttUpPending) {\r\n audioHandler.sendAudio();\r\n\r\n util.wtcpInfo(\"Private Call PTT On\", data);\r\n } \r\n }\r\n\r\n cb = getCallback(callbacks.callPTTOnCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n if (audioHandler && data.errorCode === 0) audioHandler.sendAudio(); else pttOn = false;\r\n\r\n util.wtcpInfo(\"Call PTT On Response\", data);\r\n };\r\n\r\n local.callPttOnError = function (data, t) {\r\n cb = getCallback(callbacks.callPTTOnCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n pttOn = false;\r\n\r\n util.wtcpError(\"Call PTT On Error\", data);\r\n };\r\n\r\n local.callPttOnUnsol = function (data) {\r\n eventDispatcher.trigger(eventList.CALL_PTT_ON_RECEIVED, data);\r\n util.wtcpInfo(\"Call PTT On Received\", data);\r\n };\r\n\r\n local.callPttOffResponse = function (data, t) {\r\n cb = getCallback(callbacks.callPTTOffCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n pttOn = false;\r\n\r\n if (pttUpPending) {\r\n pttUpPending = false;\r\n util.wtcpInfo(\"Cancelling callPTTOn because callPTTOff request came before callPTTOn response was received from proxy\");\r\n sendCallPttUp(d.callId)\r\n .then((data) => {\r\n pttUpSuccess(data);\r\n })\r\n .catch((err) => {\r\n pttUpFailure(err);\r\n });\r\n }\r\n\r\n util.wtcpInfo(\"Call PTT Off Response\", data);\r\n };\r\n\r\n local.callPttOffError = function (data, t) {\r\n cb = getCallback(callbacks.callPTTOffCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Call PTT Off Error\", data);\r\n };\r\n\r\n local.callPttOffUnsol = function (data) {\r\n eventDispatcher.trigger(eventList.CALL_PTT_OFF_RECEIVED, data);\r\n util.wtcpInfo(\"Call PTT Off Received\", data);\r\n };\r\n\r\n local.addressBookGetResponse = function (data, t) {\r\n cb = getCallback(callbacks.addressBookCallbacks, t);\r\n if (cb) {\r\n if (data.errorCode > 0) cb.reject(data); else cb.resolve(data);\r\n }\r\n\r\n util.wtcpInfo(\"Address Book Info Response\", data);\r\n };\r\n\r\n local.textMessageResponse = function (data, t) {\r\n cb = getCallback(callbacks.textMessageCallbacks, t);\r\n if (cb) {\r\n data.textMsgConfirmedDate = new Date(Date.now());\r\n cb.resolve(data);\r\n }\r\n\r\n util.wtcpInfo(\"Text Message Sent\", data);\r\n };\r\n\r\n local.textMessageError = function (data, t) {\r\n cb = getCallback(callbacks.textMessageCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Error sending Text Message\", data);\r\n };\r\n\r\n local.textMessageUnsol = function (data) {\r\n eventDispatcher.trigger(eventList.TXT_MSG_RECEIVED, data);\r\n util.wtcpInfo(\"Text Message Received\", data);\r\n };\r\n\r\n local.privateMediaMessageResponse = function (data, t) {\r\n cb = getCallback(callbacks.privateMediaMessageCallbacks, t);\r\n if(cb) {\r\n data.textMsgConfirmedDate = new Date(Date.now());\r\n cb.resolve(data);\r\n }\r\n\r\n util.wtcpInfo(\"Private Media Message Sent\", data);\r\n };\r\n\r\n local.privateMediaMessageError = function (data, t) {\r\n cb = getCallback(callbacks.privateMediaMessageCallbacks, t) ;\r\n if(cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Error sending Private Media Message\");\r\n }\r\n\r\n local.privateMediaMessageUnsol = function(data, t) {\r\n eventDispatcher.trigger(eventList.PRIV_MEDIA_MSG_RECEIVED, data);\r\n util.wtcpInfo(\"Private Media Message Received\", data);\r\n };\r\n\r\n local.callMakeResponse = function(data, t) {\r\n cb = getCallback(callbacks.callMakeRequestCallbacks, t);\r\n if (cb) {\r\n if (data.errorCode > 0) cb.reject(data); else cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"Call Make acknowledged by Proxy\", data);\r\n };\r\n\r\n local.callHangupResponse = function(data, t) {\r\n clearCallStates();\r\n cb = getCallback(callbacks.callHangupRequestCallbacks, t);\r\n if (cb) {\r\n if (data.errorCode > 0) cb.reject(data); else cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"Call Hang-up acknowledged by Proxy\", data);\r\n };\r\n\r\n local.callAnswerResponse = function(data, t) {\r\n cb = getCallback(callbacks.callAnswerRequestCallbacks, t);\r\n if (cb) {\r\n if (data.errorCode > 0) cb.reject(data); else cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"Call Answer acknowledged by Proxy\", data);\r\n };\r\n\r\n local.callHangupUnsol = function(data, t) {\r\n clearCallStates();\r\n eventDispatcher.trigger(eventList.CALL_HANGUP_RECEIVED, data);\r\n util.wtcpInfo(\"Call Hangup Received\", data);\r\n };\r\n\r\n local.callOfferUnsol = function(data, t) {\r\n eventDispatcher.trigger(eventList.CALL_OFFER_RECEIVED, data);\r\n util.wtcpInfo(\"Call Offer Received\", data);\r\n };\r\n\r\n // Version 2\r\n local.setEndpointPropertiesFilterResponse = function (data, t) {\r\n cb = getCallback(callbacks.endpointPropFilteringCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n util.wtcpInfo(\"Set Endpoint Prop Filter Response\", data);\r\n };\r\n\r\n local.setEndpointPropertiesFilterError = function (data, t) {\r\n cb = getCallback(callbacks.endpointPropFilteringCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Set Endpoint Prop Filter Error\", data);\r\n };\r\n\r\n local.setEndpointFilterResponse = function (data, t) {\r\n cb = getCallback(callbacks.endpointFilteringCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n util.wtcpInfo(\"Set Endpoint Filter Response\", data);\r\n };\r\n\r\n local.setEndpointFilterError = function (data, t) {\r\n cb = getCallback(callbacks.endpointFilteringCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Set Endpoint Filter Error\", data);\r\n };\r\n\r\n local.clearEndpointFilterResponse = function(data, t) {\r\n cb = getCallback(callbacks.clearEndpointFilterCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n util.wtcpInfo(\"Clear Endpoint Filer Response\", data);\r\n };\r\n\r\n local.clearEndpointFilterError = function(data, t) {\r\n cb = getCallback(callbacks.clearEndpointFilterCallbacks, t);\r\n\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Clear Endpoint Filter Error\", data);\r\n };\r\n\r\n local.playAudio = function (data) {\r\n //audioHandler.playAudio(d.audioMessages, d.audioLength, d.data);\r\n audioHandler.playAudio(data.audioArrayBuffer, data.audioLength);\r\n };\r\n\r\n local.connectionInfoUpdated = function(data, t) {\r\n eventDispatcher.trigger(eventList.CONNECTION_INFO_UPDATED, data);\r\n util.wtcpInfo(\"Connection Info Updated\", data);\r\n };\r\n\r\n local.wsConnected = function (d, t) {\r\n socketActive = true;\r\n\r\n cb = getCallback(callbacks.socketConnectedCallbacks, t);\r\n if (cb) cb.resolve();\r\n\r\n util.wtcpInfo(\"Web Socket connection established\");\r\n };\r\n\r\n local.wsClosed = function (closeEvent) {\r\n socketActive = false;\r\n eventDispatcher.trigger(eventList.SOCKET_CLOSED, closeEvent);\r\n util.wtcpInfo(\"Web Socket connection closed\", closeEvent);\r\n };\r\n\r\n local.wsError = function (data, t) {\r\n cb = getCallback(callbacks.socketConnectedCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Web Socket connection failed\", data);\r\n };\r\n\r\n // Expose two functions for unit testing\r\n\r\n this.pushCallbacks = pushCallbacks;\r\n this.getCallback = getCallback;\r\n\r\n /* --- Public events --- */\r\n this.onConnectionClosed = new EventSubscriber(eventList.SOCKET_CLOSED);\r\n\r\n this.onSessionClosed = new EventSubscriber(eventList.SESSION_CLOSED_RECEIVED);\r\n\r\n this.onProxyUpdated = new EventSubscriber(eventList.PROXY_UPDATED);\r\n\r\n this.onChannelPropertiesReceived = new EventSubscriber(eventList.CHANNEL_PROPS_RECEIVED);\r\n\r\n this.onChannelActivity = new EventSubscriber(eventList.CHANNEL_ACTIVITY);\r\n\r\n this.onEndpointPropertiesReceived = new EventSubscriber(eventList.ENDPOINT_PROPS_RECEIVED);\r\n\r\n this.onPhoneLineStatusChanged = new EventSubscriber(eventList.PHONE_LINE_STATUS_CHANGED);\r\n\r\n this.onCallProgressReceived = new EventSubscriber(eventList.CALL_PROGRESS_RECEIVED);\r\n\r\n this.onCallHangupReceived = new EventSubscriber(eventList.CALL_HANGUP_RECEIVED);\r\n\r\n this.onCallOfferReceived = new EventSubscriber(eventList.CALL_OFFER_RECEIVED);\r\n\r\n this.onPTTOff = new EventSubscriber(eventList.PTT_OFF);\r\n\r\n this.onDTMFReceived = new EventSubscriber(eventList.DTMF_RECEIEVED);\r\n\r\n this.onCallPTTOnReceived = new EventSubscriber(eventList.CALL_PTT_ON_RECEIVED);\r\n\r\n this.onCallPTTOffReceived = new EventSubscriber(eventList.CALL_PTT_OFF_RECEIVED);\r\n\r\n this.onTextMessageReceived = new EventSubscriber(eventList.TXT_MSG_RECEIVED);\r\n\r\n this.onPrivateMediaMessageReceived = new EventSubscriber(eventList.PRIV_MEDIA_MSG_RECEIVED);\r\n\r\n this.onPingResponse = new EventSubscriber(eventList.PING_PONG_RESPONSE);\r\n\r\n this.onConnectionInfoUpdated = new EventSubscriber(eventList.CONNECTION_INFO_UPDATED);\r\n\r\n /* --- Public client functions --- */\r\n this.connect = function (serverUrl, username, password, profileId) {\r\n\r\n if (wtcpWorker) {\r\n // Re-connecting - terminate existing worker\r\n wtcpWorker.onerror = null;\r\n wtcpWorker.onmessage = null;\r\n wtcpWorker.terminate();\r\n locator = null;\r\n }\r\n\r\n wtcpWorker = clientWorker || new Worker(path + 'wtcp-worker-api.js');\r\n\r\n wtcpWorker.onerror = workerError;\r\n wtcpWorker.onmessage = workerMessage;\r\n\r\n initWorker();\r\n\r\n return new Promise(function (resolve, reject) {\r\n var tranId = pushCallbacks(callbacks.socketConnectedCallbacks, resolve, reject);\r\n locator = new locService.Locator();\r\n if (serverUrl.match(serverUrlPattern)) {\r\n locator.webSocketServer = serverUrl;\r\n\r\n sendMessage(\"connect\", tranId, {\r\n locator: locator\r\n });\r\n } else {\r\n locator.getProxy(serverUrl).then(function () {\r\n if (locator.proxyServerID == null) throw \"Locator not initialized, call getProxy()\";\r\n\r\n let _address;\r\n if (locator.wsPort) {\r\n _address = `${locator.address[0]}:${locator.wsPort}`;\r\n } else {\r\n _address = locator.address[0];\r\n }\r\n\r\n if (!!serverUrl.match(httpsPattern)) {\r\n locator.webSocketServer = `wss://${_address}`;\r\n } else {\r\n locator.webSocketServer = `ws://${_address}`;\r\n }\r\n\r\n sendMessage(\"connect\", tranId, {\r\n locator: locator\r\n });\r\n })[\"catch\"](function (err) {\r\n reject(err);\r\n });\r\n }\r\n }).then(function () {\r\n return login(username, password, profileId);\r\n }, function (err) {\r\n throw \"error connecting to Proxy\";\r\n });\r\n };\r\n\r\n this.setProfile = function (username, password, profileId) {\r\n return new Promise(function (resolve, reject) {\r\n let tranId = pushCallbacks(callbacks.sendCredentialsCallbacks, resolve, reject);\r\n\r\n sendCredentials(tranId, username || \"\", password || \"\", profileId || \"\");\r\n });\r\n };\r\n\r\n // Proxy Request Messages\r\n this.closeSession = function () {\r\n return new Promise(function(resolve, reject) {\r\n sendMessage(\"closeSession\", pushCallbacks(callbacks.closeSessionCallbacks, resolve, reject));\r\n });\r\n };\r\n\r\n this.setActiveChannels = function (channelIds) {\r\n if (!channelIds || !(typeof channelIds === \"object\")) channelIds = [];\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"setActiveChannels\", pushCallbacks(callbacks.setActiveChannelsCallbacks, resolve, reject), {\r\n channelIds: channelIds\r\n });\r\n });\r\n };\r\n\r\n this.getChannelProperties = function (channelId) {\r\n ///Requests Channel Properties from Proxy\r\n ///Channel ID to request properties for\r\n if (!channelId) throw \"getChannelPropertiesRequest(channelId) requires a valid channel Id\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"getChannelPropertiesRequest\", pushCallbacks(callbacks.getChannelPropsCallbacks, resolve, reject), {\r\n channelId: channelId\r\n });\r\n });\r\n };\r\n\r\n this.setChannelProperties = function (channelId, props) {\r\n ///Request Proxy save or update Channel Properties\r\n ///Channel ID to set properties for\r\n ///json object containing key-value pairs\r\n if (!channelId) throw \"setChannelPropertiesRequest(channelId, properties) expects a valid channel Id\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"setChannelPropertiesRequest\", pushCallbacks(callbacks.setChannelPropsCallbacks, resolve, reject), {\r\n channelId: channelId,\r\n props: props\r\n });\r\n });\r\n };\r\n\r\n this.getChannelActivity = function (channelId) {\r\n if (!channelId) throw \"channelActivityRequest(channelId) requires a valid channel Id\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"channelActivityRequest\", pushCallbacks(callbacks.channelActivityCallbacks, resolve, reject), {\r\n channelId: channelId\r\n });\r\n });\r\n };\r\n\r\n this.endpointLookup = function (channelId, includeFlags, excludeFlags, pageSize, pageNumber, nameBeginsWith) {\r\n if (!channelId) throw \"channelActivityRequest(channelId) requires a valid channel Id\";\r\n\r\n includeFlags = includeFlags || new wtcp.EndpointFlags();\r\n excludeFlags = excludeFlags || new wtcp.EndpointFlags();\r\n pageSize = pageSize || 1;\r\n pageNumber = pageNumber || 1;\r\n nameBeginsWith = nameBeginsWith || \"\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"endpointLookupRequest\", pushCallbacks(callbacks.getEndpointLookupCallbacks, resolve, reject), {\r\n channelId: channelId,\r\n includeFlags: includeFlags,\r\n excludeFlags: excludeFlags,\r\n pageSize: pageSize,\r\n pageNumber: pageNumber,\r\n nameBeginsWith: nameBeginsWith\r\n });\r\n });\r\n };\r\n\r\n this.getEndpointProperties = function (endpointId, propList, channelId) {\r\n if (!endpointId) throw \"getEndpointProperties(endpointId, properties) requires a valid endpoint Id\";\r\n\r\n var msgBody = {\r\n endpointId: endpointId,\r\n propList: propList\r\n };\r\n\r\n if (channelId != null) {\r\n msgBody.channelId = channelId;\r\n }\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"getEndpointPropertiesRequest\", pushCallbacks(callbacks.getEndpointPropsCallbacks, resolve, reject), msgBody );\r\n });\r\n };\r\n\r\n this.setEndpointProperties = function (endpointId, props) {\r\n if (!endpointId) throw \"setEndpointProperties(endpointId, properties) requires a valid endpoint Id\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"setEndpointPropertiesRequest\", pushCallbacks(callbacks.setEndpointPropsCallbacks, resolve, reject), {\r\n endpointId: endpointId,\r\n props: props\r\n });\r\n });\r\n };\r\n\r\n this.PTTDown = function (channelIds) {\r\n if (!channelIds || Object.prototype.toString.call(channelIds) !== \"[object Array]\" || channelIds.length === 0) throw \"PTTDown requires an array of channel ids\";\r\n pttDownPending = true;\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n if (!pttOn && !pttUpPending) {\r\n pttOn = true;\r\n sendMessage(\"PTTDown\", pushCallbacks(callbacks.pttDownCallbacks, resolve, reject), {\r\n channelIds: channelIds\r\n });\r\n } else {\r\n util.wtcpError(`ALERT: PTTDown pttOn=${pttOn} and pttUpPending=${pttUpPending}`);\r\n reject(wtcpJsClientErrors[\"PTT_NOT_READY\"]);\r\n }\r\n });\r\n };\r\n\r\n function sendPttUp() {\r\n let sendMessagePromise = new Promise(function (resolve, reject) {\r\n sendMessage(\"PTTUp\", pushCallbacks(callbacks.pttDownCallbacks, resolve, reject));\r\n });\r\n\r\n // wait promise for a second before timeout \r\n return util.promiseTimeout(1000, sendMessagePromise)\r\n .then((result) => { util.wtcpInfo(\"Sending a message : \", result); \r\n return result; })\r\n .catch(err => { util.wtcpInfo(\"ALERT : sending a message :\",err);\r\n return err; });\r\n }\r\n\r\n function awaitPttUp() {\r\n let awaitPromise = new Promise(function(resolve, reject) {\r\n pttUpPending = true;\r\n pttUpSuccess = resolve;\r\n pttUpFailure = reject;\r\n });\r\n\r\n // wait promise for a second before timeout\r\n return util.promiseTimeout(1000, awaitPromise)\r\n .then((result) => { util.wtcpInfo(\"awaitPttUp done, result =\", result);\r\n pttUpPending = false; \r\n pttOn = false;\r\n return result;\r\n })\r\n .catch(err => { util.wtcpInfo(\"awaitPttUp. exception =\", errr);\r\n return err;\r\n });\r\n }\r\n\r\n this.PTTUp = function () {\r\n if (pttDownPending) {\r\n return awaitPttUp();\r\n } else {\r\n if (audioHandler) {\r\n return util.promiseTimeout(1000, audioHandler.endAudio())\r\n .then(() => {return sendPttUp();})\r\n .catch((err) => {\r\n // will send sendPttUp even if failed to close endAudio\r\n util.wtcInfo('ALERT: PttUp failed while waiting endAudio call', err);\r\n return sendPttUp();\r\n });\r\n } else {\r\n util.wtcpDebug(\"no audio handler\");\r\n return sendPttUp();\r\n }\r\n }\r\n };\r\n\r\n function sendCallPttUp(callId) {\r\n return new Promise(function (resolve, reject) {\r\n sendMessage(\"callPTTOffRequest\", pushCallbacks(callbacks.callPTTOffCallbacks, resolve, reject), {\r\n callId: callId\r\n });\r\n });\r\n }\r\n\r\n this.callPTTOn = function(callId) {\r\n if (!callId) throw \"callPTTOn(callId) requires a valid call Id\";\r\n\r\n pttDownPending = true;\r\n\r\n return new Promise(function(resolve, reject) {\r\n\r\n if (!pttOn) {\r\n pttOn = true;\r\n\r\n sendMessage(\"callPTTOnRequest\", pushCallbacks(callbacks.callPTTOnCallbacks, resolve, reject), {\r\n callId: callId\r\n });\r\n } else {\r\n reject(wtcpJsClientErrors[\"PTT_NOT_READY\"]);\r\n }\r\n });\r\n };\r\n\r\n this.callPTTOff = function (callId) {\r\n if (!callId) throw \"callPTTOff(callId) requires a valid call Id\";\r\n\r\n if (pttDownPending) {\r\n\r\n return awaitPttUp();\r\n } else {\r\n if (audioHandler) {\r\n return audioHandler.endAudio().then(() => {\r\n return sendCallPttUp(callId);\r\n }).catch((err) => {\r\n util.wtcpError('callPTTOff failed', err);\r\n });\r\n } else {\r\n return sendCallPttUp(callId);\r\n }\r\n }\r\n };\r\n\r\n this.setActivePhoneLines = function (phoneLines) {\r\n let fail = !phoneLines;\r\n\r\n if (!fail) {\r\n for (let line of phoneLines) {\r\n if (!line) {\r\n fail = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (fail ) throw \"setActivePhoneLines requires a list of phone lines\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"setActivePhoneLines\", pushCallbacks(callbacks.setActivePhoneLinesCallbacks, resolve, reject), {\r\n phoneLines: phoneLines\r\n });\r\n });\r\n };\r\n\r\n this.makeCall = function (type, source, destination) {\r\n ///Make a point-to-point call request\r\n ///Endpoint == 1, E164 number == 2\r\n ///Phone line to use to make the call (as returned by \"Start Call Provider\") response\r\n ///if type === 1, then this is the endpoint to reach, otherwise it is the phone number to call\r\n ///Returns a Promise\r\n if (!type) throw \"makeCall(type, source, destination) requires type, source, and destination\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"callMakeRequest\", pushCallbacks(callbacks.callMakeRequestCallbacks, resolve, reject), {\r\n type: type,\r\n source: source,\r\n destination: destination\r\n });\r\n });\r\n };\r\n\r\n this.answerCall = function(callId) {\r\n if (!callId) throw \"answerCall requires a valid call Id\";\r\n\r\n return new Promise(function(resolve, reject) {\r\n sendMessage(\"callAnswerRequest\", pushCallbacks(callbacks.callAnswerRequestCallbacks, resolve, reject), {\r\n callId: callId\r\n });\r\n });\r\n };\r\n\r\n this.hangupCall = function (callId) {\r\n if (!callId) throw \"hangupCall requires a valid call Id\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"callHangUpRequest\", pushCallbacks(callbacks.callHangupRequestCallbacks, resolve, reject), {\r\n callId: callId\r\n });\r\n });\r\n };\r\n\r\n this.muteAllChannels = function () {\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"muteAllChannels\", pushCallbacks(callbacks.muteChannelCallbacks, resolve, reject));\r\n });\r\n };\r\n\r\n this.unmuteAllChannels = function () {\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"unmuteAllChannels\", pushCallbacks(callbacks.muteChannelCallbacks, resolve, reject));\r\n });\r\n };\r\n\r\n this.muteChannels = function (channels) {\r\n if (!channels) throw \"muteChannels(chanels) requires a valid list of channels\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"muteChannels\", pushCallbacks(callbacks.muteChannelCallbacks, resolve, reject), { channels: channels });\r\n });\r\n };\r\n\r\n this.dtmfSendRequest = function (callId, dtmf) {\r\n if (!callId) throw \"dtmfSendRequest(callId) was called without a valid callId\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"dtmfSendRequest\", pushCallbacks(callbacks.dtmfSendCallbacks, resolve, reject), {\r\n callId: callId,\r\n dtmf: dtmf\r\n });\r\n });\r\n };\r\n\r\n this.getAddressBook = function (pageSize, pageNum, filter) {\r\n if (locator.version === 1 || !filter || filter.length === 0) filter = \"*\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"getAddressBook\", pushCallbacks(callbacks.addressBookCallbacks, resolve, reject), {\r\n pageSize: pageSize || 200,\r\n pageNum: pageNum || 1,\r\n filter: filter\r\n });\r\n });\r\n };\r\n\r\n function getDefaultOptions() {\r\n var options = {};\r\n\r\n if (!options.hasOwnProperty(\"important\")) options.important = false;\r\n\r\n return options\r\n }\r\n\r\n this.sendTextMessage = function (channelId, message, options) {\r\n if (!channelId || typeof channelId !== \"number\") throw \"sendTextMessage(channelId, message) requires a valid channel Id\";\r\n\r\n options = options || getDefaultOptions();\r\n\r\n if (options.important) message = \"[[ALERT1]]\" + message;\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n // Only channel text messages are currently implemented\r\n sendMessage(\"sendTextMessage\", pushCallbacks(callbacks.textMessageCallbacks, resolve, reject), {\r\n channelId: channelId,\r\n message: message\r\n });\r\n });\r\n };\r\n\r\n this.sendP2PMessage = function(privateTextMessageRequest, options) {\r\n if (!privateTextMessageRequest || !privateTextMessageRequest instanceof wtcp.PrivateTextMessageRequest) throw \"sendP2PMessage(privateTextMessageRequest) argument must be type PrivateTextMessageRequest\";\r\n\r\n options = options || getDefaultOptions();\r\n\r\n // eventually this should be replaced with metadata and handled in the client, not WtcpJs\r\n if (options.important) privateTextMessageRequest.data = \"[[ALERT1]]\" + privateTextMessageRequest.data;\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n // assumed will always be a text/plain message. We will have to change the signature when we support multimedia messages\r\n sendMessage(\"sendP2PMessage\", pushCallbacks(callbacks.privateMediaMessageCallbacks, resolve, reject), privateTextMessageRequest);\r\n });\r\n }\r\n\r\n // Version 2\r\n var setEndpointFilter = function setEndpointFilter(type, filterId, channelId, endpointFilter, propFilter, endpointId, threshold, anchor) {\r\n /*if (locator.version < 2)\r\n throw \"Endpoint filtering is only supported in WTCP version 2 or greater\";*/\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"setEndpointFilter\", pushCallbacks(callbacks.endpointFilteringCallbacks, resolve, reject), {\r\n filterId: filterId,\r\n type: type,\r\n channelId: channelId,\r\n endpointFilter: endpointFilter,\r\n propertyFilter: propFilter,\r\n endpointId: endpointId,\r\n notificationThreshold: threshold,\r\n anchorInfo: anchor\r\n });\r\n });\r\n };\r\n\r\n this.setEndpointChannelFilter = function (filterId, channelId, endpointFilter, propFilter, threshold, anchorInfo) {\r\n if (!channelId) throw \"channelId argument is required\";\r\n\r\n return setEndpointFilter(2, filterId, channelId, endpointFilter, propFilter, '', threshold, anchorInfo);\r\n };\r\n\r\n this.setEndpointSPCFilter = function (filterId, endpointId, endpointFilter, propFilter, threshold, anchorInfo) {\r\n return setEndpointFilter(1, filterId, 0, endpointFilter, propFilter, endpointId, threshold, anchorInfo);\r\n };\r\n\r\n this.setEndpointAddressBookFilter = function (filterId, endpointFilter, propFilter, threshold, anchorInfo) {\r\n return setEndpointFilter(3, filterId, 0, endpointFilter, propFilter, '', threshold, anchorInfo);\r\n };\r\n\r\n this.clearEndpointFilter = function (filterId) {\r\n if (!filterId || isNaN(filterId)) throw new Error(\"Invalid argument type for filterId, must be an unsigned integer value\");\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n // Only channel text messages are currently implemented\r\n sendMessage(\"clearEndpointFilter\", pushCallbacks(callbacks.clearEndpointFilterCallbacks, resolve, reject), {\r\n filterId: filterId\r\n });\r\n });\r\n };\r\n\r\n var setEndpointPropertiesFilter = function(type, filter) {\r\n if (type < 1 || type > 6) throw \"setEndpointPropertiesFilter(type, filter) type argument is required\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"setEndpointPropertiesFilter\", pushCallbacks(callbacks.endpointPropFilteringCallbacks, resolve, reject), { type: type, filter: filter });\r\n });\r\n };\r\n\r\n this.setEndpointPropertiesPrivateCallFilter = function (filter) {\r\n return setEndpointPropertiesFilter(1, filter);\r\n };\r\n\r\n this.setEndpointPropertiesTextMessageFilter = function (filter) {\r\n return setEndpointPropertiesFilter(2, filter);\r\n };\r\n\r\n this.setEndpointPropertiesChannelActivityFilter = function (filter) {\r\n return setEndpointPropertiesFilter(3, filter);\r\n };\r\n\r\n this.setEndpointPropertiesPrivateMessageFilter = function (filter) {\r\n return setEndpointPropertiesFilter(4, filter);\r\n };\r\n\r\n this.visualizeAudio = function (canvas) {\r\n audioHandler.visualize(canvas);\r\n };\r\n\r\n this.setVolume = function (volume) {\r\n audioHandler.setVolume(volume);\r\n };\r\n\r\n this.destroy = function () {\r\n if (socketActive)\r\n return this.closeSession();\r\n else return new Promise(function(resolve, reject) {\r\n try {\r\n teardownClient();\r\n } catch (e) {\r\n reject(e);\r\n } finally {\r\n eventDispatcher.events = {};\r\n resolve();\r\n }\r\n });\r\n };\r\n\r\n this.SendMessage = sendMessage;\r\n\r\n init();\r\n\r\n return this;\r\n };\r\n\r\n module.exports = wtcp;\r\n})(global.WtcpJs);\n}).call(this)}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n\n},{\"./wtcp-types/ErrorResponse.js\":2,\"./wtcp-types/requests/AnchorInfo.js\":3,\"./wtcp-types/requests/PrivateTextMessageRequest.js\":4,\"./wtcp.locator.js\":6,\"./wtcp.util.js\":7,\"./wtcp.wtcpaudio.js\":8,\"ua-parser-js\":10}],6:[function(require,module,exports){\n(function (global){(function (){\n/// \r\nglobal.WtcpJs = global.WtcpJs || {};\r\n\r\nvar util = require('./wtcp.util.js');\r\n\r\n(function(locatorModule) {\r\n\r\n function getNonce() {\r\n return Math.floor(Math.random() * 9999) + 1;\r\n }\r\n\r\n locatorModule.JXON = function(options) {\r\n if (!(this instanceof locatorModule.JXON))\r\n return new locatorModule.JXON(options);\r\n\r\n return this;\r\n };\r\n\r\n /*locatorModule.JXON.prototype = Object.create(locatorModule.WtcpBase.prototype);\r\n locatorModule.JXON.prototype.constructor = locatorModule.JXON;*/\r\n\r\n locatorModule.JXON.prototype.getJXONTree = function(oXMLParent) {\r\n oXMLParent.hasAttributes = oXMLParent.hasAttributes || function() { return false; };\r\n var vResult = /* put here the default value for empty nodes! */ true, nLength = 0, sCollectedTxt = \"\", oAttrib = null;\r\n if (oXMLParent.hasAttributes()) {\r\n vResult = {};\r\n for (nLength; nLength < oXMLParent.attributes.length; nLength++) {\r\n oAttrib = oXMLParent.attributes.item(nLength);\r\n vResult[\"@\" + oAttrib.name.toLowerCase()] = this.parseText(oAttrib.value.trim());\r\n }\r\n }\r\n if (oXMLParent.hasChildNodes()) {\r\n for (var oNode, sProp, vContent, nItem = 0; nItem < oXMLParent.childNodes.length; nItem++) {\r\n oNode = oXMLParent.childNodes.item(nItem);\r\n if (oNode.nodeType === 4) {\r\n sCollectedTxt += oNode.nodeValue;\r\n } /* nodeType is \"CDATASection\" (4) */\r\n else if (oNode.nodeType === 3) {\r\n sCollectedTxt += oNode.nodeValue.trim();\r\n } /* nodeType is \"Text\" (3) */\r\n else if (oNode.nodeType === 1 && !oNode.prefix) { /* nodeType is \"Element\" (1) */\r\n if (nLength === 0) {\r\n vResult = {};\r\n }\r\n sProp = oNode.nodeName.toLowerCase();\r\n vContent = this.getJXONTree(oNode);\r\n if (vResult.hasOwnProperty(sProp)) {\r\n if (vResult[sProp].constructor !== Array) {\r\n vResult[sProp] = [vResult[sProp]];\r\n }\r\n vResult[sProp].push(vContent);\r\n } else {\r\n vResult[sProp] = vContent;\r\n nLength++;\r\n }\r\n }\r\n }\r\n }\r\n if (sCollectedTxt) {\r\n nLength > 0 ? vResult.keyValue = this.parseText(sCollectedTxt) : vResult = this.parseText(sCollectedTxt);\r\n }\r\n /* if (nLength > 0) { Object.freeze(vResult); } */\r\n return vResult;\r\n }\r\n\r\n locatorModule.JXON.prototype.parseText = function(sValue) {\r\n if (/^\\s*$/.test(sValue)) {\r\n return null;\r\n }\r\n if (/^(?:true|false)$/i.test(sValue)) {\r\n return sValue.toLowerCase() === \"true\";\r\n }\r\n if (isFinite(sValue)) {\r\n return parseFloat(sValue);\r\n }\r\n if (isFinite(Date.parse(sValue))) {\r\n return new Date(sValue);\r\n }\r\n return sValue;\r\n };\r\n\r\n locatorModule.Locator = function(options) {\r\n if (!(this instanceof locatorModule.Locator))\r\n return new locatorModule.Locator(options);\r\n\r\n locatorModule.JXON.call(this);\r\n this.proxyServerID = null;\r\n this.proxyIndex = null;\r\n this.address = [];\r\n this.port = [];\r\n this.wsPort = 443;\r\n this.softwareVersionCheckUrl = null;\r\n this.version = 2;\r\n this.controlVersion = 1;\r\n this.httpStatusCode = 200; \r\n\r\n return this;\r\n };\r\n\r\n locatorModule.Locator.prototype = Object.create(locatorModule.JXON.prototype);\r\n locatorModule.Locator.prototype.constructor = locatorModule.Locator;\r\n\r\n locatorModule.Locator.prototype.getProxy = function (proxyurl) {\r\n let _proxyurl = proxyurl;\r\n return this.tryToGetProxy(\r\n `${_proxyurl}/waveapi/proxy_locator.asp?action=getproxy&pc=wtcpJs&ver=3.0.0&requires=WTCPv2&nonce=${getNonce()}`)\r\n .then( result => { \r\n // Due to hardening, we got 403 forbidden response\r\n // we try again with new URL /wave/_locator/proxy_locator.asp with the same parameter \r\n if( result.httpStatusCode == 403) {\r\n return this.tryToGetProxy(\r\n `${_proxyurl}/wave/_locator/proxy_locator.asp?action=getproxy&pc=wtcpJs&ver=3.0.0&requires=WTCPv2&nonce=${getNonce()}`)\r\n .then(result => {return result; });\r\n }\r\n else {\r\n return result; \r\n }\r\n },\r\n error => { \r\n util.wtcpError(\"Error to get proxy\", error);\r\n return Promise.reject(error);\r\n })\r\n .then(result => { return result;},\r\n err => { util.wtcpError(\"Exception at getProxy: \", err); return Promise.reject(err);} );\r\n\r\n }\r\n\r\n locatorModule.Locator.prototype.tryToGetProxy = function (targetUrl) {\r\n let locatorUrl = targetUrl;\r\n var _this = this;\r\n return new Promise(function(resolve, reject) {\r\n var oReq = new XMLHttpRequest();\r\n\r\n util.wtcpInfo(\"TPS Locator | getProxy url: \" , locatorUrl);\r\n\r\n oReq.onload = function(e) {\r\n\r\n _this.httpStatusCode = e.currentTarget.status;\r\n if (e.currentTarget.status === 200) {\r\n var response = _this.getJXONTree(this.responseXML);\r\n if (response.serverresponse[\"@error\"])\r\n util.wtcpError(\"Proxy Locator returned error code \" + response.serverresponse[\"@error\"]);\r\n else {\r\n var proxy = response.serverresponse.proxy;\r\n _this.proxyServerID = proxy[\"@serverid\"];\r\n _this.proxyIndex = proxy[\"@proxyindex\"];\r\n _this.address[0] = proxy[\"@address1\"];\r\n _this.address[1] = proxy[\"@address2\"];\r\n _this.port[0] = proxy[\"@port1\"];\r\n _this.port[1] = proxy[\"@port2\"];\r\n _this.wsPort = proxy[\"@wsport\"];\r\n _this.softwareVersionCheckUrl = proxy[\"@softwareversioncheckurl\"];\r\n _this.version = 2; // TBD: WTCP version number should be added to locator service\r\n _this.controlVersion = 1; // TBD: WTCP-Ctrl OpCode version should be added to locator service\r\n \r\n util.wtcpInfo(\"TPS Locator | proxyIndex: \" + _this.proxyIndex + \", ProxyServerID: \" +\r\n _this.proxyServerID + \", addrss1: \" +\r\n _this.address[0] + \", address2: \" +\r\n _this.address[1] + \", port1: \" +\r\n _this.port[0] + \", port2: \" +\r\n _this.port[1]);\r\n }\r\n } \r\n resolve(_this);\r\n };\r\n\r\n oReq.onerror = function(err) {\r\n if (typeof reject !== \"undefined\" && reject)\r\n reject(err.statusText);\r\n }\r\n\r\n oReq.open(\"get\", locatorUrl, true);\r\n try\r\n {\r\n oReq.send(); \r\n }\r\n catch(ex)\r\n {\r\n reject(\"exception in tryToGetProxy : \"+ ex);\r\n }\r\n \r\n }); \r\n }\r\n\r\n module.exports = locatorModule;\r\n\r\n})(global.WtcpJs);\n}).call(this)}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n\n},{\"./wtcp.util.js\":7}],7:[function(require,module,exports){\n(function (global){(function (){\n\"use strict\";\r\n\r\nglobal.WtcpJs = global.WtcpJs || {};\r\n\r\n(function() {\r\n let doc;\r\n let decoder;\r\n let loggingLevels = {\r\n none: 0,\r\n error: 1,\r\n warn: 2,\r\n debug: 3,\r\n info: 4\r\n };\r\n\r\n let baseLogMsg = 'WtcpJs:';\r\n\r\n try {\r\n doc = document;\r\n } catch (e) {\r\n doc = undefined;\r\n }\r\n\r\n var scriptPath = '';\r\n if (doc) {\r\n var scriptEls = doc.getElementsByTagName('script');\r\n var thisScriptEl = scriptEls[scriptEls.length - 1];\r\n var scriptSrc = thisScriptEl.src;\r\n scriptPath = scriptSrc.substr(0, scriptSrc.lastIndexOf('/') + 1);\r\n }\r\n\r\n // Detect Endianness\r\n var littleEndian = (function() {\r\n var buffer = new ArrayBuffer(2);\r\n new DataView(buffer).setInt16(0, 256, true);\r\n return new Int16Array(buffer)[0] === 256;\r\n })();\r\n\r\n //let wtcpLog = Symbol('wtcpLog');\r\n\r\n var WtcpUtil = function() {\r\n\r\n this.logLevel = 0;\r\n\r\n // Public properties\r\n Object.defineProperty(this, \"Path\", { get: function() { return scriptPath; } });\r\n Object.defineProperty(this, \"LittleEndian\", { get: function() { return littleEndian; } });\r\n };\r\n\r\n // default to 'info' - 3. If we don't specify or bad value, get as much info as possible\r\n WtcpUtil.prototype.setLoggingLevel = function (value) {\r\n if (!Number.isInteger(value))\r\n value = value in loggingLevels ? loggingLevels[value] : 4; // default to 'info'\r\n\r\n this.logLevel = value < 0 ? 0 : value > 4 ? 4 : value; // 0 <= logLevel <= 3\r\n }\r\n\r\n function formatLogMsg(fn, msg, args) {\r\n fn.call(console, `${baseLogMsg} ${msg}`, args);\r\n }\r\n\r\n WtcpUtil.prototype.wtcpInfo = function(e, ...args) {\r\n if (this.logLevel >= loggingLevels.info)\r\n formatLogMsg(console.info, e, args);\r\n }\r\n\r\n WtcpUtil.prototype.wtcpDebug = function(e, ...args) {\r\n if(this.logLevel >= loggingLevels.debug)\r\n formatLogMsg(console.debug, e, args);\r\n }\r\n\r\n WtcpUtil.prototype.wtcpWarn = function(e, ...args) {\r\n if (this.logLevel >= loggingLevels.warn)\r\n formatLogMsg(console.warn, e, args);\r\n }\r\n\r\n WtcpUtil.prototype.wtcpError = function(e, ...args) {\r\n if(this.logLevel >= loggingLevels.error)\r\n formatLogMsg(console.error, e, args);\r\n }\r\n\r\n var messages = '';\r\n\r\n WtcpUtil.prototype.debugWindow = function(messageClass, message) {\r\n var date = new Date();\r\n var time = date.getHours() + \":\" + date.getMinutes() + \":\" + date.getSeconds() + \".\" + date.getMilliseconds();\r\n messages += time + \" | \" + messageClass + \": \" + message + \"\\n\";\r\n\r\n //doc.getElementById(\"debugMessageWindow\").innerText = messages;\r\n };\r\n\r\n WtcpUtil.prototype.loadScript = function(filename, callback) {\r\n if (doc !== undefined) {\r\n var scriptElem = doc.createElement('script');\r\n scriptElem.setAttribute(\"type\", \"text/javascript\");\r\n scriptElem.setAttribute(\"src\", filename);\r\n scriptElem.onload = function(e) {\r\n if (callback)\r\n callback.call(this, e);\r\n };\r\n scriptElem.onerror = function(e) {\r\n if (callback)\r\n callback.call(this, e);\r\n }\r\n doc.getElementsByTagName(\"head\")[0].appendChild(scriptElem);\r\n } else {\r\n throw \"Use importScripts from Web Workers, loadScript only works from UI thread\";\r\n }\r\n };\r\n\r\n WtcpUtil.prototype.getScriptPath = function() {\r\n return scriptPath;\r\n };\r\n\r\n WtcpUtil.prototype.byteWriter = function(view, val, length, offset) {\r\n //only use this for tiny, short, or int (length 1, 2, or 4)\r\n //doesn't work for setting negative values\r\n //needs a lot of work, need to switch to using dataview??\r\n var shift;\r\n if (!offset)\r\n offset = 0;\r\n\r\n var n = offset + length;\r\n\r\n for (var x = offset; x < n; x++) {\r\n shift = ((n - (x + 1)) * 8);\r\n if (x === offset)\r\n view[x] = val >>> shift;\r\n else\r\n view[x] = (val >>> shift) ^ (view[x - 1] << 8);\r\n }\r\n };\r\n\r\n WtcpUtil.prototype.stringReader = function(data, position) {\r\n ///Gets the UTF-8 string value from byte stream at specified position\r\n ///\r\n ///Numeric position from beginning of ArrayBuffer to start reading\r\n ///returns {string: 'text', str_terminate: position}\r\n try {\r\n decoder = new TextDecoder(\"utf-8\");\r\n } catch (e) {\r\n //TBD: Works in Chrome, but need to add poly-fill or use existing library if not defined\r\n throw \"browser does not support TextDecoder\";\r\n }\r\n\r\n var i;\r\n var str = \"\";\r\n\r\n try {\r\n\r\n var view = new Uint8Array(data);\r\n\r\n for (i = position; i < view.length; i++) {\r\n if (view[i] === 0)\r\n break;\r\n }\r\n\r\n var strView = new Uint8Array(data, position, i - position);\r\n\r\n str = decoder.decode(strView);\r\n\r\n } catch (exc) {\r\n this.wtcpError(\"Error decoding UTF-8 string\", exc);\r\n }\r\n\r\n return { value: str, position: i };\r\n };\r\n\r\n WtcpUtil.prototype.byteReader = function(view, length, offset) {\r\n ///Retrieve value from byte stream at specified offset and length\r\n ///\r\n ///Number of bytes to read\r\n ///Numeric offset from beginning of ArrayBufferView to start reading\r\n ///returns numeric value\r\n\r\n var n = length + offset;\r\n var val = 0, shift;\r\n for (var x = offset; x < n; x++) {\r\n shift = ((n - (x + 1)) * 8);\r\n val += view[x] << shift;\r\n }\r\n return val;\r\n };\r\n\r\n WtcpUtil.prototype.addBitrange = function(val, valToAdd, bitLength, lshBytes) {\r\n ///Isolates a bit range from value\r\n ///Value to add to\r\n ///Value to add\r\n ///Number of bits to write\r\n ///Byte length of value (1 for INT8, 2 for INT16, etc...)\r\n ///\r\n\r\n if (valToAdd > (Math.pow(2, bitLength) - 1))\r\n throw `value is too great for the bitLength specified: ${valToAdd} > ${(Math.pow(2, bitLength) - 1)} for bitlength ${bitLength}`;\r\n\r\n valToAdd = valToAdd << (lshBytes * 8);\r\n val |= valToAdd;\r\n\r\n return val;\r\n };\r\n\r\n WtcpUtil.prototype.mergeArrayBuffers = function(bufferInfo1, bufferInfo2) {\r\n ///Merge two array buffers\r\n ///{buffer: ArrayBuffer, offset: Int}\r\n ///{buffer: ArrayBuffer, offset: Int}\r\n ///\r\n var ta = new Int8Array(bufferInfo1.buffer, bufferInfo1.offset);\r\n var tb = new Int8Array(bufferInfo2.buffer, bufferInfo2.offset);\r\n var n = new Int8Array(ta.length + tb.length);\r\n n.set(ta);\r\n n.set(tb, (ta.length - bufferInfo1.offset));\r\n\r\n return n.buffer;\r\n };\r\n\r\n /**\r\n * bitwise reader for extracting bit ranges from a TypedArray value\r\n * @param {Number} val - numeric value to extract bit range from \r\n * @param {Number} bitPos - bit position to start reading \r\n * @param {Number} bitLength - total number of bits to read \r\n * @param {Number} numBytes - byte length of value (1 for INT8, 2 for INT16, etc...)\r\n * @returns {Number} \r\n */\r\n WtcpUtil.prototype.bitReader = function(val, bitPos, bitLength, numBytes) {\r\n var totalBits = (numBytes * 8) - 1;\r\n\r\n let n = totalBits;\r\n\r\n while (n > bitPos) {\r\n val = val & ~(1 << n--);\r\n }\r\n val = val >>> (bitPos - bitLength) + 1;\r\n\r\n return val;\r\n };\r\n\r\n WtcpUtil.prototype.parseWtcpHeader = function(offset, data) {\r\n var int8View = new Uint8Array(data, offset, 4);\r\n var h = this.byteReader(int8View, 4, 0);\r\n return {\r\n version: this.bitReader(h, 31, 3, 4) + 1,\r\n type: this.bitReader(h, 28, 3, 4),\r\n sequence: this.bitReader(h, 25, 10, 4),\r\n payloadLength: this.bitReader(h, 15, 16, 4)\r\n };\r\n };\r\n\r\n WtcpUtil.prototype.promiseTimeout = function(ms, promise) {\r\n\r\n // create a promise that rejects in milliseconds\r\n \r\n let timerId; \r\n let timedPromise = new Promise((resolve, reject) => \r\n {\r\n timerId = setTimeout(() => { reject('timeout in ' + ms + ' ms'); }, ms); \r\n }); \r\n\r\n // returns a race between our timeout and the passed in promise\r\n\r\n return Promise.race([timedPromise, promise])\r\n .then( (result) => { clearTimeout(timerId); \r\n return result;\r\n })\r\n .catch((err) => { \r\n console.log(\"ALERT : race exception : \", err)\r\n return err;});\r\n };\r\n\r\n WtcpUtil.prototype.EndpointFlags = function() {\r\n this.Moderator = false;\r\n this.Speaking = false;\r\n this.Typing = false;\r\n this.AudioTxMute = false;\r\n this.TextMute = false;\r\n this.Unavailable = false;\r\n this.Visible = false;\r\n this.AudioRxMute = false;\r\n this.TxSilence = false;\r\n this.RxSilence = false;\r\n this.EmergencyTx = false;\r\n this.Self = false;\r\n this.P2P = false;\r\n this.Gone = false;\r\n\r\n return this;\r\n };\r\n\r\n WtcpJs.EndpointFlags = WtcpUtil.prototype.EndpointFlags;\r\n\r\n module.exports = new WtcpUtil();\r\n})();\n}).call(this)}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n\n},{}],8:[function(require,module,exports){\n(function (global){(function (){\n/// \r\n/// \r\n\"use strict\";\r\n\r\nglobal.WtcpJs = global.WtcpJs || {};\r\n\r\nvar util = require('./wtcp.util.js');\r\n\r\n(function(wtcp) {\r\n\r\n wtcp.WTCPAudio = function(client, settings) {\r\n\r\n const SMOOTHING = 0.8;\r\n const FFT_SIZE = 2048;\r\n\r\n var _this = this;\r\n var context;\r\n var gainNode;\r\n var visCanvas;\r\n var analyser;\r\n var micStream;\r\n var microphone, scriptNode, biquadFilter, offlineContext;\r\n var channelData;\r\n var sampleRate;\r\n var downsampleBuffer;\r\n var audioSamplesStarted = 0;\r\n var audioSamplesEnded = 0;\r\n var audioEndTime;\r\n var times;\r\n var initStatus = {\r\n status: 'inprogress',\r\n message: 'In Progress'\r\n };\r\n var micEnabled = false;\r\n var sendingAudio = false;\r\n var audioPlaying = false;\r\n var playerActive = settings.audioPlayerActive;\r\n var isVisualizing = false;\r\n var audioQueueTimeout = null;\r\n var audioQueue = [];\r\n var audioQueueBufferLength = 0;\r\n var endAudioSuccess, endAudioFailure;\r\n this.messageHandlers = {};\r\n\r\n this.getStatus = function getStatus() { return initStatus; }\r\n\r\n // Properties\r\n Object.defineProperty(this, \"MicrophoneEnabled\", { get: function() { return micEnabled; } });\r\n Object.defineProperty(this, \"PlayerEnabled\", {\r\n get: function() { return playerActive; },\r\n set: function (isEnabled) {\r\n playerActive = isEnabled;\r\n\r\n if (!(playerActive) && audioQueueTimeout) {\r\n clearTimeout(audioQueueTimeout);\r\n audioQueueTimeout = null;\r\n }\r\n\r\n util.wtcpDebug(`WtcpAudio.PlayerEnabled: audio player is now ${playerActive ? 'on' : 'off'}`);\r\n }\r\n });\r\n\r\n function asFloat(pct) {\r\n return pct < 0 ? 0 : pct >= 100 ? 1 : pct / 100;\r\n }\r\n\r\n /* remove this after some testing\r\n function convertToMono(input) {\r\n var splitter = context.createChannelSplitter(2);\r\n var merger = context.createChannelMerger(2);\r\n\r\n input.connect(splitter);\r\n splitter.connect(merger, 0, 0);\r\n splitter.connect(merger, 0, 1);\r\n return merger;\r\n } */\r\n\r\n function audioBufferSourceNodeEnded(e) {\r\n if (++audioSamplesEnded === audioSamplesStarted) {\r\n audioPlaying = false;\r\n audioSamplesEnded = 0;\r\n audioSamplesStarted = 0;\r\n }\r\n }\r\n\r\n function setGain(val) {\r\n gainNode.gain.value = asFloat(val);\r\n }\r\n\r\n function draw() {\r\n // Draw the time domain chart.\r\n var bufferLength = analyser.frequencyBinCount;\r\n var sliceWidth = visCanvas.width * 1.0 / bufferLength;\r\n var x = 0, v = 0, y = 0;\r\n var drawCtx = visCanvas.getContext('2d');\r\n drawCtx.clearRect(0, 0, visCanvas.width, visCanvas.height);\r\n drawCtx.lineWidth = 2;\r\n drawCtx.strokeStyle = 'white';\r\n drawCtx.beginPath();\r\n\r\n analyser.getByteTimeDomainData(times);\r\n\r\n for (var i = 0; i < bufferLength; i++) {\r\n v = times[i] / 128.0;\r\n y = v * visCanvas.height / 2;\r\n\r\n if (i === 0)\r\n drawCtx.moveTo(x, y);\r\n else\r\n drawCtx.lineTo(x, y);\r\n\r\n x += sliceWidth;\r\n }\r\n\r\n drawCtx.lineTo(visCanvas.width, visCanvas.height / 2);\r\n drawCtx.stroke();\r\n }\r\n\r\n function startAudio(src) {\r\n audioSamplesStarted++;\r\n\r\n src.connect(gainNode);\r\n gainNode.connect(isVisualizing ? analyser : context.destination);\r\n\r\n if (!audioPlaying) {\r\n audioPlaying = true;\r\n //audioEndTime = context.currentTime + .05;\r\n audioEndTime = context.currentTime;\r\n }\r\n src.start(audioEndTime);\r\n audioEndTime += (src.buffer.duration);\r\n\r\n if (isVisualizing)\r\n requestAnimationFrame(draw);\r\n }\r\n\r\n this.playAudio = function(buffer, audioLength) {\r\n if (!playerActive)\r\n return;\r\n\r\n audioQueue.push(buffer);\r\n audioQueueBufferLength += audioLength;\r\n\r\n if (!audioQueueTimeout) {\r\n audioQueueTimeout = setTimeout(function() {\r\n var data = audioQueue;\r\n var len = audioQueueBufferLength;\r\n\r\n audioQueue = [];\r\n audioQueueBufferLength = 0;\r\n\r\n var src = context.createBufferSource();\r\n src.onended = audioBufferSourceNodeEnded;\r\n\r\n var b = data[0];\r\n for (var x = 1; x < data.length; x++) {\r\n b = util.mergeArrayBuffers({ buffer: b, offset: 0 }, { buffer: data[x], offset: 0 });\r\n }\r\n\r\n // Experimental feature - trying to decode Opus. Use if (1) to enable\r\n if (0) {\r\n context.decodeAudioData(buffer, function(data) {\r\n src.buffer = data;\r\n\r\n startAudio(src);\r\n }, function(e) { util.wtcpInfo(\"Error decoding audio\", e); });\r\n } else {\r\n var audioArrayBuffer = context.createBuffer(1, (len / 2), 8000);\r\n audioArrayBuffer.copyToChannel(new Float32Array(b), 0);\r\n src.buffer = audioArrayBuffer;\r\n\r\n util.wtcpDebug(\"Scheduling audio clip: duration = \" + src.buffer.duration + \", Queue depth: \" + data.length + \", buffer length: \" + len);\r\n startAudio(src);\r\n\r\n audioQueueTimeout = null;\r\n }\r\n }, 250);\r\n }\r\n };\r\n\r\n this.sendAudio = function() {\r\n\r\n // scriptProcessorNode's dont work on OfflineAudioContexts in chrome. Its not getting fixed\r\n // because scriptprocessor nodes are going away in favor of Audio Workers, which will work with offlinecontexts\r\n // Will have to use scriptProcessorNode for now\r\n\r\n if (!sendingAudio && typeof context.createMediaStreamSource === \"function\") {\r\n let halting = false;\r\n sendingAudio = true;\r\n\r\n if (micStream) {\r\n\r\n microphone = context.createMediaStreamSource(micStream);\r\n scriptNode = context.createScriptProcessor(settings.processorNodeBufferSize, 1, 1);\r\n biquadFilter = context.createBiquadFilter();\r\n biquadFilter.type = 'lowpass';\r\n biquadFilter.frequency.value = 4000;\r\n biquadFilter.Q.value = 2;\r\n\r\n scriptNode.onaudioprocess = function(e) {\r\n\r\n /* ---------------- OfflineAudioContext method of downsampling audio ---------------------------------------- \r\n // This works but you still get clicking artifacts after every sample\r\n var b, source;\r\n offlineContext = new OfflineAudioContext(1, e.inputBuffer.length / (e.inputBuffer.sampleRate / 8000), 8000);\r\n\r\n offlineContext.oncomplete = function(audioBuffer) {\r\n var buffer = audioBuffer.renderedBuffer.getChannelData(0).buffer;\r\n client.SendMessage(\"processAudio\", 1, {\r\n sampleRate: 8000,\r\n channelData: buffer\r\n }, [buffer]);\r\n };\r\n\r\n downsampleBuffer = offlineContext.createBuffer(1, e.inputBuffer.length, e.inputBuffer.sampleRate);\r\n\r\n b = downsampleBuffer.getChannelData(0);\r\n e.inputBuffer.copyFromChannel(b, 0);\r\n\r\n source = offlineContext.createBufferSource();\r\n source.buffer = downsampleBuffer;\r\n source.connect(offlineContext.destination);\r\n source.start(0);\r\n\r\n offlineContext.startRendering();\r\n\r\n /* ------------------------------------------------------------------------------------------------------------*/\r\n\r\n /* ----------------- Pass audio buffer straight to worker thread where it can be manually down-sampled ------- */\r\n\r\n sampleRate = e.inputBuffer.sampleRate;\r\n channelData = new Float32Array(e.inputBuffer.length);\r\n e.inputBuffer.copyFromChannel(channelData, 0);\r\n\r\n client.SendMessage(\"processAudio\", 1, {\r\n sampleRate: sampleRate,\r\n channelData: channelData.buffer,\r\n flush: !sendingAudio\r\n }, [channelData.buffer]);\r\n\r\n if (!sendingAudio && !halting) {\r\n try {\r\n client.SendMessage(\"endAudio\", 1);\r\n halting = true;\r\n } catch (err) {\r\n endAudioFailure(err);\r\n }\r\n }\r\n /* -------------------------------------------------------------------------------------------------------------*/\r\n }\r\n\r\n microphone.connect(biquadFilter);\r\n biquadFilter.connect(scriptNode);\r\n scriptNode.connect(context.destination);\r\n }\r\n }\r\n };\r\n\r\n this.messageHandlers['audioEnded'] = function() {\r\n microphone.disconnect();\r\n biquadFilter.disconnect();\r\n scriptNode.disconnect();\r\n util.wtcpDebug('audio: audioEnded handled, disconnected microphone and script node');\r\n endAudioSuccess();\r\n };\r\n\r\n this.endAudio = function() {\r\n\r\n return new Promise(function(resolve, reject) {\r\n if (microphone) {\r\n sendingAudio = false;\r\n endAudioSuccess = resolve;\r\n endAudioFailure = reject;\r\n } else {\r\n resolve();\r\n }\r\n });\r\n };\r\n\r\n this.setVolume = function(val) {\r\n setGain(val);\r\n }\r\n\r\n this.visualize = (canvas) => {\r\n times = new Uint8Array(analyser.frequencyBinCount);\r\n visCanvas = canvas;\r\n isVisualizing = true;\r\n };\r\n\r\n var init = function() {\r\n util.setLoggingLevel(settings.loggingLevel);\r\n try {\r\n // Fix up for prefixing\r\n window.AudioContext = window.AudioContext || window.webkitAudioContext;\r\n window.OfflineAudioContext = window.OfflineAudioContext || window.webkitOfflineAudioContext;\r\n context = new AudioContext();\r\n gainNode = context.createGain();\r\n setGain(settings.initialVolume);\r\n analyser = context.createAnalyser();\r\n analyser.minDecibels = -140;\r\n analyser.maxDecibels = 0;\r\n analyser.smoothingTimeConstant = SMOOTHING;\r\n analyser.fftSize = FFT_SIZE;\r\n analyser.connect(context.destination);\r\n } catch (e) {\r\n throw \"Initialization error: \" + e.message;\r\n }\r\n\r\n try {\r\n if (navigator.mediaDevices === undefined) {\r\n util.wtcpError(\"you are not secure running browser.\");\r\n throw \"current DOM is not loaded securely. try to use https instead of http\";\r\n } \r\n if (navigator.mediaDevices.getUserMedia) {\r\n navigator.mediaDevices.getUserMedia({ audio: true })\r\n .then(function(stream) {\r\n micStream = stream;\r\n micEnabled = true;\r\n initStatus = {status: 'ready', message: 'Ready'};\r\n })\r\n .catch(function(err) {\r\n util.wtcpError(\"getUserMedia error\", err);\r\n initStatus = {status: 'error', message: err.message};\r\n });\r\n } else {\r\n navigator.getUserMedia = navigator.getUserMedia ||\r\n navigator.webkitGetUserMedia ||\r\n navigator.mozGetUserMedia ||\r\n navigator.msGetUserMedia;\r\n\r\n navigator.getUserMedia({ audio: true }, function (stream) {\r\n micStream = stream;\r\n micEnabled = true;\r\n initStatus = { status: 'ready', message: 'Ready' };\r\n }, function (err) {\r\n util.wtcpError(\"getUserMedia error: \" + err.message);\r\n initStatus = { status: 'error', message: err.message };\r\n });\r\n } \r\n } catch (e) {\r\n throw \"getUserMedia() is not supported in your browser\";\r\n }\r\n }\r\n\r\n init();\r\n };\r\n\r\n module.exports = wtcp;\r\n})({});\n}).call(this)}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n\n},{\"./wtcp.util.js\":7}],9:[function(require,module,exports){\n(function () {\n var validator = new RegExp(\"^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$\", \"i\");\n\n function gen(count) {\n var out = \"\";\n for (var i=0; i\n * Licensed under MIT License\n */\n\n(function (window, undefined) {\n\n 'use strict';\n\n //////////////\n // Constants\n /////////////\n\n\n var LIBVERSION = '0.7.28',\n EMPTY = '',\n UNKNOWN = '?',\n FUNC_TYPE = 'function',\n UNDEF_TYPE = 'undefined',\n OBJ_TYPE = 'object',\n STR_TYPE = 'string',\n MAJOR = 'major', // deprecated\n MODEL = 'model',\n NAME = 'name',\n TYPE = 'type',\n VENDOR = 'vendor',\n VERSION = 'version',\n ARCHITECTURE= 'architecture',\n CONSOLE = 'console',\n MOBILE = 'mobile',\n TABLET = 'tablet',\n SMARTTV = 'smarttv',\n WEARABLE = 'wearable',\n EMBEDDED = 'embedded',\n UA_MAX_LENGTH = 255;\n\n\n ///////////\n // Helper\n //////////\n\n\n var util = {\n extend : function (regexes, extensions) {\n var mergedRegexes = {};\n for (var i in regexes) {\n if (extensions[i] && extensions[i].length % 2 === 0) {\n mergedRegexes[i] = extensions[i].concat(regexes[i]);\n } else {\n mergedRegexes[i] = regexes[i];\n }\n }\n return mergedRegexes;\n },\n has : function (str1, str2) {\n return typeof str1 === STR_TYPE ? str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1 : false;\n },\n lowerize : function (str) {\n return str.toLowerCase();\n },\n major : function (version) {\n return typeof(version) === STR_TYPE ? version.replace(/[^\\d\\.]/g,'').split(\".\")[0] : undefined;\n },\n trim : function (str, len) {\n str = str.replace(/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g, '');\n return typeof(len) === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);\n }\n };\n\n\n ///////////////\n // Map helper\n //////////////\n\n\n var mapper = {\n\n rgx : function (ua, arrays) {\n\n var i = 0, j, k, p, q, matches, match;\n\n // loop through all regexes maps\n while (i < arrays.length && !matches) {\n\n var regex = arrays[i], // even sequence (0,2,4,..)\n props = arrays[i + 1]; // odd sequence (1,3,5,..)\n j = k = 0;\n\n // try matching uastring with regexes\n while (j < regex.length && !matches) {\n\n matches = regex[j++].exec(ua);\n\n if (!!matches) {\n for (p = 0; p < props.length; p++) {\n match = matches[++k];\n q = props[p];\n // check if given property is actually array\n if (typeof q === OBJ_TYPE && q.length > 0) {\n if (q.length == 2) {\n if (typeof q[1] == FUNC_TYPE) {\n // assign modified match\n this[q[0]] = q[1].call(this, match);\n } else {\n // assign given value, ignore regex match\n this[q[0]] = q[1];\n }\n } else if (q.length == 3) {\n // check whether function or regex\n if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {\n // call function (usually string mapper)\n this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;\n } else {\n // sanitize match using given regex\n this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;\n }\n } else if (q.length == 4) {\n this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;\n }\n } else {\n this[q] = match ? match : undefined;\n }\n }\n }\n }\n i += 2;\n }\n },\n\n str : function (str, map) {\n\n for (var i in map) {\n // check if array\n if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {\n for (var j = 0; j < map[i].length; j++) {\n if (util.has(map[i][j], str)) {\n return (i === UNKNOWN) ? undefined : i;\n }\n }\n } else if (util.has(map[i], str)) {\n return (i === UNKNOWN) ? undefined : i;\n }\n }\n return str;\n }\n };\n\n\n ///////////////\n // String map\n //////////////\n\n\n var maps = {\n\n browser : {\n // Safari < 3.0\n oldSafari : {\n version : {\n '1.0' : '/8',\n '1.2' : '/1',\n '1.3' : '/3',\n '2.0' : '/412',\n '2.0.2' : '/416',\n '2.0.3' : '/417',\n '2.0.4' : '/419',\n '?' : '/'\n }\n },\n oldEdge : {\n version : {\n '0.1' : '12.',\n '21' : '13.',\n '31' : '14.',\n '39' : '15.',\n '41' : '16.',\n '42' : '17.',\n '44' : '18.'\n }\n }\n },\n\n os : {\n windows : {\n version : {\n 'ME' : '4.90',\n 'NT 3.11' : 'NT3.51',\n 'NT 4.0' : 'NT4.0',\n '2000' : 'NT 5.0',\n 'XP' : ['NT 5.1', 'NT 5.2'],\n 'Vista' : 'NT 6.0',\n '7' : 'NT 6.1',\n '8' : 'NT 6.2',\n '8.1' : 'NT 6.3',\n '10' : ['NT 6.4', 'NT 10.0'],\n 'RT' : 'ARM'\n }\n }\n }\n };\n\n\n //////////////\n // Regex map\n /////////////\n\n\n var regexes = {\n\n browser : [[\n\n /\\b(?:crmo|crios)\\/([\\w\\.]+)/i // Chrome for Android/iOS\n ], [VERSION, [NAME, 'Chrome']], [\n /edg(?:e|ios|a)?\\/([\\w\\.]+)/i // Microsoft Edge\n ], [VERSION, [NAME, 'Edge']], [\n // breaking change (reserved for next major release):\n ///edge\\/([\\w\\.]+)/i // Old Edge (Trident)\n //], [[VERSION, mapper.str, maps.browser.oldEdge.version], [NAME, 'Edge']], [\n\n // Presto based\n /(opera\\smini)\\/([\\w\\.-]+)/i, // Opera Mini\n /(opera\\s[mobiletab]{3,6})\\b.+version\\/([\\w\\.-]+)/i, // Opera Mobi/Tablet\n /(opera)(?:.+version\\/|[\\/\\s]+)([\\w\\.]+)/i, // Opera\n ], [NAME, VERSION], [\n /opios[\\/\\s]+([\\w\\.]+)/i // Opera mini on iphone >= 8.0\n ], [VERSION, [NAME, 'Opera Mini']], [\n /\\sopr\\/([\\w\\.]+)/i // Opera Webkit\n ], [VERSION, [NAME, 'Opera']], [\n\n // Mixed\n /(kindle)\\/([\\w\\.]+)/i, // Kindle\n /(lunascape|maxthon|netfront|jasmine|blazer)[\\/\\s]?([\\w\\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer\n // Trident based\n /(avant\\s|iemobile|slim)(?:browser)?[\\/\\s]?([\\w\\.]*)/i, // Avant/IEMobile/SlimBrowser\n /(ba?idubrowser)[\\/\\s]?([\\w\\.]+)/i, // Baidu Browser\n /(?:ms|\\()(ie)\\s([\\w\\.]+)/i, // Internet Explorer\n\n // Webkit/KHTML based\n /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon)\\/([\\w\\.-]+)/i,\n // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon\n /(rekonq|puffin|brave|whale|qqbrowserlite|qq)\\/([\\w\\.]+)/i, // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ, aka ShouQ\n /(weibo)__([\\d\\.]+)/i // Weibo\n ], [NAME, VERSION], [\n /(?:[\\s\\/]uc?\\s?browser|(?:juc.+)ucweb)[\\/\\s]?([\\w\\.]+)/i // UCBrowser\n ], [VERSION, [NAME, 'UCBrowser']], [\n /(?:windowswechat)?\\sqbcore\\/([\\w\\.]+)\\b.*(?:windowswechat)?/i // WeChat Desktop for Windows Built-in Browser\n ], [VERSION, [NAME, 'WeChat(Win) Desktop']], [\n /micromessenger\\/([\\w\\.]+)/i // WeChat\n ], [VERSION, [NAME, 'WeChat']], [\n /konqueror\\/([\\w\\.]+)/i // Konqueror\n ], [VERSION, [NAME, 'Konqueror']], [\n /trident.+rv[:\\s]([\\w\\.]{1,9})\\b.+like\\sgecko/i // IE11\n ], [VERSION, [NAME, 'IE']], [\n /yabrowser\\/([\\w\\.]+)/i // Yandex\n ], [VERSION, [NAME, 'Yandex']], [\n /(avast|avg)\\/([\\w\\.]+)/i // Avast/AVG Secure Browser\n ], [[NAME, /(.+)/, '$1 Secure Browser'], VERSION], [\n /focus\\/([\\w\\.]+)/i // Firefox Focus\n ], [VERSION, [NAME, 'Firefox Focus']], [\n /opt\\/([\\w\\.]+)/i // Opera Touch\n ], [VERSION, [NAME, 'Opera Touch']], [\n /coc_coc_browser\\/([\\w\\.]+)/i // Coc Coc Browser\n ], [VERSION, [NAME, 'Coc Coc']], [\n /dolfin\\/([\\w\\.]+)/i // Dolphin\n ], [VERSION, [NAME, 'Dolphin']], [\n /coast\\/([\\w\\.]+)/i // Opera Coast\n ], [VERSION, [NAME, 'Opera Coast']],\n [/xiaomi\\/miuibrowser\\/([\\w\\.]+)/i // MIUI Browser\n ], [VERSION, [NAME, 'MIUI Browser']], [\n /fxios\\/([\\w\\.-]+)/i // Firefox for iOS\n ], [VERSION, [NAME, 'Firefox']], [\n /(qihu|qhbrowser|qihoobrowser|360browser)/i // 360\n ], [[NAME, '360 Browser']], [\n /(oculus|samsung|sailfish)browser\\/([\\w\\.]+)/i\n ], [[NAME, /(.+)/, '$1 Browser'], VERSION], [ // Oculus/Samsung/Sailfish Browser\n /(comodo_dragon)\\/([\\w\\.]+)/i // Comodo Dragon\n ], [[NAME, /_/g, ' '], VERSION], [\n /\\s(electron)\\/([\\w\\.]+)\\ssafari/i, // Electron-based App\n /(tesla)(?:\\sqtcarbrowser|\\/(20[12]\\d\\.[\\w\\.-]+))/i, // Tesla\n /m?(qqbrowser|baiduboxapp|2345Explorer)[\\/\\s]?([\\w\\.]+)/i // QQBrowser/Baidu App/2345 Browser\n ], [NAME, VERSION], [\n /(MetaSr)[\\/\\s]?([\\w\\.]+)/i, // SouGouBrowser\n /(LBBROWSER)/i // LieBao Browser\n ], [NAME], [\n\n // WebView\n /;fbav\\/([\\w\\.]+);/i // Facebook App for iOS & Android with version\n ], [VERSION, [NAME, 'Facebook']], [\n /FBAN\\/FBIOS|FB_IAB\\/FB4A/i // Facebook App for iOS & Android without version\n ], [[NAME, 'Facebook']], [\n /safari\\s(line)\\/([\\w\\.]+)/i, // Line App for iOS\n /\\b(line)\\/([\\w\\.]+)\\/iab/i, // Line App for Android\n /(chromium|instagram)[\\/\\s]([\\w\\.-]+)/i // Chromium/Instagram\n ], [NAME, VERSION], [\n /\\bgsa\\/([\\w\\.]+)\\s.*safari\\//i // Google Search Appliance on iOS\n ], [VERSION, [NAME, 'GSA']], [\n\n /headlesschrome(?:\\/([\\w\\.]+)|\\s)/i // Chrome Headless\n ], [VERSION, [NAME, 'Chrome Headless']], [\n\n /\\swv\\).+(chrome)\\/([\\w\\.]+)/i // Chrome WebView\n ], [[NAME, 'Chrome WebView'], VERSION], [\n\n /droid.+\\sversion\\/([\\w\\.]+)\\b.+(?:mobile\\ssafari|safari)/i // Android Browser\n ], [VERSION, [NAME, 'Android Browser']], [\n\n /(chrome|omniweb|arora|[tizenoka]{5}\\s?browser)\\/v?([\\w\\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia\n ], [NAME, VERSION], [\n\n /version\\/([\\w\\.]+)\\s.*mobile\\/\\w+\\s(safari)/i // Mobile Safari\n ], [VERSION, [NAME, 'Mobile Safari']], [\n /version\\/([\\w\\.]+)\\s.*(mobile\\s?safari|safari)/i // Safari & Safari Mobile\n ], [VERSION, NAME], [\n /webkit.+?(mobile\\s?safari|safari)(\\/[\\w\\.]+)/i // Safari < 3.0\n ], [NAME, [VERSION, mapper.str, maps.browser.oldSafari.version]], [\n\n /(webkit|khtml)\\/([\\w\\.]+)/i\n ], [NAME, VERSION], [\n\n // Gecko based\n /(navigator|netscape)\\/([\\w\\.-]+)/i // Netscape\n ], [[NAME, 'Netscape'], VERSION], [\n /ile\\svr;\\srv:([\\w\\.]+)\\).+firefox/i // Firefox Reality\n ], [VERSION, [NAME, 'Firefox Reality']], [\n /ekiohf.+(flow)\\/([\\w\\.]+)/i, // Flow\n /(swiftfox)/i, // Swiftfox\n /(icedragon|iceweasel|camino|chimera|fennec|maemo\\sbrowser|minimo|conkeror)[\\/\\s]?([\\w\\.\\+]+)/i,\n // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror\n /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\\/([\\w\\.-]+)$/i,\n // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix\n /(firefox)\\/([\\w\\.]+)\\s[\\w\\s\\-]+\\/[\\w\\.]+$/i, // Other Firefox-based\n /(mozilla)\\/([\\w\\.]+)\\s.+rv\\:.+gecko\\/\\d+/i, // Mozilla\n\n // Other\n /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir)[\\/\\s]?([\\w\\.]+)/i,\n // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir\n /(links)\\s\\(([\\w\\.]+)/i, // Links\n /(gobrowser)\\/?([\\w\\.]*)/i, // GoBrowser\n /(ice\\s?browser)\\/v?([\\w\\._]+)/i, // ICE Browser\n /(mosaic)[\\/\\s]([\\w\\.]+)/i // Mosaic\n ], [NAME, VERSION]\n ],\n\n cpu : [[\n\n /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\\)]/i // AMD64 (x64)\n ], [[ARCHITECTURE, 'amd64']], [\n\n /(ia32(?=;))/i // IA32 (quicktime)\n ], [[ARCHITECTURE, util.lowerize]], [\n\n /((?:i[346]|x)86)[;\\)]/i // IA32 (x86)\n ], [[ARCHITECTURE, 'ia32']], [\n\n /\\b(aarch64|armv?8e?l?)\\b/i // ARM64\n ], [[ARCHITECTURE, 'arm64']], [\n\n /\\b(arm(?:v[67])?ht?n?[fl]p?)\\b/i // ARMHF\n ], [[ARCHITECTURE, 'armhf']], [\n\n // PocketPC mistakenly identified as PowerPC\n /windows\\s(ce|mobile);\\sppc;/i\n ], [[ARCHITECTURE, 'arm']], [\n\n /((?:ppc|powerpc)(?:64)?)(?:\\smac|;|\\))/i // PowerPC\n ], [[ARCHITECTURE, /ower/, '', util.lowerize]], [\n\n /(sun4\\w)[;\\)]/i // SPARC\n ], [[ARCHITECTURE, 'sparc']], [\n\n /((?:avr32|ia64(?=;))|68k(?=\\))|\\barm(?:64|(?=v(?:[1-7]|[5-7]1)l?|;|eabi))|(?=atmel\\s)avr|(?:irix|mips|sparc)(?:64)?\\b|pa-risc)/i\n // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC\n ], [[ARCHITECTURE, util.lowerize]]\n ],\n\n device : [[\n\n //////////////////////////\n // MOBILES & TABLETS\n // Ordered by popularity\n /////////////////////////\n\n // Samsung\n /\\b(sch-i[89]0\\d|shw-m380s|sm-[pt]\\w{2,4}|gt-[pn]\\d{2,4}|sgh-t8[56]9|nexus\\s10)/i\n ], [MODEL, [VENDOR, 'Samsung'], [TYPE, TABLET]], [\n /\\b((?:s[cgp]h|gt|sm)-\\w+|galaxy\\snexus)/i,\n /\\ssamsung[\\s-]([\\w-]+)/i,\n /sec-(sgh\\w+)/i\n ], [MODEL, [VENDOR, 'Samsung'], [TYPE, MOBILE]], [\n\n // Apple\n /\\((ip(?:hone|od)[\\s\\w]*);/i // iPod/iPhone\n ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [\n /\\((ipad);[\\w\\s\\),;-]+apple/i, // iPad\n /applecoremedia\\/[\\w\\.]+\\s\\((ipad)/i,\n /\\b(ipad)\\d\\d?,\\d\\d?[;\\]].+ios/i\n ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [\n\n // Huawei\n /\\b((?:agr|ags[23]|bah2?|sht?)-a?[lw]\\d{2})/i,\n ], [MODEL, [VENDOR, 'Huawei'], [TYPE, TABLET]], [\n /d\\/huawei([\\w\\s-]+)[;\\)]/i,\n /\\b(nexus\\s6p|vog-[at]?l\\d\\d|ane-[at]?l[x\\d]\\d|eml-a?l\\d\\da?|lya-[at]?l\\d[\\dc]|clt-a?l\\d\\di?|ele-l\\d\\d)/i,\n /\\b(\\w{2,4}-[atu][ln][01259][019])[;\\)\\s]/i\n ], [MODEL, [VENDOR, 'Huawei'], [TYPE, MOBILE]], [\n\n // Xiaomi\n /\\b(poco[\\s\\w]+)(?:\\sbuild|\\))/i, // Xiaomi POCO\n /\\b;\\s(\\w+)\\sbuild\\/hm\\1/i, // Xiaomi Hongmi 'numeric' models\n /\\b(hm[\\s\\-_]?note?[\\s_]?(?:\\d\\w)?)\\sbuild/i, // Xiaomi Hongmi\n /\\b(redmi[\\s\\-_]?(?:note|k)?[\\w\\s_]+)(?:\\sbuild|\\))/i, // Xiaomi Redmi\n /\\b(mi[\\s\\-_]?(?:a\\d|one|one[\\s_]plus|note lte)?[\\s_]?(?:\\d?\\w?)[\\s_]?(?:plus)?)\\sbuild/i // Xiaomi Mi\n ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [\n /\\b(mi[\\s\\-_]?(?:pad)(?:[\\w\\s_]+))(?:\\sbuild|\\))/i // Mi Pad tablets\n ],[[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [\n\n // OPPO\n /;\\s(\\w+)\\sbuild.+\\soppo/i,\n /\\s(cph[12]\\d{3}|p(?:af|c[al]|d\\w|e[ar])[mt]\\d0|x9007)\\b/i\n ], [MODEL, [VENDOR, 'OPPO'], [TYPE, MOBILE]], [\n\n // Vivo\n /\\svivo\\s(\\w+)(?:\\sbuild|\\))/i,\n /\\s(v[12]\\d{3}\\w?[at])(?:\\sbuild|;)/i\n ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [\n\n // Realme\n /\\s(rmx[12]\\d{3})(?:\\sbuild|;)/i\n ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [\n\n // Motorola\n /\\s(milestone|droid(?:[2-4x]|\\s(?:bionic|x2|pro|razr))?:?(\\s4g)?)\\b[\\w\\s]+build\\//i,\n /\\smot(?:orola)?[\\s-](\\w*)/i,\n /((?:moto[\\s\\w\\(\\)]+|xt\\d{3,4}|nexus\\s6)(?=\\sbuild|\\)))/i\n ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [\n /\\s(mz60\\d|xoom[\\s2]{0,2})\\sbuild\\//i\n ], [MODEL, [VENDOR, 'Motorola'], [TYPE, TABLET]], [\n\n // LG\n /((?=lg)?[vl]k\\-?\\d{3})\\sbuild|\\s3\\.[\\s\\w;-]{10}lg?-([06cv9]{3,4})/i\n ], [MODEL, [VENDOR, 'LG'], [TYPE, TABLET]], [\n /(lm-?f100[nv]?|nexus\\s[45])/i,\n /lg[e;\\s\\/-]+((?!browser|netcast)\\w+)/i,\n /\\blg(\\-?[\\d\\w]+)\\sbuild/i\n ], [MODEL, [VENDOR, 'LG'], [TYPE, MOBILE]], [\n\n // Lenovo\n /(ideatab[\\w\\-\\s]+)/i,\n /lenovo\\s?(s(?:5000|6000)(?:[\\w-]+)|tab(?:[\\s\\w]+)|yt[\\d\\w-]{6}|tb[\\d\\w-]{6})/i // Lenovo tablets\n ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [\n\n // Nokia\n /(?:maemo|nokia).*(n900|lumia\\s\\d+)/i,\n /nokia[\\s_-]?([\\w\\.-]*)/i\n ], [[MODEL, /_/g, ' '], [VENDOR, 'Nokia'], [TYPE, MOBILE]], [\n\n // Google\n /droid.+;\\s(pixel\\sc)[\\s)]/i // Google Pixel C\n ], [MODEL, [VENDOR, 'Google'], [TYPE, TABLET]], [\n /droid.+;\\s(pixel[\\s\\daxl]{0,6})(?:\\sbuild|\\))/i // Google Pixel\n ], [MODEL, [VENDOR, 'Google'], [TYPE, MOBILE]], [\n\n // Sony\n /droid.+\\s([c-g]\\d{4}|so[-l]\\w+|xq-a\\w[4-7][12])(?=\\sbuild\\/|\\).+chrome\\/(?![1-6]{0,1}\\d\\.))/i\n ], [MODEL, [VENDOR, 'Sony'], [TYPE, MOBILE]], [\n /sony\\stablet\\s[ps]\\sbuild\\//i,\n /(?:sony)?sgp\\w+(?:\\sbuild\\/|\\))/i\n ], [[MODEL, 'Xperia Tablet'], [VENDOR, 'Sony'], [TYPE, TABLET]], [\n\n // OnePlus\n /\\s(kb2005|in20[12]5|be20[12][59])\\b/i,\n /\\ba000(1)\\sbuild/i, // OnePlus\n /\\boneplus\\s(a\\d{4})[\\s)]/i\n ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [\n\n // Amazon\n /(alexa)webm/i,\n /(kf[a-z]{2}wi)(\\sbuild\\/|\\))/i, // Kindle Fire without Silk\n /(kf[a-z]+)(\\sbuild\\/|\\)).+silk\\//i // Kindle Fire HD\n ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [\n /(sd|kf)[0349hijorstuw]+(\\sbuild\\/|\\)).+silk\\//i // Fire Phone\n ], [[MODEL, 'Fire Phone'], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [\n\n // BlackBerry\n /\\((playbook);[\\w\\s\\),;-]+(rim)/i // BlackBerry PlayBook\n ], [MODEL, VENDOR, [TYPE, TABLET]], [\n /((?:bb[a-f]|st[hv])100-\\d)/i,\n /\\(bb10;\\s(\\w+)/i // BlackBerry 10\n ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [\n\n // Asus\n /(?:\\b|asus_)(transfo[prime\\s]{4,10}\\s\\w+|eeepc|slider\\s\\w+|nexus\\s7|padfone|p00[cj])/i\n ], [MODEL, [VENDOR, 'ASUS'], [TYPE, TABLET]], [\n /\\s(z[es]6[027][01][km][ls]|zenfone\\s\\d\\w?)\\b/i\n ], [MODEL, [VENDOR, 'ASUS'], [TYPE, MOBILE]], [\n\n // HTC\n /(nexus\\s9)/i // HTC Nexus 9\n ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [\n /(htc)[;_\\s-]{1,2}([\\w\\s]+(?=\\)|\\sbuild)|\\w+)/i, // HTC\n\n // ZTE\n /(zte)-(\\w*)/i,\n /(alcatel|geeksphone|nexian|panasonic|(?=;\\s)sony)[_\\s-]?([\\w-]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony\n ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [\n\n // Acer\n /droid[x\\d\\.\\s;]+\\s([ab][1-7]\\-?[0178a]\\d\\d?)/i\n ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [\n\n // Meizu\n /droid.+;\\s(m[1-5]\\snote)\\sbuild/i,\n /\\bmz-([\\w-]{2,})/i\n ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [\n\n // MIXED\n /(blackberry|benq|palm(?=\\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\\s_-]?([\\w-]*)/i,\n // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron\n /(hp)\\s([\\w\\s]+\\w)/i, // HP iPAQ\n /(asus)-?(\\w+)/i, // Asus\n /(microsoft);\\s(lumia[\\s\\w]+)/i, // Microsoft Lumia\n /(lenovo)[_\\s-]?([\\w-]+)/i, // Lenovo\n /linux;.+(jolla);/i, // Jolla\n /droid.+;\\s(oppo)\\s?([\\w\\s]+)\\sbuild/i // OPPO\n ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n\n /(archos)\\s(gamepad2?)/i, // Archos\n /(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad\n /(kindle)\\/([\\w\\.]+)/i, // Kindle\n /\\s(nook)[\\w\\s]+build\\/(\\w+)/i, // Nook\n /(dell)\\s(strea[kpr\\s\\d]*[\\dko])/i, // Dell Streak\n /[;\\/]\\s?(le[\\s\\-]+pan)[\\s\\-]+(\\w{1,9})\\sbuild/i, // Le Pan Tablets\n /[;\\/]\\s?(trinity)[\\-\\s]*(t\\d{3})\\sbuild/i, // Trinity Tablets\n /\\b(gigaset)[\\s\\-]+(q\\w{1,9})\\sbuild/i, // Gigaset Tablets\n /\\b(vodafone)\\s([\\w\\s]+)(?:\\)|\\sbuild)/i // Vodafone\n ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n /\\s(surface\\sduo)\\s/i // Surface Duo\n ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, TABLET]], [\n /droid\\s[\\d\\.]+;\\s(fp\\du?)\\sbuild/i\n ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [\n /\\s(u304aa)\\sbuild/i // AT&T\n ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [\n /sie-(\\w*)/i // Siemens\n ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [\n /[;\\/]\\s?(rct\\w+)\\sbuild/i // RCA Tablets\n ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [\n /[;\\/\\s](venue[\\d\\s]{2,7})\\sbuild/i // Dell Venue Tablets\n ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [\n /[;\\/]\\s?(q(?:mv|ta)\\w+)\\sbuild/i // Verizon Tablet\n ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [\n /[;\\/]\\s(?:barnes[&\\s]+noble\\s|bn[rt])([\\w\\s\\+]*)\\sbuild/i // Barnes & Noble Tablet\n ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [\n /[;\\/]\\s(tm\\d{3}\\w+)\\sbuild/i\n ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [\n /;\\s(k88)\\sbuild/i // ZTE K Series Tablet\n ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [\n /;\\s(nx\\d{3}j)\\sbuild/i // ZTE Nubia\n ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [\n /[;\\/]\\s?(gen\\d{3})\\sbuild.*49h/i // Swiss GEN Mobile\n ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [\n /[;\\/]\\s?(zur\\d{3})\\sbuild/i // Swiss ZUR Tablet\n ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [\n /[;\\/]\\s?((zeki)?tb.*\\b)\\sbuild/i // Zeki Tablets\n ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [\n /[;\\/]\\s([yr]\\d{2})\\sbuild/i,\n /[;\\/]\\s(dragon[\\-\\s]+touch\\s|dt)(\\w{5})\\sbuild/i // Dragon Touch Tablet\n ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [\n /[;\\/]\\s?(ns-?\\w{0,9})\\sbuild/i // Insignia Tablets\n ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [\n /[;\\/]\\s?((nxa|Next)-?\\w{0,9})\\sbuild/i // NextBook Tablets\n ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [\n /[;\\/]\\s?(xtreme\\_)?(v(1[045]|2[015]|[3469]0|7[05]))\\sbuild/i\n ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [ // Voice Xtreme Phones\n /[;\\/]\\s?(lvtel\\-)?(v1[12])\\sbuild/i // LvTel Phones\n ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [\n /;\\s(ph-1)\\s/i\n ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [ // Essential PH-1\n /[;\\/]\\s?(v(100md|700na|7011|917g).*\\b)\\sbuild/i // Envizen Tablets\n ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [\n /[;\\/]\\s?(trio[\\s\\w\\-\\.]+)\\sbuild/i // MachSpeed Tablets\n ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [\n /[;\\/]\\s?tu_(1491)\\sbuild/i // Rotor Tablets\n ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [\n /(shield[\\w\\s]+)\\sbuild/i // Nvidia Shield Tablets\n ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, TABLET]], [\n /(sprint)\\s(\\w+)/i // Sprint Phones\n ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n /(kin\\.[onetw]{3})/i // Microsoft Kin\n ], [[MODEL, /\\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [\n /droid\\s[\\d\\.]+;\\s(cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\\)/i // Zebra\n ], [MODEL, [VENDOR, 'Zebra'], [TYPE, TABLET]], [\n /droid\\s[\\d\\.]+;\\s(ec30|ps20|tc[2-8]\\d[kx])\\)/i\n ], [MODEL, [VENDOR, 'Zebra'], [TYPE, MOBILE]], [\n\n ///////////////////\n // CONSOLES\n ///////////////////\n\n /\\s(ouya)\\s/i, // Ouya\n /(nintendo)\\s([wids3utch]+)/i // Nintendo\n ], [VENDOR, MODEL, [TYPE, CONSOLE]], [\n /droid.+;\\s(shield)\\sbuild/i // Nvidia\n ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [\n /(playstation\\s[345portablevi]+)/i // Playstation\n ], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [\n /[\\s\\(;](xbox(?:\\sone)?(?!;\\sxbox))[\\s\\);]/i // Microsoft Xbox\n ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, CONSOLE]], [\n\n ///////////////////\n // SMARTTVS\n ///////////////////\n\n /smart-tv.+(samsung)/i // Samsung\n ], [VENDOR, [TYPE, SMARTTV]], [\n /hbbtv.+maple;(\\d+)/i\n ], [[MODEL, /^/, 'SmartTV'], [VENDOR, 'Samsung'], [TYPE, SMARTTV]], [\n /(?:linux;\\snetcast.+smarttv|lg\\snetcast\\.tv-201\\d)/i, // LG SmartTV\n ], [[VENDOR, 'LG'], [TYPE, SMARTTV]], [\n /(apple)\\s?tv/i // Apple TV\n ], [VENDOR, [MODEL, 'Apple TV'], [TYPE, SMARTTV]], [\n /crkey/i // Google Chromecast\n ], [[MODEL, 'Chromecast'], [VENDOR, 'Google'], [TYPE, SMARTTV]], [\n /droid.+aft([\\w])(\\sbuild\\/|\\))/i // Fire TV\n ], [MODEL, [VENDOR, 'Amazon'], [TYPE, SMARTTV]], [\n /\\(dtv[\\);].+(aquos)/i // Sharp\n ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [\n /hbbtv\\/\\d+\\.\\d+\\.\\d+\\s+\\([\\w\\s]*;\\s*(\\w[^;]*);([^;]*)/i // HbbTV devices\n ], [[VENDOR, util.trim], [MODEL, util.trim], [TYPE, SMARTTV]], [\n /[\\s\\/\\(](android\\s|smart[-\\s]?|opera\\s)tv[;\\)\\s]/i // SmartTV from Unidentified Vendors\n ], [[TYPE, SMARTTV]], [\n\n ///////////////////\n // WEARABLES\n ///////////////////\n\n /((pebble))app\\/[\\d\\.]+\\s/i // Pebble\n ], [VENDOR, MODEL, [TYPE, WEARABLE]], [\n /droid.+;\\s(glass)\\s\\d/i // Google Glass\n ], [MODEL, [VENDOR, 'Google'], [TYPE, WEARABLE]], [\n /droid\\s[\\d\\.]+;\\s(wt63?0{2,3})\\)/i\n ], [MODEL, [VENDOR, 'Zebra'], [TYPE, WEARABLE]], [\n\n ///////////////////\n // EMBEDDED\n ///////////////////\n\n /(tesla)(?:\\sqtcarbrowser|\\/20[12]\\d\\.[\\w\\.-]+)/i // Tesla\n ], [VENDOR, [TYPE, EMBEDDED]], [\n\n ////////////////////\n // MIXED (GENERIC)\n ///////////////////\n\n /droid .+?; ([^;]+?)(?: build|\\) applewebkit).+? mobile safari/i // Android Phones from Unidentified Vendors\n ], [MODEL, [TYPE, MOBILE]], [\n /droid .+?;\\s([^;]+?)(?: build|\\) applewebkit).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors\n ], [MODEL, [TYPE, TABLET]], [\n /\\s(tablet|tab)[;\\/]/i, // Unidentifiable Tablet\n /\\s(mobile)(?:[;\\/]|\\ssafari)/i // Unidentifiable Mobile\n ], [[TYPE, util.lowerize]], [\n /(android[\\w\\.\\s\\-]{0,9});.+build/i // Generic Android Device\n ], [MODEL, [VENDOR, 'Generic']], [\n /(phone)/i\n ], [[TYPE, MOBILE]]\n ],\n\n engine : [[\n\n /windows.+\\sedge\\/([\\w\\.]+)/i // EdgeHTML\n ], [VERSION, [NAME, 'EdgeHTML']], [\n\n /webkit\\/537\\.36.+chrome\\/(?!27)([\\w\\.]+)/i // Blink\n ], [VERSION, [NAME, 'Blink']], [\n\n /(presto)\\/([\\w\\.]+)/i, // Presto\n /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\\/([\\w\\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna\n /ekioh(flow)\\/([\\w\\.]+)/i, // Flow\n /(khtml|tasman|links)[\\/\\s]\\(?([\\w\\.]+)/i, // KHTML/Tasman/Links\n /(icab)[\\/\\s]([23]\\.[\\d\\.]+)/i // iCab\n ], [NAME, VERSION], [\n\n /rv\\:([\\w\\.]{1,9})\\b.+(gecko)/i // Gecko\n ], [VERSION, NAME]\n ],\n\n os : [[\n\n // Windows\n /microsoft\\s(windows)\\s(vista|xp)/i // Windows (iTunes)\n ], [NAME, VERSION], [\n /(windows)\\snt\\s6\\.2;\\s(arm)/i, // Windows RT\n /(windows\\sphone(?:\\sos)*)[\\s\\/]?([\\d\\.\\s\\w]*)/i, // Windows Phone\n /(windows\\smobile|windows)[\\s\\/]?([ntce\\d\\.\\s]+\\w)(?!.+xbox)/i\n ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [\n /(win(?=3|9|n)|win\\s9x\\s)([nt\\d\\.]+)/i\n ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [\n\n // iOS/macOS\n /ip[honead]{2,4}\\b(?:.*os\\s([\\w]+)\\slike\\smac|;\\sopera)/i, // iOS\n /cfnetwork\\/.+darwin/i\n ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [\n /(mac\\sos\\sx)\\s?([\\w\\s\\.]*)/i,\n /(macintosh|mac(?=_powerpc)\\s)(?!.+haiku)/i // Mac OS\n ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [\n\n // Mobile OSes // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki/Sailfish OS\n /(android|webos|palm\\sos|qnx|bada|rim\\stablet\\sos|meego|sailfish|contiki)[\\/\\s-]?([\\w\\.]*)/i,\n /(blackberry)\\w*\\/([\\w\\.]*)/i, // Blackberry\n /(tizen|kaios)[\\/\\s]([\\w\\.]+)/i, // Tizen/KaiOS\n /\\((series40);/i // Series 40\n ], [NAME, VERSION], [\n /\\(bb(10);/i // BlackBerry 10\n ], [VERSION, [NAME, 'BlackBerry']], [\n /(?:symbian\\s?os|symbos|s60(?=;)|series60)[\\/\\s-]?([\\w\\.]*)/i // Symbian\n ], [VERSION, [NAME, 'Symbian']], [\n /mozilla.+\\(mobile;.+gecko.+firefox/i // Firefox OS\n ], [[NAME, 'Firefox OS']], [\n /web0s;.+rt(tv)/i,\n /\\b(?:hp)?wos(?:browser)?\\/([\\w\\.]+)/i // WebOS\n ], [VERSION, [NAME, 'webOS']], [\n\n // Google Chromecast\n /crkey\\/([\\d\\.]+)/i // Google Chromecast\n ], [VERSION, [NAME, 'Chromecast']], [\n /(cros)\\s[\\w]+\\s([\\w\\.]+\\w)/i // Chromium OS\n ], [[NAME, 'Chromium OS'], VERSION],[\n\n // Console\n /(nintendo|playstation)\\s([wids345portablevuch]+)/i, // Nintendo/Playstation\n /(xbox);\\s+xbox\\s([^\\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S)\n\n // GNU/Linux based\n /(mint)[\\/\\s\\(\\)]?(\\w*)/i, // Mint\n /(mageia|vectorlinux)[;\\s]/i, // Mageia/VectorLinux\n /(joli|[kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?=\\slinux)|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus|raspbian)(?:\\sgnu\\/linux)?(?:\\slinux)?[\\/\\s-]?(?!chrom|package)([\\w\\.-]*)/i,\n // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware\n // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus\n /(hurd|linux)\\s?([\\w\\.]*)/i, // Hurd/Linux\n /(gnu)\\s?([\\w\\.]*)/i, // GNU\n\n // BSD based\n /\\s([frentopc-]{0,4}bsd|dragonfly)\\s?(?!amd|[ix346]{1,2}86)([\\w\\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly\n /(haiku)\\s(\\w+)/i // Haiku\n ], [NAME, VERSION], [\n\n // Other\n /(sunos)\\s?([\\w\\.\\d]*)/i // Solaris\n ], [[NAME, 'Solaris'], VERSION], [\n /((?:open)?solaris)[\\/\\s-]?([\\w\\.]*)/i, // Solaris\n /(aix)\\s((\\d)(?=\\.|\\)|\\s)[\\w\\.])*/i, // AIX\n /(plan\\s9|minix|beos|os\\/2|amigaos|morphos|risc\\sos|openvms|fuchsia)/i, // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS/Fuchsia\n /(unix)\\s?([\\w\\.]*)/i // UNIX\n ], [NAME, VERSION]\n ]\n };\n\n\n /////////////////\n // Constructor\n ////////////////\n var UAParser = function (ua, extensions) {\n\n if (typeof ua === 'object') {\n extensions = ua;\n ua = undefined;\n }\n\n if (!(this instanceof UAParser)) {\n return new UAParser(ua, extensions).getResult();\n }\n\n var _ua = ua || ((typeof window !== 'undefined' && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY);\n var _rgxmap = extensions ? util.extend(regexes, extensions) : regexes;\n\n this.getBrowser = function () {\n var _browser = { name: undefined, version: undefined };\n mapper.rgx.call(_browser, _ua, _rgxmap.browser);\n _browser.major = util.major(_browser.version); // deprecated\n return _browser;\n };\n this.getCPU = function () {\n var _cpu = { architecture: undefined };\n mapper.rgx.call(_cpu, _ua, _rgxmap.cpu);\n return _cpu;\n };\n this.getDevice = function () {\n var _device = { vendor: undefined, model: undefined, type: undefined };\n mapper.rgx.call(_device, _ua, _rgxmap.device);\n return _device;\n };\n this.getEngine = function () {\n var _engine = { name: undefined, version: undefined };\n mapper.rgx.call(_engine, _ua, _rgxmap.engine);\n return _engine;\n };\n this.getOS = function () {\n var _os = { name: undefined, version: undefined };\n mapper.rgx.call(_os, _ua, _rgxmap.os);\n return _os;\n };\n this.getResult = function () {\n return {\n ua : this.getUA(),\n browser : this.getBrowser(),\n engine : this.getEngine(),\n os : this.getOS(),\n device : this.getDevice(),\n cpu : this.getCPU()\n };\n };\n this.getUA = function () {\n return _ua;\n };\n this.setUA = function (ua) {\n _ua = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? util.trim(ua, UA_MAX_LENGTH) : ua;\n return this;\n };\n this.setUA(_ua);\n return this;\n };\n\n UAParser.VERSION = LIBVERSION;\n UAParser.BROWSER = {\n NAME : NAME,\n MAJOR : MAJOR, // deprecated\n VERSION : VERSION\n };\n UAParser.CPU = {\n ARCHITECTURE : ARCHITECTURE\n };\n UAParser.DEVICE = {\n MODEL : MODEL,\n VENDOR : VENDOR,\n TYPE : TYPE,\n CONSOLE : CONSOLE,\n MOBILE : MOBILE,\n SMARTTV : SMARTTV,\n TABLET : TABLET,\n WEARABLE: WEARABLE,\n EMBEDDED: EMBEDDED\n };\n UAParser.ENGINE = {\n NAME : NAME,\n VERSION : VERSION\n };\n UAParser.OS = {\n NAME : NAME,\n VERSION : VERSION\n };\n\n ///////////\n // Export\n //////////\n\n\n // check js environment\n if (typeof(exports) !== UNDEF_TYPE) {\n // nodejs env\n if (typeof module !== UNDEF_TYPE && module.exports) {\n exports = module.exports = UAParser;\n }\n exports.UAParser = UAParser;\n } else {\n // requirejs env (optional)\n if (typeof(define) === 'function' && define.amd) {\n define(function () {\n return UAParser;\n });\n } else if (typeof window !== 'undefined') {\n // browser env\n window.UAParser = UAParser;\n }\n }\n\n // jQuery/Zepto specific (optional)\n // Note:\n // In AMD env the global scope should be kept clean, but jQuery is an exception.\n // jQuery always exports to global scope, unless jQuery.noConflict(true) is used,\n // and we should catch that.\n var $ = typeof window !== 'undefined' && (window.jQuery || window.Zepto);\n if ($ && !$.ua) {\n var parser = new UAParser();\n $.ua = parser.getResult();\n $.ua.get = function () {\n return parser.getUA();\n };\n $.ua.set = function (uastring) {\n parser.setUA(uastring);\n var result = parser.getResult();\n for (var prop in result) {\n $.ua[prop] = result[prop];\n }\n };\n }\n\n})(typeof window === 'object' ? window : this);\n\n},{}]},{},[1,7,6,8,5])\n\n","(function(wtcpJs) {\r\n \"use strict\";\r\n class ErrorResponse {\r\n constructor() {\r\n this.errorCode = 0;\r\n this.errorMessage = \"\";\r\n }\r\n }\r\n\r\n wtcpJs.ErrorResponse = ErrorResponse;\r\n})(WtcpJs || (WtcpJs = {}));","(function (wtcpJs) {\r\n \"use strict\";\r\n class AnchorInfo {\r\n\r\n constructor() {\r\n this.value = 0;\r\n this.type = 0;\r\n this.before = 0;\r\n this.after = 0;\r\n }\r\n }\r\n\r\n wtcpJs.AnchorInfo = AnchorInfo;\r\n})(WtcpJs || (WtcpJs = {}));","(function(wtcpJs) {\r\n \"use strict\";\r\n let guid = require('guid');\r\n class PrivateTextMessageRequest {\r\n constructor(obj) {\r\n this.conversationId = \"\";\r\n this.label = \"\";\r\n this.participants = [];\r\n this.metaData = [];\r\n this.mimeType = 'text/plain; charset=utf8';\r\n this.data = ''; \r\n this.destination = {\r\n userName: '', \r\n displayName: '', \r\n callAlias: '' \r\n };\r\n\r\n if(!obj || !obj.conversationId)\r\n {\r\n this.conversationId = guid.create().value;\r\n } else {\r\n this.conversationId = obj.conversationId;\r\n }\r\n }\r\n }\r\n\r\n wtcpJs.PrivateTextMessageRequest = PrivateTextMessageRequest;\r\n})(WtcpJs || (WtcpJs = {}));","/// \r\n/// \r\n/// \r\n\r\nconst wtcpUtil = require('./wtcp.util.js');\r\n\r\nglobal.WtcpJs = global.WtcpJs || {};\r\n\r\n(function (wtcp) {\r\n \"use strict\";\r\n\r\n var util = require('./wtcp.util.js');\r\n var resp = require('./wtcp-types/ErrorResponse.js');\r\n var ai = require('./wtcp-types/requests/AnchorInfo.js');\r\n var pmReq = require('./wtcp-types/requests/PrivateTextMessageRequest.js');\r\n var audio = require('./wtcp.wtcpaudio.js');\r\n var locService = require('./wtcp.locator.js');\r\n var uaParser = require('ua-parser-js');\r\n\r\n const WTCPJS_CLIENT_OFFSET = 0x1B58;\r\n\r\n var eventList = {\r\n PROXY_UPDATED: \"pu1\",\r\n CHANNEL_PROPS_RECEIVED: \"cp1\",\r\n CHANNEL_ACTIVITY: \"ca1\",\r\n ENDPOINT_PROPS_RECEIVED: \"ep1\",\r\n PTT_OFF: \"po1\",\r\n DTMF_RECEIEVED: \"dr1\",\r\n CALL_PTT_ON_RECEIVED: \"cpor1\",\r\n CALL_PTT_OFF_RECEIVED: \"cpor2\",\r\n TXT_MSG_RECEIVED: \"tm1\",\r\n OPEN_SESSION_RECEIVED: \"sr1\",\r\n SESSION_CLOSED_RECEIVED: \"scr1\",\r\n PING_PONG_RESPONSE: \"ppr\",\r\n SOCKET_CLOSED: \"sc1\",\r\n SIGNAL_RECEIVED: \"sr2\",\r\n PHONE_LINE_STATUS_CHANGED: \"plsc\",\r\n CALL_PROGRESS_RECEIVED: \"cpr\",\r\n CALL_HANGUP_RECEIVED: \"chr\",\r\n CALL_OFFER_RECEIVED: \"cor\",\r\n CONNECTION_INFO_UPDATED: \"lu\",\r\n PRIV_MEDIA_MSG_RECEIVED: \"pmmr\"\r\n };\r\n\r\n var proxyInstanceCnt = 0;\r\n var proxyGlobals = {};\r\n var transCounter = 0; // transaction counter 1..36767\r\n\r\n var wtcpJsClientErrors = {\r\n \"PTT_NOT_READY\": (() => {\r\n let err = new WtcpJs.ErrorResponse();\r\n err.errorCode = WTCPJS_CLIENT_OFFSET | 1;\r\n err.errorMessage = \"You cannot PTT again until the WtpcjJs client handles the PTTUp response\";\r\n\r\n return err;\r\n })()\r\n };\r\n\r\n var registerInstance = function registerInstance() {\r\n var id = \"proxy_instance_\" + proxyInstanceCnt++;\r\n proxyGlobals[id] = {};\r\n\r\n return id;\r\n };\r\n\r\n var pushCallbacks = function pushCallbacks(map, res, rej) {\r\n // use transaction counter as a key for the map \r\n // use one counter for all maps (don't need to have individual counter for every map) \r\n // some leftover key will be gone after one cycle loop due to a missing response\r\n transCounter = (transCounter + 1) % 36768; \r\n // valid transaction range is [1..36767] \r\n if(transCounter == 0) transCounter = 1; \r\n map.set(transCounter,{ resolve: res, reject: rej })\r\n return transCounter; \r\n };\r\n\r\n var getCallback = function getCallback(map, key) {\r\n var cb;\r\n if (!map.has(key)) {\r\n if (map.size > 0) { // pick the last one -- this is a bad code smell (bug 46475) it appears that unit test will make this bad situation.\r\n wtcpUtil.wtcpInfo(`ALERT: number of keys : ${map.size} map = ${map.toString()}`);\r\n for(let k of map.keys())\r\n key = k;\r\n wtcpUtil.wtcpInfo(\"ALERT: Fetch the last key instead for given key:\", key)\r\n }\r\n }\r\n // if key is still missing, return undefined \r\n cb = map.get(key);\r\n map.delete(key)\r\n return cb; \r\n };\r\n\r\n var ua = null;\r\n if(window && window.navigator) {\r\n ua = uaParser(navigator.userAgent);\r\n }\r\n\r\n wtcp.Client = function (clientOptions, clientWorker) {\r\n\r\n if (!(this instanceof wtcp.Client)) return new wtcp.Client(clientOptions);\r\n\r\n /* --- Private variables --- */\r\n\r\n var local = {};\r\n var defaults = {\r\n profileId: \"\",\r\n pingInterval: 30,\r\n initialVolume: 100,\r\n audioPlayerActive: true,\r\n loggingLevel: 0,\r\n exportOutboundAudio: false,\r\n processorNodeBufferSize: 8192,\r\n outboundAudioFile: 'audio.wav',\r\n deviceId: \"HTML5 capable browser\",\r\n applicationName: 'MOT-WTCPJS-1.1',\r\n licenseUUID: \"{436C743D-896D-456e-A61B-6F564F3D2C78}\" // default to WAVE_LICENSE_WTC_SDK\r\n };\r\n\r\n var socketActive = false;\r\n var locator;\r\n var serverUrlPattern = /^ws{1,2}:\\/\\//;\r\n var httpsPattern = /^https:\\/\\//;\r\n var settings = {};\r\n var pttDownPending = false;\r\n var pttUpPending = false;\r\n var pttUpSuccess = null;\r\n var pttUpFailure = null;\r\n var pttOn = false;\r\n var requestTimeoutId;\r\n\r\n var callbacks = {\r\n socketConnectedCallbacks: new Map(),\r\n sendCredentialsCallbacks: new Map(),\r\n getChannelPropsCallbacks: new Map(),\r\n setChannelPropsCallbacks: new Map(),\r\n getEndpointLookupCallbacks: new Map(),\r\n getEndpointPropsCallbacks: new Map(),\r\n setEndpointPropsCallbacks: new Map(),\r\n setActiveChannelsCallbacks: new Map(),\r\n setActivePhoneLinesCallbacks: new Map(),\r\n pttDownCallbacks: new Map(),\r\n muteChannelCallbacks: new Map(),\r\n dtmfSendCallbacks: new Map(),\r\n callPTTOnCallbacks: new Map(),\r\n callPTTOffCallbacks: new Map(),\r\n addressBookCallbacks: new Map(),\r\n textMessageCallbacks: new Map(),\r\n endpointFilteringCallbacks: new Map(),\r\n endpointPropFilteringCallbacks: new Map(),\r\n openSessionCallbacks: new Map(),\r\n closeSessionCallbacks: new Map(),\r\n channelActivityCallbacks: new Map(),\r\n callMakeRequestCallbacks: new Map(),\r\n callHangupRequestCallbacks: new Map(),\r\n callAnswerRequestCallbacks: new Map(),\r\n clearEndpointFilterCallbacks: new Map(),\r\n privateMediaMessageCallbacks: new Map()\r\n };\r\n\r\n var eventDispatcher = {\r\n events: {},\r\n on: function on(event, callback) {\r\n var handlers = this.events[event] || [];\r\n handlers.push(callback);\r\n this.events[event] = handlers;\r\n\r\n return function() {\r\n for (var i = 0; i < handlers.length; i++) {\r\n if (callback === handlers[i]) {\r\n handlers.splice(i, 1);\r\n break;\r\n }\r\n }\r\n };\r\n },\r\n trigger: function trigger(event, data) {\r\n var handlers = this.events[event];\r\n\r\n if (!handlers || handlers.length < 1) return;\r\n\r\n [].forEach.call(handlers, function (handler) {\r\n try {\r\n handler(data);\r\n } catch (e) {\r\n util.wtcpError(\"An error occurred in the callback subscribed to \" + event + \": \" + e.message);\r\n }\r\n });\r\n }\r\n };\r\n\r\n var EventSubscriber = function(event) {\r\n return {\r\n subscribe: function (callback) {\r\n return eventDispatcher.on(event, callback);\r\n }\r\n }\r\n }\r\n\r\n var workerError = function workerError(e) {\r\n util.wtcpError(\" in Worker: \" + e.message);\r\n };\r\n\r\n var workerMessage = function workerMessage(e) {\r\n try {\r\n if (local[e.data.cmd].length < 2) local[e.data.cmd](e.data.value); else local[e.data.cmd](e.data.value, e.data.tranid);\r\n } catch (e) {\r\n if (typeof e.data !== \"undefined\") util.wtcpError(\"Unknown function called from worker: \", e.data.cmd); else {\r\n util.wtcpError(\"Worker exception thrown\", e);\r\n }\r\n }\r\n };\r\n\r\n var clearCallStates = function() {\r\n // Clear PTT pending flags since the call is no longer active\r\n pttUpPending = false;\r\n pttDownPending = false;\r\n pttOn = false;\r\n }\r\n\r\n Object.assign(settings, defaults, clientOptions);\r\n util.setLoggingLevel(settings.loggingLevel);\r\n\r\n var path = util.getScriptPath();\r\n\r\n // In future release there will be some criteria provided by locator to determine which audio handler to use\r\n // The correct one will be dynamically loaded at run time. For now defaulting to WTCPAudio\r\n var audioHandler = new audio.WTCPAudio(this, settings);\r\n\r\n Object.assign(local, audioHandler.messageHandlers);\r\n\r\n var cb;\r\n var instanceId = registerInstance();\r\n var wtcpWorker = {\r\n terminate: function terminate() { },\r\n postMessage: function postMessage() {\r\n throw \"worker not initialized, you must first connect to a WAVE Proxy\";\r\n }\r\n };\r\n\r\n /* --- Public properties --- */\r\n Object.defineProperty(this, \"LibraryVersion\", { get: function () {\r\n // this gets replaced by gulp at build-time\r\n // VERSION_PLACEHOLDER\r\n }});\r\n Object.defineProperty(this, \"WTCPVersion\", { get: function () { return locator.version; } });\r\n Object.defineProperty(this, \"ServerId\", { get: function () { return locator.proxyServerID; } });\r\n Object.defineProperty(this, \"IsClientActive\", { get: function () { return socketActive; } });\r\n Object.defineProperty(this, \"WTCPAudioStatus\", { get: function () { return audioHandler.getStatus(); } });\r\n Object.defineProperty(this, \"AudioPlayerActive\", {\r\n get: function () { return audioHandler.PlayerEnabled; },\r\n set: function (newValue) {\r\n settings.audioPlayerActive = newValue;\r\n audioHandler.PlayerEnabled = newValue;\r\n }\r\n });\r\n\r\n console.info('WctpJS v' + this.LibraryVersion);\r\n console.info('logging level: ' + settings.loggingLevel);\r\n // Private Function definitions\r\n\r\n var teardownClient = function teardownClient() {\r\n locator = null;\r\n wtcpWorker.terminate(); // Consider having worker close itself to give it a chance to shutdown gracefully\r\n delete proxyGlobals[instanceId];\r\n\r\n util.wtcpInfo(\"WtcpJs Client worker teardown complete\");\r\n };\r\n\r\n var sendMessage = function sendMessage(cmd, tranid, value, transfer) {\r\n if (!socketActive && !(cmd === \"init\" || cmd === \"connect\")) throw \"Can't call \" + cmd + \", Socket is not active! You must call connect() before using the Client object\";\r\n value = value || {};\r\n tranid = tranid || 1;\r\n\r\n if (!transfer) transfer = [];\r\n\r\n wtcpWorker.postMessage({\r\n \"tranid\": tranid,\r\n \"cmd\": cmd,\r\n \"value\": value\r\n }, transfer);\r\n };\r\n\r\n var init = function init() { };\r\n\r\n var initWorker = function initWorker() {\r\n\r\n sendMessage(\"init\", 1, {\r\n wtcpjsPath: path + \"wtcpjs.js\",\r\n settings: settings\r\n });\r\n };\r\n\r\n var openSession = function openSession() {\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"openSession\", pushCallbacks(callbacks.openSessionCallbacks, resolve, reject), {\r\n pingIntervalOption: settings.pingInterval,\r\n deviceId: settings.deviceId,\r\n platformString: ua ? `${settings.applicationName}-${ua.os.name}-${ua.os.version}-${ua.cpu.architecture}` : `${settings.applicationName}-?-?-?`\r\n });\r\n });\r\n };\r\n\r\n var sendCredentials = function sendCredentials(tranId, userId, password, profile) {\r\n //WTCP Protocol Specification says to MD5 the password, but that doesn't seem to work on proxy...\r\n //var md5hash = CryptoJS.MD5(password);\r\n\r\n if (!profile) profile = \"\";\r\n\r\n sendMessage(\"sendCredentials\", tranId, {\r\n userId: userId,\r\n password: password,\r\n profile: profile,\r\n uuid: settings.licenseUUID\r\n });\r\n };\r\n\r\n var login = function login(usr, pwd, profileId) {\r\n util.wtcpInfo(\"Connect Success\");\r\n\r\n return openSession().then(function (args) {\r\n return new Promise(function (resolve, reject) {\r\n let tranId = pushCallbacks(callbacks.sendCredentialsCallbacks, resolve, reject);\r\n\r\n if (profileId) sendCredentials(tranId, usr, pwd, profileId); else sendCredentials(tranId, usr, pwd, \"\");\r\n }, function (args) {\r\n //options.error.call(this, args);\r\n });\r\n });\r\n };\r\n\r\n /* --- Worker.onmessage functions --- */\r\n\r\n local.setEndpointPropertiesResponse = function (data, t) {\r\n\r\n cb = getCallback(callbacks.setEndpointPropsCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"setEndpointPropertiesResponse\", data);\r\n };\r\n\r\n local.signalingSyntaxError = function (data) {\r\n eventDispatcher.trigger(eventList.SIGNAL_RECEIVED, data);\r\n util.wtcpInfo(\"Signaling op-code 1: Syntax Error received\", data);\r\n };\r\n\r\n local.openSessionResponse = function (data, t) {\r\n\r\n cb = getCallback(callbacks.openSessionCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"OpenSessionResponse\", data);\r\n };\r\n\r\n local.openSessionError = function (data, t) {\r\n socketActive = false;\r\n cb = getCallback(callbacks.openSessionCallbacks, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n util.wtcpInfo(\"openSessionError\", data);\r\n };\r\n\r\n local.closeSessionResponse = function (data, t) {\r\n teardownClient();\r\n cb = getCallback(callbacks.closeSessionCallbacks, t);\r\n if (cb) cb.resolve(); \r\n\r\n util.wtcpInfo(\"Proxy session closed\");\r\n };\r\n\r\n local.closeSessionUnsolResponse = function (data) {\r\n eventDispatcher.trigger(eventList.SESSION_CLOSED_RECEIVED, data);\r\n util.wtcpError(\"closeSessionError\", data);\r\n };\r\n\r\n local.sendCredentialsResponse = function (data, t) {\r\n cb = getCallback(callbacks.sendCredentialsCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n // Need to add cb here\r\n util.wtcpInfo(\"sendCredentialsResponse\", data);\r\n };\r\n\r\n local.sendCredentialsError = function (data, t) {\r\n cb = getCallback(callbacks.sendCredentialsCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"sendCredentialsResponse\", data);\r\n // Need to add callbacks here\r\n };\r\n\r\n local.setActiveChannelsResponse = function (data, t) {\r\n cb = getCallback(callbacks.setActiveChannelsCallbacks, t);\r\n if (cb) {\r\n if (data.hasErrors && data.channelResponses.length === 0) cb.reject(data.failedChannelResponses);\r\n else cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"setChannelsResponse\", data);\r\n };\r\n\r\n local.unsolProxyUpdate = function (data) {\r\n eventDispatcher.trigger(eventList.PROXY_UPDATED, data);\r\n util.wtcpInfo(\"unsolicitedProxyUpdate\", data);\r\n };\r\n\r\n local.getChannelPropertiesUnsol = function (data) {\r\n eventDispatcher.trigger(eventList.CHANNEL_PROPS_RECEIVED, data);\r\n util.wtcpInfo(\"getChannelPropertiesUnsol\", data);\r\n };\r\n\r\n local.getChannelPropertiesResponse = function (data, t) {\r\n cb = getCallback(callbacks.getChannelPropsCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"getChannelPropertiesResponse\", data);\r\n };\r\n\r\n local.getChannelPropertiesError = function (data, t) {\r\n cb = getCallback(callbacks.getChannelPropsCallbacks, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n util.wtcpError(\"getChannelPropertiesError\", data);\r\n };\r\n\r\n local.setChannelPropertiesResponse = function (data, t) {\r\n cb = getCallback(callbacks.setChannelPropsCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"setChannelPropertiesResponse\", data);\r\n };\r\n\r\n local.setChannelPropertiesError = function (data, t) {\r\n cb = getCallback(callbacks.setChannelPropsCallbacks, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n util.wtcpError(\"setChannelPropertiesError\", data);\r\n };\r\n\r\n local.channelActivityResponse = function (data, t) {\r\n cb = getCallback(callbacks.channelActivityCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"channelActivityResponse\", data);\r\n };\r\n\r\n local.channelActivityError = function (err, t) {\r\n cb = getCallback(callbacks.channelActivityCallbacks, t);\r\n if (cb) {\r\n cb.reject(err);\r\n }\r\n util.wtcpError(\"channelActivityError\", err);\r\n };\r\n\r\n local.channelActivityUnsolicited = function (data) {\r\n eventDispatcher.trigger(eventList.CHANNEL_ACTIVITY, data);\r\n util.wtcpInfo(\"channelActivityUnsolicited\", data);\r\n };\r\n\r\n local.endpointLookupResponse = function (data, t) {\r\n cb = getCallback(callbacks.getEndpointLookupCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"endpointLookUpResponse\", data);\r\n };\r\n\r\n local.endpointLookupError = function (data, t) {\r\n cb = getCallback(callbacks.getEndpointLookup, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n };\r\n\r\n local.getEndpointPropertiesResponse = function (data, t) {\r\n cb = getCallback(callbacks.getEndpointPropsCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n };\r\n\r\n local.getEndpointPropertiesError = function (data, t) {\r\n cb = getCallback(callbacks.getEndpointPropsCallbacks, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n };\r\n\r\n local.getEndpointPropertiesUnsolicited = function (data) {\r\n // Not sure if this opCode is ever sent from Proxy. Test it... if not, combine this with _RESP directly above\r\n eventDispatcher.trigger(eventList.ENDPOINT_PROPS_RECEIVED, data);\r\n util.wtcpInfo(\"getEndpointPropertiesUnsolicited\", data);\r\n };\r\n\r\n local.setEndpointPropertiesError = function (data, t) {\r\n cb = getCallback(callbacks.setEndpointPropsCallbacks, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n util.wtcpError(\"setEndpointPropertiesError\", data);\r\n };\r\n\r\n local.pttResponse = function (data, t) {\r\n pttDownPending = false;\r\n cb = getCallback(callbacks.pttDownCallbacks, t);\r\n if (cb) {\r\n if (!pttUpPending) {\r\n cb.resolve(data);\r\n if (audioHandler && data.channelResponses.length > 0 && data.channelResponses[0].errorCode === 0) {\r\n audioHandler.sendAudio();\r\n\r\n util.wtcpInfo(\"PTT On\", data);\r\n } else {\r\n pttOn = false;\r\n util.wtcpInfo(\"PTT Off\", data);\r\n }\r\n } else {\r\n // PTTUp was called before the PTTDown response came back\r\n pttUpPending = false;\r\n util.wtcpInfo(\"Cancelling PTTDown because PTTUp request came before PTTDown response was received from proxy\");\r\n cb.reject(wtcpJsClientErrors[\"PTT_NOT_READY\"]);\r\n sendPttUp()\r\n .then((data) => {\r\n // TBD: This is not working correctly. PTT while another channel is clocking waiting for response\r\n // leads to bad state on the channel you are trying to PTT on\r\n pttUpSuccess(data);\r\n })\r\n .catch((err) => {\r\n pttUpFailure(err);\r\n });\r\n }\r\n }\r\n };\r\n\r\n local.pttError = function (err, t) {\r\n cb = getCallback(callbacks.pttDownCallbacks, t);\r\n if (cb) {\r\n cb.reject(err);\r\n }\r\n\r\n pttOn = false;\r\n pttUpPending = false;\r\n\r\n util.wtcpError(\"PTT Down Error\", err);\r\n };\r\n\r\n local.pttOff = function (data, t) { // Unsolicited PTT Off message\r\n pttOn = false;\r\n eventDispatcher.trigger(eventList.PTT_OFF, data);\r\n util.wtcpInfo(\"PTT Off\", data);\r\n };\r\n\r\n local.setActivePhoneLinesResponse = function (data, t) {\r\n cb = getCallback(callbacks.setActivePhoneLinesCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"setActivePhoneLinesResponse\", data);\r\n };\r\n\r\n local.setActivePhoneLinesError = function (data, t) {\r\n cb = getCallback(callbacks.setActivePhoneLinesCallbacks, t);\r\n if (cb) {\r\n cb.reject(data);\r\n }\r\n util.wtcpError(\"ActivePhoneLineError\", data);\r\n };\r\n\r\n local.phoneLineStatusUnsol = function (data, t) {\r\n util.wtcpInfo(\"phoneLineStatusUnsol\", data);\r\n eventDispatcher.trigger(eventList.PHONE_LINE_STATUS_CHANGED, data);\r\n };\r\n\r\n local.callProgressUnsol = function(data, t) {\r\n util.wtcpInfo(\"callProgressUnsol\", data);\r\n eventDispatcher.trigger(eventList.CALL_PROGRESS_RECEIVED, data);\r\n };\r\n\r\n local.muteChannelResponse = function (data, t) {\r\n cb = getCallback(callbacks.muteChannelCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n util.wtcpInfo(\"Mute Channel Response\", data);\r\n };\r\n\r\n local.muteChannelError = function (data, t) {\r\n cb = getCallback(callbacks.muteChannelCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Mute Channel Error\", data);\r\n };\r\n\r\n local.pingResponse = function (data, t) {\r\n util.wtcpInfo(\"Proxy Pong\", data);\r\n };\r\n\r\n local.pongResponse = function (data) {\r\n eventDispatcher.trigger(eventList.PING_PONG_RESPONSE, data);\r\n util.wtcpInfo(\"Proxy Pong response to client Ping\", data);\r\n };\r\n\r\n local.pingRequest = function (data, t) {\r\n util.wtcpInfo(\"Proxy Ping\", data);\r\n };\r\n\r\n local.dtmfResponse = function (t) {\r\n cb = getCallback(callbacks.dtmfSendCallbacks, t);\r\n if (cb) cb.resolve();\r\n\r\n util.wtcpInfo(\"DTMF Send Response\");\r\n };\r\n\r\n local.dtmfError = function (data, t) {\r\n cb = getCallback(callbacks.dtmfSendCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"DTMF Send Error\", data);\r\n };\r\n\r\n local.dtmfUnsol = function (data) {\r\n eventDispatcher.trigger(eventList.DTMF_RECEIEVED, data);\r\n\r\n util.wtcpInfo(\"DTMF Received\", data);\r\n };\r\n\r\n local.callPttOnResponse = function (data, t) {\r\n\r\n pttDownPending = false;\r\n cb = getCallback(callbacks.pttDownCallbacks, t);\r\n if (cb) {\r\n cb.resolve(data);\r\n if (!pttUpPending) {\r\n audioHandler.sendAudio();\r\n\r\n util.wtcpInfo(\"Private Call PTT On\", data);\r\n } \r\n }\r\n\r\n cb = getCallback(callbacks.callPTTOnCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n if (audioHandler && data.errorCode === 0) audioHandler.sendAudio(); else pttOn = false;\r\n\r\n util.wtcpInfo(\"Call PTT On Response\", data);\r\n };\r\n\r\n local.callPttOnError = function (data, t) {\r\n cb = getCallback(callbacks.callPTTOnCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n pttOn = false;\r\n\r\n util.wtcpError(\"Call PTT On Error\", data);\r\n };\r\n\r\n local.callPttOnUnsol = function (data) {\r\n eventDispatcher.trigger(eventList.CALL_PTT_ON_RECEIVED, data);\r\n util.wtcpInfo(\"Call PTT On Received\", data);\r\n };\r\n\r\n local.callPttOffResponse = function (data, t) {\r\n cb = getCallback(callbacks.callPTTOffCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n pttOn = false;\r\n\r\n if (pttUpPending) {\r\n pttUpPending = false;\r\n util.wtcpInfo(\"Cancelling callPTTOn because callPTTOff request came before callPTTOn response was received from proxy\");\r\n sendCallPttUp(d.callId)\r\n .then((data) => {\r\n pttUpSuccess(data);\r\n })\r\n .catch((err) => {\r\n pttUpFailure(err);\r\n });\r\n }\r\n\r\n util.wtcpInfo(\"Call PTT Off Response\", data);\r\n };\r\n\r\n local.callPttOffError = function (data, t) {\r\n cb = getCallback(callbacks.callPTTOffCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Call PTT Off Error\", data);\r\n };\r\n\r\n local.callPttOffUnsol = function (data) {\r\n eventDispatcher.trigger(eventList.CALL_PTT_OFF_RECEIVED, data);\r\n util.wtcpInfo(\"Call PTT Off Received\", data);\r\n };\r\n\r\n local.addressBookGetResponse = function (data, t) {\r\n cb = getCallback(callbacks.addressBookCallbacks, t);\r\n if (cb) {\r\n if (data.errorCode > 0) cb.reject(data); else cb.resolve(data);\r\n }\r\n\r\n util.wtcpInfo(\"Address Book Info Response\", data);\r\n };\r\n\r\n local.textMessageResponse = function (data, t) {\r\n cb = getCallback(callbacks.textMessageCallbacks, t);\r\n if (cb) {\r\n data.textMsgConfirmedDate = new Date(Date.now());\r\n cb.resolve(data);\r\n }\r\n\r\n util.wtcpInfo(\"Text Message Sent\", data);\r\n };\r\n\r\n local.textMessageError = function (data, t) {\r\n cb = getCallback(callbacks.textMessageCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Error sending Text Message\", data);\r\n };\r\n\r\n local.textMessageUnsol = function (data) {\r\n eventDispatcher.trigger(eventList.TXT_MSG_RECEIVED, data);\r\n util.wtcpInfo(\"Text Message Received\", data);\r\n };\r\n\r\n local.privateMediaMessageResponse = function (data, t) {\r\n cb = getCallback(callbacks.privateMediaMessageCallbacks, t);\r\n if(cb) {\r\n data.textMsgConfirmedDate = new Date(Date.now());\r\n cb.resolve(data);\r\n }\r\n\r\n util.wtcpInfo(\"Private Media Message Sent\", data);\r\n };\r\n\r\n local.privateMediaMessageError = function (data, t) {\r\n cb = getCallback(callbacks.privateMediaMessageCallbacks, t) ;\r\n if(cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Error sending Private Media Message\");\r\n }\r\n\r\n local.privateMediaMessageUnsol = function(data, t) {\r\n eventDispatcher.trigger(eventList.PRIV_MEDIA_MSG_RECEIVED, data);\r\n util.wtcpInfo(\"Private Media Message Received\", data);\r\n };\r\n\r\n local.callMakeResponse = function(data, t) {\r\n cb = getCallback(callbacks.callMakeRequestCallbacks, t);\r\n if (cb) {\r\n if (data.errorCode > 0) cb.reject(data); else cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"Call Make acknowledged by Proxy\", data);\r\n };\r\n\r\n local.callHangupResponse = function(data, t) {\r\n clearCallStates();\r\n cb = getCallback(callbacks.callHangupRequestCallbacks, t);\r\n if (cb) {\r\n if (data.errorCode > 0) cb.reject(data); else cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"Call Hang-up acknowledged by Proxy\", data);\r\n };\r\n\r\n local.callAnswerResponse = function(data, t) {\r\n cb = getCallback(callbacks.callAnswerRequestCallbacks, t);\r\n if (cb) {\r\n if (data.errorCode > 0) cb.reject(data); else cb.resolve(data);\r\n }\r\n util.wtcpInfo(\"Call Answer acknowledged by Proxy\", data);\r\n };\r\n\r\n local.callHangupUnsol = function(data, t) {\r\n clearCallStates();\r\n eventDispatcher.trigger(eventList.CALL_HANGUP_RECEIVED, data);\r\n util.wtcpInfo(\"Call Hangup Received\", data);\r\n };\r\n\r\n local.callOfferUnsol = function(data, t) {\r\n eventDispatcher.trigger(eventList.CALL_OFFER_RECEIVED, data);\r\n util.wtcpInfo(\"Call Offer Received\", data);\r\n };\r\n\r\n // Version 2\r\n local.setEndpointPropertiesFilterResponse = function (data, t) {\r\n cb = getCallback(callbacks.endpointPropFilteringCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n util.wtcpInfo(\"Set Endpoint Prop Filter Response\", data);\r\n };\r\n\r\n local.setEndpointPropertiesFilterError = function (data, t) {\r\n cb = getCallback(callbacks.endpointPropFilteringCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Set Endpoint Prop Filter Error\", data);\r\n };\r\n\r\n local.setEndpointFilterResponse = function (data, t) {\r\n cb = getCallback(callbacks.endpointFilteringCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n util.wtcpInfo(\"Set Endpoint Filter Response\", data);\r\n };\r\n\r\n local.setEndpointFilterError = function (data, t) {\r\n cb = getCallback(callbacks.endpointFilteringCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Set Endpoint Filter Error\", data);\r\n };\r\n\r\n local.clearEndpointFilterResponse = function(data, t) {\r\n cb = getCallback(callbacks.clearEndpointFilterCallbacks, t);\r\n if (cb) cb.resolve(data);\r\n\r\n util.wtcpInfo(\"Clear Endpoint Filer Response\", data);\r\n };\r\n\r\n local.clearEndpointFilterError = function(data, t) {\r\n cb = getCallback(callbacks.clearEndpointFilterCallbacks, t);\r\n\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Clear Endpoint Filter Error\", data);\r\n };\r\n\r\n local.playAudio = function (data) {\r\n //audioHandler.playAudio(d.audioMessages, d.audioLength, d.data);\r\n audioHandler.playAudio(data.audioArrayBuffer, data.audioLength);\r\n };\r\n\r\n local.connectionInfoUpdated = function(data, t) {\r\n eventDispatcher.trigger(eventList.CONNECTION_INFO_UPDATED, data);\r\n util.wtcpInfo(\"Connection Info Updated\", data);\r\n };\r\n\r\n local.wsConnected = function (d, t) {\r\n socketActive = true;\r\n\r\n cb = getCallback(callbacks.socketConnectedCallbacks, t);\r\n if (cb) cb.resolve();\r\n\r\n util.wtcpInfo(\"Web Socket connection established\");\r\n };\r\n\r\n local.wsClosed = function (closeEvent) {\r\n socketActive = false;\r\n eventDispatcher.trigger(eventList.SOCKET_CLOSED, closeEvent);\r\n util.wtcpInfo(\"Web Socket connection closed\", closeEvent);\r\n };\r\n\r\n local.wsError = function (data, t) {\r\n cb = getCallback(callbacks.socketConnectedCallbacks, t);\r\n if (cb) cb.reject(data);\r\n\r\n util.wtcpError(\"Web Socket connection failed\", data);\r\n };\r\n\r\n // Expose two functions for unit testing\r\n\r\n this.pushCallbacks = pushCallbacks;\r\n this.getCallback = getCallback;\r\n\r\n /* --- Public events --- */\r\n this.onConnectionClosed = new EventSubscriber(eventList.SOCKET_CLOSED);\r\n\r\n this.onSessionClosed = new EventSubscriber(eventList.SESSION_CLOSED_RECEIVED);\r\n\r\n this.onProxyUpdated = new EventSubscriber(eventList.PROXY_UPDATED);\r\n\r\n this.onChannelPropertiesReceived = new EventSubscriber(eventList.CHANNEL_PROPS_RECEIVED);\r\n\r\n this.onChannelActivity = new EventSubscriber(eventList.CHANNEL_ACTIVITY);\r\n\r\n this.onEndpointPropertiesReceived = new EventSubscriber(eventList.ENDPOINT_PROPS_RECEIVED);\r\n\r\n this.onPhoneLineStatusChanged = new EventSubscriber(eventList.PHONE_LINE_STATUS_CHANGED);\r\n\r\n this.onCallProgressReceived = new EventSubscriber(eventList.CALL_PROGRESS_RECEIVED);\r\n\r\n this.onCallHangupReceived = new EventSubscriber(eventList.CALL_HANGUP_RECEIVED);\r\n\r\n this.onCallOfferReceived = new EventSubscriber(eventList.CALL_OFFER_RECEIVED);\r\n\r\n this.onPTTOff = new EventSubscriber(eventList.PTT_OFF);\r\n\r\n this.onDTMFReceived = new EventSubscriber(eventList.DTMF_RECEIEVED);\r\n\r\n this.onCallPTTOnReceived = new EventSubscriber(eventList.CALL_PTT_ON_RECEIVED);\r\n\r\n this.onCallPTTOffReceived = new EventSubscriber(eventList.CALL_PTT_OFF_RECEIVED);\r\n\r\n this.onTextMessageReceived = new EventSubscriber(eventList.TXT_MSG_RECEIVED);\r\n\r\n this.onPrivateMediaMessageReceived = new EventSubscriber(eventList.PRIV_MEDIA_MSG_RECEIVED);\r\n\r\n this.onPingResponse = new EventSubscriber(eventList.PING_PONG_RESPONSE);\r\n\r\n this.onConnectionInfoUpdated = new EventSubscriber(eventList.CONNECTION_INFO_UPDATED);\r\n\r\n /* --- Public client functions --- */\r\n this.connect = function (serverUrl, username, password, profileId) {\r\n\r\n if (wtcpWorker) {\r\n // Re-connecting - terminate existing worker\r\n wtcpWorker.onerror = null;\r\n wtcpWorker.onmessage = null;\r\n wtcpWorker.terminate();\r\n locator = null;\r\n }\r\n\r\n wtcpWorker = clientWorker || new Worker(path + 'wtcp-worker-api.js');\r\n\r\n wtcpWorker.onerror = workerError;\r\n wtcpWorker.onmessage = workerMessage;\r\n\r\n initWorker();\r\n\r\n return new Promise(function (resolve, reject) {\r\n var tranId = pushCallbacks(callbacks.socketConnectedCallbacks, resolve, reject);\r\n locator = new locService.Locator();\r\n if (serverUrl.match(serverUrlPattern)) {\r\n locator.webSocketServer = serverUrl;\r\n\r\n sendMessage(\"connect\", tranId, {\r\n locator: locator\r\n });\r\n } else {\r\n locator.getProxy(serverUrl).then(function () {\r\n if (locator.proxyServerID == null) throw \"Locator not initialized, call getProxy()\";\r\n\r\n let _address;\r\n if (locator.wsPort) {\r\n _address = `${locator.address[0]}:${locator.wsPort}`;\r\n } else {\r\n _address = locator.address[0];\r\n }\r\n\r\n if (!!serverUrl.match(httpsPattern)) {\r\n locator.webSocketServer = `wss://${_address}`;\r\n } else {\r\n locator.webSocketServer = `ws://${_address}`;\r\n }\r\n\r\n sendMessage(\"connect\", tranId, {\r\n locator: locator\r\n });\r\n })[\"catch\"](function (err) {\r\n reject(err);\r\n });\r\n }\r\n }).then(function () {\r\n return login(username, password, profileId);\r\n }, function (err) {\r\n throw \"error connecting to Proxy\";\r\n });\r\n };\r\n\r\n this.setProfile = function (username, password, profileId) {\r\n return new Promise(function (resolve, reject) {\r\n let tranId = pushCallbacks(callbacks.sendCredentialsCallbacks, resolve, reject);\r\n\r\n sendCredentials(tranId, username || \"\", password || \"\", profileId || \"\");\r\n });\r\n };\r\n\r\n // Proxy Request Messages\r\n this.closeSession = function () {\r\n return new Promise(function(resolve, reject) {\r\n sendMessage(\"closeSession\", pushCallbacks(callbacks.closeSessionCallbacks, resolve, reject));\r\n });\r\n };\r\n\r\n this.setActiveChannels = function (channelIds) {\r\n if (!channelIds || !(typeof channelIds === \"object\")) channelIds = [];\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"setActiveChannels\", pushCallbacks(callbacks.setActiveChannelsCallbacks, resolve, reject), {\r\n channelIds: channelIds\r\n });\r\n });\r\n };\r\n\r\n this.getChannelProperties = function (channelId) {\r\n ///Requests Channel Properties from Proxy\r\n ///Channel ID to request properties for\r\n if (!channelId) throw \"getChannelPropertiesRequest(channelId) requires a valid channel Id\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"getChannelPropertiesRequest\", pushCallbacks(callbacks.getChannelPropsCallbacks, resolve, reject), {\r\n channelId: channelId\r\n });\r\n });\r\n };\r\n\r\n this.setChannelProperties = function (channelId, props) {\r\n ///Request Proxy save or update Channel Properties\r\n ///Channel ID to set properties for\r\n ///json object containing key-value pairs\r\n if (!channelId) throw \"setChannelPropertiesRequest(channelId, properties) expects a valid channel Id\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"setChannelPropertiesRequest\", pushCallbacks(callbacks.setChannelPropsCallbacks, resolve, reject), {\r\n channelId: channelId,\r\n props: props\r\n });\r\n });\r\n };\r\n\r\n this.getChannelActivity = function (channelId) {\r\n if (!channelId) throw \"channelActivityRequest(channelId) requires a valid channel Id\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"channelActivityRequest\", pushCallbacks(callbacks.channelActivityCallbacks, resolve, reject), {\r\n channelId: channelId\r\n });\r\n });\r\n };\r\n\r\n this.endpointLookup = function (channelId, includeFlags, excludeFlags, pageSize, pageNumber, nameBeginsWith) {\r\n if (!channelId) throw \"channelActivityRequest(channelId) requires a valid channel Id\";\r\n\r\n includeFlags = includeFlags || new wtcp.EndpointFlags();\r\n excludeFlags = excludeFlags || new wtcp.EndpointFlags();\r\n pageSize = pageSize || 1;\r\n pageNumber = pageNumber || 1;\r\n nameBeginsWith = nameBeginsWith || \"\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"endpointLookupRequest\", pushCallbacks(callbacks.getEndpointLookupCallbacks, resolve, reject), {\r\n channelId: channelId,\r\n includeFlags: includeFlags,\r\n excludeFlags: excludeFlags,\r\n pageSize: pageSize,\r\n pageNumber: pageNumber,\r\n nameBeginsWith: nameBeginsWith\r\n });\r\n });\r\n };\r\n\r\n this.getEndpointProperties = function (endpointId, propList, channelId) {\r\n if (!endpointId) throw \"getEndpointProperties(endpointId, properties) requires a valid endpoint Id\";\r\n\r\n var msgBody = {\r\n endpointId: endpointId,\r\n propList: propList\r\n };\r\n\r\n if (channelId != null) {\r\n msgBody.channelId = channelId;\r\n }\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"getEndpointPropertiesRequest\", pushCallbacks(callbacks.getEndpointPropsCallbacks, resolve, reject), msgBody );\r\n });\r\n };\r\n\r\n this.setEndpointProperties = function (endpointId, props) {\r\n if (!endpointId) throw \"setEndpointProperties(endpointId, properties) requires a valid endpoint Id\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"setEndpointPropertiesRequest\", pushCallbacks(callbacks.setEndpointPropsCallbacks, resolve, reject), {\r\n endpointId: endpointId,\r\n props: props\r\n });\r\n });\r\n };\r\n\r\n this.PTTDown = function (channelIds) {\r\n if (!channelIds || Object.prototype.toString.call(channelIds) !== \"[object Array]\" || channelIds.length === 0) throw \"PTTDown requires an array of channel ids\";\r\n pttDownPending = true;\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n if (!pttOn && !pttUpPending) {\r\n pttOn = true;\r\n sendMessage(\"PTTDown\", pushCallbacks(callbacks.pttDownCallbacks, resolve, reject), {\r\n channelIds: channelIds\r\n });\r\n } else {\r\n util.wtcpError(`ALERT: PTTDown pttOn=${pttOn} and pttUpPending=${pttUpPending}`);\r\n reject(wtcpJsClientErrors[\"PTT_NOT_READY\"]);\r\n }\r\n });\r\n };\r\n\r\n function sendPttUp() {\r\n let sendMessagePromise = new Promise(function (resolve, reject) {\r\n sendMessage(\"PTTUp\", pushCallbacks(callbacks.pttDownCallbacks, resolve, reject));\r\n });\r\n\r\n // wait promise for a second before timeout \r\n return util.promiseTimeout(1000, sendMessagePromise)\r\n .then((result) => { util.wtcpInfo(\"Sending a message : \", result); \r\n return result; })\r\n .catch(err => { util.wtcpInfo(\"ALERT : sending a message :\",err);\r\n return err; });\r\n }\r\n\r\n function awaitPttUp() {\r\n let awaitPromise = new Promise(function(resolve, reject) {\r\n pttUpPending = true;\r\n pttUpSuccess = resolve;\r\n pttUpFailure = reject;\r\n });\r\n\r\n // wait promise for a second before timeout\r\n return util.promiseTimeout(1000, awaitPromise)\r\n .then((result) => { util.wtcpInfo(\"awaitPttUp done, result =\", result);\r\n pttUpPending = false; \r\n pttOn = false;\r\n return result;\r\n })\r\n .catch(err => { util.wtcpInfo(\"awaitPttUp. exception =\", errr);\r\n return err;\r\n });\r\n }\r\n\r\n this.PTTUp = function () {\r\n if (pttDownPending) {\r\n return awaitPttUp();\r\n } else {\r\n if (audioHandler) {\r\n return util.promiseTimeout(1000, audioHandler.endAudio())\r\n .then(() => {return sendPttUp();})\r\n .catch((err) => {\r\n // will send sendPttUp even if failed to close endAudio\r\n util.wtcInfo('ALERT: PttUp failed while waiting endAudio call', err);\r\n return sendPttUp();\r\n });\r\n } else {\r\n util.wtcpDebug(\"no audio handler\");\r\n return sendPttUp();\r\n }\r\n }\r\n };\r\n\r\n function sendCallPttUp(callId) {\r\n return new Promise(function (resolve, reject) {\r\n sendMessage(\"callPTTOffRequest\", pushCallbacks(callbacks.callPTTOffCallbacks, resolve, reject), {\r\n callId: callId\r\n });\r\n });\r\n }\r\n\r\n this.callPTTOn = function(callId) {\r\n if (!callId) throw \"callPTTOn(callId) requires a valid call Id\";\r\n\r\n pttDownPending = true;\r\n\r\n return new Promise(function(resolve, reject) {\r\n\r\n if (!pttOn) {\r\n pttOn = true;\r\n\r\n sendMessage(\"callPTTOnRequest\", pushCallbacks(callbacks.callPTTOnCallbacks, resolve, reject), {\r\n callId: callId\r\n });\r\n } else {\r\n reject(wtcpJsClientErrors[\"PTT_NOT_READY\"]);\r\n }\r\n });\r\n };\r\n\r\n this.callPTTOff = function (callId) {\r\n if (!callId) throw \"callPTTOff(callId) requires a valid call Id\";\r\n\r\n if (pttDownPending) {\r\n\r\n return awaitPttUp();\r\n } else {\r\n if (audioHandler) {\r\n return audioHandler.endAudio().then(() => {\r\n return sendCallPttUp(callId);\r\n }).catch((err) => {\r\n util.wtcpError('callPTTOff failed', err);\r\n });\r\n } else {\r\n return sendCallPttUp(callId);\r\n }\r\n }\r\n };\r\n\r\n this.setActivePhoneLines = function (phoneLines) {\r\n let fail = !phoneLines;\r\n\r\n if (!fail) {\r\n for (let line of phoneLines) {\r\n if (!line) {\r\n fail = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (fail ) throw \"setActivePhoneLines requires a list of phone lines\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"setActivePhoneLines\", pushCallbacks(callbacks.setActivePhoneLinesCallbacks, resolve, reject), {\r\n phoneLines: phoneLines\r\n });\r\n });\r\n };\r\n\r\n this.makeCall = function (type, source, destination) {\r\n ///Make a point-to-point call request\r\n ///Endpoint == 1, E164 number == 2\r\n ///Phone line to use to make the call (as returned by \"Start Call Provider\") response\r\n ///if type === 1, then this is the endpoint to reach, otherwise it is the phone number to call\r\n ///Returns a Promise\r\n if (!type) throw \"makeCall(type, source, destination) requires type, source, and destination\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"callMakeRequest\", pushCallbacks(callbacks.callMakeRequestCallbacks, resolve, reject), {\r\n type: type,\r\n source: source,\r\n destination: destination\r\n });\r\n });\r\n };\r\n\r\n this.answerCall = function(callId) {\r\n if (!callId) throw \"answerCall requires a valid call Id\";\r\n\r\n return new Promise(function(resolve, reject) {\r\n sendMessage(\"callAnswerRequest\", pushCallbacks(callbacks.callAnswerRequestCallbacks, resolve, reject), {\r\n callId: callId\r\n });\r\n });\r\n };\r\n\r\n this.hangupCall = function (callId) {\r\n if (!callId) throw \"hangupCall requires a valid call Id\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"callHangUpRequest\", pushCallbacks(callbacks.callHangupRequestCallbacks, resolve, reject), {\r\n callId: callId\r\n });\r\n });\r\n };\r\n\r\n this.muteAllChannels = function () {\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"muteAllChannels\", pushCallbacks(callbacks.muteChannelCallbacks, resolve, reject));\r\n });\r\n };\r\n\r\n this.unmuteAllChannels = function () {\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"unmuteAllChannels\", pushCallbacks(callbacks.muteChannelCallbacks, resolve, reject));\r\n });\r\n };\r\n\r\n this.muteChannels = function (channels) {\r\n if (!channels) throw \"muteChannels(chanels) requires a valid list of channels\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"muteChannels\", pushCallbacks(callbacks.muteChannelCallbacks, resolve, reject), { channels: channels });\r\n });\r\n };\r\n\r\n this.dtmfSendRequest = function (callId, dtmf) {\r\n if (!callId) throw \"dtmfSendRequest(callId) was called without a valid callId\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"dtmfSendRequest\", pushCallbacks(callbacks.dtmfSendCallbacks, resolve, reject), {\r\n callId: callId,\r\n dtmf: dtmf\r\n });\r\n });\r\n };\r\n\r\n this.getAddressBook = function (pageSize, pageNum, filter) {\r\n if (locator.version === 1 || !filter || filter.length === 0) filter = \"*\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"getAddressBook\", pushCallbacks(callbacks.addressBookCallbacks, resolve, reject), {\r\n pageSize: pageSize || 200,\r\n pageNum: pageNum || 1,\r\n filter: filter\r\n });\r\n });\r\n };\r\n\r\n function getDefaultOptions() {\r\n var options = {};\r\n\r\n if (!options.hasOwnProperty(\"important\")) options.important = false;\r\n\r\n return options\r\n }\r\n\r\n this.sendTextMessage = function (channelId, message, options) {\r\n if (!channelId || typeof channelId !== \"number\") throw \"sendTextMessage(channelId, message) requires a valid channel Id\";\r\n\r\n options = options || getDefaultOptions();\r\n\r\n if (options.important) message = \"[[ALERT1]]\" + message;\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n // Only channel text messages are currently implemented\r\n sendMessage(\"sendTextMessage\", pushCallbacks(callbacks.textMessageCallbacks, resolve, reject), {\r\n channelId: channelId,\r\n message: message\r\n });\r\n });\r\n };\r\n\r\n this.sendP2PMessage = function(privateTextMessageRequest, options) {\r\n if (!privateTextMessageRequest || !privateTextMessageRequest instanceof wtcp.PrivateTextMessageRequest) throw \"sendP2PMessage(privateTextMessageRequest) argument must be type PrivateTextMessageRequest\";\r\n\r\n options = options || getDefaultOptions();\r\n\r\n // eventually this should be replaced with metadata and handled in the client, not WtcpJs\r\n if (options.important) privateTextMessageRequest.data = \"[[ALERT1]]\" + privateTextMessageRequest.data;\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n // assumed will always be a text/plain message. We will have to change the signature when we support multimedia messages\r\n sendMessage(\"sendP2PMessage\", pushCallbacks(callbacks.privateMediaMessageCallbacks, resolve, reject), privateTextMessageRequest);\r\n });\r\n }\r\n\r\n // Version 2\r\n var setEndpointFilter = function setEndpointFilter(type, filterId, channelId, endpointFilter, propFilter, endpointId, threshold, anchor) {\r\n /*if (locator.version < 2)\r\n throw \"Endpoint filtering is only supported in WTCP version 2 or greater\";*/\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"setEndpointFilter\", pushCallbacks(callbacks.endpointFilteringCallbacks, resolve, reject), {\r\n filterId: filterId,\r\n type: type,\r\n channelId: channelId,\r\n endpointFilter: endpointFilter,\r\n propertyFilter: propFilter,\r\n endpointId: endpointId,\r\n notificationThreshold: threshold,\r\n anchorInfo: anchor\r\n });\r\n });\r\n };\r\n\r\n this.setEndpointChannelFilter = function (filterId, channelId, endpointFilter, propFilter, threshold, anchorInfo) {\r\n if (!channelId) throw \"channelId argument is required\";\r\n\r\n return setEndpointFilter(2, filterId, channelId, endpointFilter, propFilter, '', threshold, anchorInfo);\r\n };\r\n\r\n this.setEndpointSPCFilter = function (filterId, endpointId, endpointFilter, propFilter, threshold, anchorInfo) {\r\n return setEndpointFilter(1, filterId, 0, endpointFilter, propFilter, endpointId, threshold, anchorInfo);\r\n };\r\n\r\n this.setEndpointAddressBookFilter = function (filterId, endpointFilter, propFilter, threshold, anchorInfo) {\r\n return setEndpointFilter(3, filterId, 0, endpointFilter, propFilter, '', threshold, anchorInfo);\r\n };\r\n\r\n this.clearEndpointFilter = function (filterId) {\r\n if (!filterId || isNaN(filterId)) throw new Error(\"Invalid argument type for filterId, must be an unsigned integer value\");\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n // Only channel text messages are currently implemented\r\n sendMessage(\"clearEndpointFilter\", pushCallbacks(callbacks.clearEndpointFilterCallbacks, resolve, reject), {\r\n filterId: filterId\r\n });\r\n });\r\n };\r\n\r\n var setEndpointPropertiesFilter = function(type, filter) {\r\n if (type < 1 || type > 6) throw \"setEndpointPropertiesFilter(type, filter) type argument is required\";\r\n\r\n return new Promise(function (resolve, reject) {\r\n\r\n sendMessage(\"setEndpointPropertiesFilter\", pushCallbacks(callbacks.endpointPropFilteringCallbacks, resolve, reject), { type: type, filter: filter });\r\n });\r\n };\r\n\r\n this.setEndpointPropertiesPrivateCallFilter = function (filter) {\r\n return setEndpointPropertiesFilter(1, filter);\r\n };\r\n\r\n this.setEndpointPropertiesTextMessageFilter = function (filter) {\r\n return setEndpointPropertiesFilter(2, filter);\r\n };\r\n\r\n this.setEndpointPropertiesChannelActivityFilter = function (filter) {\r\n return setEndpointPropertiesFilter(3, filter);\r\n };\r\n\r\n this.setEndpointPropertiesPrivateMessageFilter = function (filter) {\r\n return setEndpointPropertiesFilter(4, filter);\r\n };\r\n\r\n this.visualizeAudio = function (canvas) {\r\n audioHandler.visualize(canvas);\r\n };\r\n\r\n this.setVolume = function (volume) {\r\n audioHandler.setVolume(volume);\r\n };\r\n\r\n this.destroy = function () {\r\n if (socketActive)\r\n return this.closeSession();\r\n else return new Promise(function(resolve, reject) {\r\n try {\r\n teardownClient();\r\n } catch (e) {\r\n reject(e);\r\n } finally {\r\n eventDispatcher.events = {};\r\n resolve();\r\n }\r\n });\r\n };\r\n\r\n this.SendMessage = sendMessage;\r\n\r\n init();\r\n\r\n return this;\r\n };\r\n\r\n module.exports = wtcp;\r\n})(global.WtcpJs);","/// \r\nglobal.WtcpJs = global.WtcpJs || {};\r\n\r\nvar util = require('./wtcp.util.js');\r\n\r\n(function(locatorModule) {\r\n\r\n function getNonce() {\r\n return Math.floor(Math.random() * 9999) + 1;\r\n }\r\n\r\n locatorModule.JXON = function(options) {\r\n if (!(this instanceof locatorModule.JXON))\r\n return new locatorModule.JXON(options);\r\n\r\n return this;\r\n };\r\n\r\n /*locatorModule.JXON.prototype = Object.create(locatorModule.WtcpBase.prototype);\r\n locatorModule.JXON.prototype.constructor = locatorModule.JXON;*/\r\n\r\n locatorModule.JXON.prototype.getJXONTree = function(oXMLParent) {\r\n oXMLParent.hasAttributes = oXMLParent.hasAttributes || function() { return false; };\r\n var vResult = /* put here the default value for empty nodes! */ true, nLength = 0, sCollectedTxt = \"\", oAttrib = null;\r\n if (oXMLParent.hasAttributes()) {\r\n vResult = {};\r\n for (nLength; nLength < oXMLParent.attributes.length; nLength++) {\r\n oAttrib = oXMLParent.attributes.item(nLength);\r\n vResult[\"@\" + oAttrib.name.toLowerCase()] = this.parseText(oAttrib.value.trim());\r\n }\r\n }\r\n if (oXMLParent.hasChildNodes()) {\r\n for (var oNode, sProp, vContent, nItem = 0; nItem < oXMLParent.childNodes.length; nItem++) {\r\n oNode = oXMLParent.childNodes.item(nItem);\r\n if (oNode.nodeType === 4) {\r\n sCollectedTxt += oNode.nodeValue;\r\n } /* nodeType is \"CDATASection\" (4) */\r\n else if (oNode.nodeType === 3) {\r\n sCollectedTxt += oNode.nodeValue.trim();\r\n } /* nodeType is \"Text\" (3) */\r\n else if (oNode.nodeType === 1 && !oNode.prefix) { /* nodeType is \"Element\" (1) */\r\n if (nLength === 0) {\r\n vResult = {};\r\n }\r\n sProp = oNode.nodeName.toLowerCase();\r\n vContent = this.getJXONTree(oNode);\r\n if (vResult.hasOwnProperty(sProp)) {\r\n if (vResult[sProp].constructor !== Array) {\r\n vResult[sProp] = [vResult[sProp]];\r\n }\r\n vResult[sProp].push(vContent);\r\n } else {\r\n vResult[sProp] = vContent;\r\n nLength++;\r\n }\r\n }\r\n }\r\n }\r\n if (sCollectedTxt) {\r\n nLength > 0 ? vResult.keyValue = this.parseText(sCollectedTxt) : vResult = this.parseText(sCollectedTxt);\r\n }\r\n /* if (nLength > 0) { Object.freeze(vResult); } */\r\n return vResult;\r\n }\r\n\r\n locatorModule.JXON.prototype.parseText = function(sValue) {\r\n if (/^\\s*$/.test(sValue)) {\r\n return null;\r\n }\r\n if (/^(?:true|false)$/i.test(sValue)) {\r\n return sValue.toLowerCase() === \"true\";\r\n }\r\n if (isFinite(sValue)) {\r\n return parseFloat(sValue);\r\n }\r\n if (isFinite(Date.parse(sValue))) {\r\n return new Date(sValue);\r\n }\r\n return sValue;\r\n };\r\n\r\n locatorModule.Locator = function(options) {\r\n if (!(this instanceof locatorModule.Locator))\r\n return new locatorModule.Locator(options);\r\n\r\n locatorModule.JXON.call(this);\r\n this.proxyServerID = null;\r\n this.proxyIndex = null;\r\n this.address = [];\r\n this.port = [];\r\n this.wsPort = 443;\r\n this.softwareVersionCheckUrl = null;\r\n this.version = 2;\r\n this.controlVersion = 1;\r\n this.httpStatusCode = 200; \r\n\r\n return this;\r\n };\r\n\r\n locatorModule.Locator.prototype = Object.create(locatorModule.JXON.prototype);\r\n locatorModule.Locator.prototype.constructor = locatorModule.Locator;\r\n\r\n locatorModule.Locator.prototype.getProxy = function (proxyurl) {\r\n let _proxyurl = proxyurl;\r\n return this.tryToGetProxy(\r\n `${_proxyurl}/waveapi/proxy_locator.asp?action=getproxy&pc=wtcpJs&ver=3.0.0&requires=WTCPv2&nonce=${getNonce()}`)\r\n .then( result => { \r\n // Due to hardening, we got 403 forbidden response\r\n // we try again with new URL /wave/_locator/proxy_locator.asp with the same parameter \r\n if( result.httpStatusCode == 403) {\r\n return this.tryToGetProxy(\r\n `${_proxyurl}/wave/_locator/proxy_locator.asp?action=getproxy&pc=wtcpJs&ver=3.0.0&requires=WTCPv2&nonce=${getNonce()}`)\r\n .then(result => {return result; });\r\n }\r\n else {\r\n return result; \r\n }\r\n },\r\n error => { \r\n util.wtcpError(\"Error to get proxy\", error);\r\n return Promise.reject(error);\r\n })\r\n .then(result => { return result;},\r\n err => { util.wtcpError(\"Exception at getProxy: \", err); return Promise.reject(err);} );\r\n\r\n }\r\n\r\n locatorModule.Locator.prototype.tryToGetProxy = function (targetUrl) {\r\n let locatorUrl = targetUrl;\r\n var _this = this;\r\n return new Promise(function(resolve, reject) {\r\n var oReq = new XMLHttpRequest();\r\n\r\n util.wtcpInfo(\"TPS Locator | getProxy url: \" , locatorUrl);\r\n\r\n oReq.onload = function(e) {\r\n\r\n _this.httpStatusCode = e.currentTarget.status;\r\n if (e.currentTarget.status === 200) {\r\n var response = _this.getJXONTree(this.responseXML);\r\n if (response.serverresponse[\"@error\"])\r\n util.wtcpError(\"Proxy Locator returned error code \" + response.serverresponse[\"@error\"]);\r\n else {\r\n var proxy = response.serverresponse.proxy;\r\n _this.proxyServerID = proxy[\"@serverid\"];\r\n _this.proxyIndex = proxy[\"@proxyindex\"];\r\n _this.address[0] = proxy[\"@address1\"];\r\n _this.address[1] = proxy[\"@address2\"];\r\n _this.port[0] = proxy[\"@port1\"];\r\n _this.port[1] = proxy[\"@port2\"];\r\n _this.wsPort = proxy[\"@wsport\"];\r\n _this.softwareVersionCheckUrl = proxy[\"@softwareversioncheckurl\"];\r\n _this.version = 2; // TBD: WTCP version number should be added to locator service\r\n _this.controlVersion = 1; // TBD: WTCP-Ctrl OpCode version should be added to locator service\r\n \r\n util.wtcpInfo(\"TPS Locator | proxyIndex: \" + _this.proxyIndex + \", ProxyServerID: \" +\r\n _this.proxyServerID + \", addrss1: \" +\r\n _this.address[0] + \", address2: \" +\r\n _this.address[1] + \", port1: \" +\r\n _this.port[0] + \", port2: \" +\r\n _this.port[1]);\r\n }\r\n } \r\n resolve(_this);\r\n };\r\n\r\n oReq.onerror = function(err) {\r\n if (typeof reject !== \"undefined\" && reject)\r\n reject(err.statusText);\r\n }\r\n\r\n oReq.open(\"get\", locatorUrl, true);\r\n try\r\n {\r\n oReq.send(); \r\n }\r\n catch(ex)\r\n {\r\n reject(\"exception in tryToGetProxy : \"+ ex);\r\n }\r\n \r\n }); \r\n }\r\n\r\n module.exports = locatorModule;\r\n\r\n})(global.WtcpJs);","\"use strict\";\r\n\r\nglobal.WtcpJs = global.WtcpJs || {};\r\n\r\n(function() {\r\n let doc;\r\n let decoder;\r\n let loggingLevels = {\r\n none: 0,\r\n error: 1,\r\n warn: 2,\r\n debug: 3,\r\n info: 4\r\n };\r\n\r\n let baseLogMsg = 'WtcpJs:';\r\n\r\n try {\r\n doc = document;\r\n } catch (e) {\r\n doc = undefined;\r\n }\r\n\r\n var scriptPath = '';\r\n if (doc) {\r\n var scriptEls = doc.getElementsByTagName('script');\r\n var thisScriptEl = scriptEls[scriptEls.length - 1];\r\n var scriptSrc = thisScriptEl.src;\r\n scriptPath = scriptSrc.substr(0, scriptSrc.lastIndexOf('/') + 1);\r\n }\r\n\r\n // Detect Endianness\r\n var littleEndian = (function() {\r\n var buffer = new ArrayBuffer(2);\r\n new DataView(buffer).setInt16(0, 256, true);\r\n return new Int16Array(buffer)[0] === 256;\r\n })();\r\n\r\n //let wtcpLog = Symbol('wtcpLog');\r\n\r\n var WtcpUtil = function() {\r\n\r\n this.logLevel = 0;\r\n\r\n // Public properties\r\n Object.defineProperty(this, \"Path\", { get: function() { return scriptPath; } });\r\n Object.defineProperty(this, \"LittleEndian\", { get: function() { return littleEndian; } });\r\n };\r\n\r\n // default to 'info' - 3. If we don't specify or bad value, get as much info as possible\r\n WtcpUtil.prototype.setLoggingLevel = function (value) {\r\n if (!Number.isInteger(value))\r\n value = value in loggingLevels ? loggingLevels[value] : 4; // default to 'info'\r\n\r\n this.logLevel = value < 0 ? 0 : value > 4 ? 4 : value; // 0 <= logLevel <= 3\r\n }\r\n\r\n function formatLogMsg(fn, msg, args) {\r\n fn.call(console, `${baseLogMsg} ${msg}`, args);\r\n }\r\n\r\n WtcpUtil.prototype.wtcpInfo = function(e, ...args) {\r\n if (this.logLevel >= loggingLevels.info)\r\n formatLogMsg(console.info, e, args);\r\n }\r\n\r\n WtcpUtil.prototype.wtcpDebug = function(e, ...args) {\r\n if(this.logLevel >= loggingLevels.debug)\r\n formatLogMsg(console.debug, e, args);\r\n }\r\n\r\n WtcpUtil.prototype.wtcpWarn = function(e, ...args) {\r\n if (this.logLevel >= loggingLevels.warn)\r\n formatLogMsg(console.warn, e, args);\r\n }\r\n\r\n WtcpUtil.prototype.wtcpError = function(e, ...args) {\r\n if(this.logLevel >= loggingLevels.error)\r\n formatLogMsg(console.error, e, args);\r\n }\r\n\r\n var messages = '';\r\n\r\n WtcpUtil.prototype.debugWindow = function(messageClass, message) {\r\n var date = new Date();\r\n var time = date.getHours() + \":\" + date.getMinutes() + \":\" + date.getSeconds() + \".\" + date.getMilliseconds();\r\n messages += time + \" | \" + messageClass + \": \" + message + \"\\n\";\r\n\r\n //doc.getElementById(\"debugMessageWindow\").innerText = messages;\r\n };\r\n\r\n WtcpUtil.prototype.loadScript = function(filename, callback) {\r\n if (doc !== undefined) {\r\n var scriptElem = doc.createElement('script');\r\n scriptElem.setAttribute(\"type\", \"text/javascript\");\r\n scriptElem.setAttribute(\"src\", filename);\r\n scriptElem.onload = function(e) {\r\n if (callback)\r\n callback.call(this, e);\r\n };\r\n scriptElem.onerror = function(e) {\r\n if (callback)\r\n callback.call(this, e);\r\n }\r\n doc.getElementsByTagName(\"head\")[0].appendChild(scriptElem);\r\n } else {\r\n throw \"Use importScripts from Web Workers, loadScript only works from UI thread\";\r\n }\r\n };\r\n\r\n WtcpUtil.prototype.getScriptPath = function() {\r\n return scriptPath;\r\n };\r\n\r\n WtcpUtil.prototype.byteWriter = function(view, val, length, offset) {\r\n //only use this for tiny, short, or int (length 1, 2, or 4)\r\n //doesn't work for setting negative values\r\n //needs a lot of work, need to switch to using dataview??\r\n var shift;\r\n if (!offset)\r\n offset = 0;\r\n\r\n var n = offset + length;\r\n\r\n for (var x = offset; x < n; x++) {\r\n shift = ((n - (x + 1)) * 8);\r\n if (x === offset)\r\n view[x] = val >>> shift;\r\n else\r\n view[x] = (val >>> shift) ^ (view[x - 1] << 8);\r\n }\r\n };\r\n\r\n WtcpUtil.prototype.stringReader = function(data, position) {\r\n ///Gets the UTF-8 string value from byte stream at specified position\r\n ///\r\n ///Numeric position from beginning of ArrayBuffer to start reading\r\n ///returns {string: 'text', str_terminate: position}\r\n try {\r\n decoder = new TextDecoder(\"utf-8\");\r\n } catch (e) {\r\n //TBD: Works in Chrome, but need to add poly-fill or use existing library if not defined\r\n throw \"browser does not support TextDecoder\";\r\n }\r\n\r\n var i;\r\n var str = \"\";\r\n\r\n try {\r\n\r\n var view = new Uint8Array(data);\r\n\r\n for (i = position; i < view.length; i++) {\r\n if (view[i] === 0)\r\n break;\r\n }\r\n\r\n var strView = new Uint8Array(data, position, i - position);\r\n\r\n str = decoder.decode(strView);\r\n\r\n } catch (exc) {\r\n this.wtcpError(\"Error decoding UTF-8 string\", exc);\r\n }\r\n\r\n return { value: str, position: i };\r\n };\r\n\r\n WtcpUtil.prototype.byteReader = function(view, length, offset) {\r\n ///Retrieve value from byte stream at specified offset and length\r\n ///\r\n ///Number of bytes to read\r\n ///Numeric offset from beginning of ArrayBufferView to start reading\r\n ///returns numeric value\r\n\r\n var n = length + offset;\r\n var val = 0, shift;\r\n for (var x = offset; x < n; x++) {\r\n shift = ((n - (x + 1)) * 8);\r\n val += view[x] << shift;\r\n }\r\n return val;\r\n };\r\n\r\n WtcpUtil.prototype.addBitrange = function(val, valToAdd, bitLength, lshBytes) {\r\n ///Isolates a bit range from value\r\n ///Value to add to\r\n ///Value to add\r\n ///Number of bits to write\r\n ///Byte length of value (1 for INT8, 2 for INT16, etc...)\r\n ///\r\n\r\n if (valToAdd > (Math.pow(2, bitLength) - 1))\r\n throw `value is too great for the bitLength specified: ${valToAdd} > ${(Math.pow(2, bitLength) - 1)} for bitlength ${bitLength}`;\r\n\r\n valToAdd = valToAdd << (lshBytes * 8);\r\n val |= valToAdd;\r\n\r\n return val;\r\n };\r\n\r\n WtcpUtil.prototype.mergeArrayBuffers = function(bufferInfo1, bufferInfo2) {\r\n ///Merge two array buffers\r\n ///{buffer: ArrayBuffer, offset: Int}\r\n ///{buffer: ArrayBuffer, offset: Int}\r\n ///\r\n var ta = new Int8Array(bufferInfo1.buffer, bufferInfo1.offset);\r\n var tb = new Int8Array(bufferInfo2.buffer, bufferInfo2.offset);\r\n var n = new Int8Array(ta.length + tb.length);\r\n n.set(ta);\r\n n.set(tb, (ta.length - bufferInfo1.offset));\r\n\r\n return n.buffer;\r\n };\r\n\r\n /**\r\n * bitwise reader for extracting bit ranges from a TypedArray value\r\n * @param {Number} val - numeric value to extract bit range from \r\n * @param {Number} bitPos - bit position to start reading \r\n * @param {Number} bitLength - total number of bits to read \r\n * @param {Number} numBytes - byte length of value (1 for INT8, 2 for INT16, etc...)\r\n * @returns {Number} \r\n */\r\n WtcpUtil.prototype.bitReader = function(val, bitPos, bitLength, numBytes) {\r\n var totalBits = (numBytes * 8) - 1;\r\n\r\n let n = totalBits;\r\n\r\n while (n > bitPos) {\r\n val = val & ~(1 << n--);\r\n }\r\n val = val >>> (bitPos - bitLength) + 1;\r\n\r\n return val;\r\n };\r\n\r\n WtcpUtil.prototype.parseWtcpHeader = function(offset, data) {\r\n var int8View = new Uint8Array(data, offset, 4);\r\n var h = this.byteReader(int8View, 4, 0);\r\n return {\r\n version: this.bitReader(h, 31, 3, 4) + 1,\r\n type: this.bitReader(h, 28, 3, 4),\r\n sequence: this.bitReader(h, 25, 10, 4),\r\n payloadLength: this.bitReader(h, 15, 16, 4)\r\n };\r\n };\r\n\r\n WtcpUtil.prototype.promiseTimeout = function(ms, promise) {\r\n\r\n // create a promise that rejects in milliseconds\r\n \r\n let timerId; \r\n let timedPromise = new Promise((resolve, reject) => \r\n {\r\n timerId = setTimeout(() => { reject('timeout in ' + ms + ' ms'); }, ms); \r\n }); \r\n\r\n // returns a race between our timeout and the passed in promise\r\n\r\n return Promise.race([timedPromise, promise])\r\n .then( (result) => { clearTimeout(timerId); \r\n return result;\r\n })\r\n .catch((err) => { \r\n console.log(\"ALERT : race exception : \", err)\r\n return err;});\r\n };\r\n\r\n WtcpUtil.prototype.EndpointFlags = function() {\r\n this.Moderator = false;\r\n this.Speaking = false;\r\n this.Typing = false;\r\n this.AudioTxMute = false;\r\n this.TextMute = false;\r\n this.Unavailable = false;\r\n this.Visible = false;\r\n this.AudioRxMute = false;\r\n this.TxSilence = false;\r\n this.RxSilence = false;\r\n this.EmergencyTx = false;\r\n this.Self = false;\r\n this.P2P = false;\r\n this.Gone = false;\r\n\r\n return this;\r\n };\r\n\r\n WtcpJs.EndpointFlags = WtcpUtil.prototype.EndpointFlags;\r\n\r\n module.exports = new WtcpUtil();\r\n})();","/// \r\n/// \r\n\"use strict\";\r\n\r\nglobal.WtcpJs = global.WtcpJs || {};\r\n\r\nvar util = require('./wtcp.util.js');\r\n\r\n(function(wtcp) {\r\n\r\n wtcp.WTCPAudio = function(client, settings) {\r\n\r\n const SMOOTHING = 0.8;\r\n const FFT_SIZE = 2048;\r\n\r\n var _this = this;\r\n var context;\r\n var gainNode;\r\n var visCanvas;\r\n var analyser;\r\n var micStream;\r\n var microphone, scriptNode, biquadFilter, offlineContext;\r\n var channelData;\r\n var sampleRate;\r\n var downsampleBuffer;\r\n var audioSamplesStarted = 0;\r\n var audioSamplesEnded = 0;\r\n var audioEndTime;\r\n var times;\r\n var initStatus = {\r\n status: 'inprogress',\r\n message: 'In Progress'\r\n };\r\n var micEnabled = false;\r\n var sendingAudio = false;\r\n var audioPlaying = false;\r\n var playerActive = settings.audioPlayerActive;\r\n var isVisualizing = false;\r\n var audioQueueTimeout = null;\r\n var audioQueue = [];\r\n var audioQueueBufferLength = 0;\r\n var endAudioSuccess, endAudioFailure;\r\n this.messageHandlers = {};\r\n\r\n this.getStatus = function getStatus() { return initStatus; }\r\n\r\n // Properties\r\n Object.defineProperty(this, \"MicrophoneEnabled\", { get: function() { return micEnabled; } });\r\n Object.defineProperty(this, \"PlayerEnabled\", {\r\n get: function() { return playerActive; },\r\n set: function (isEnabled) {\r\n playerActive = isEnabled;\r\n\r\n if (!(playerActive) && audioQueueTimeout) {\r\n clearTimeout(audioQueueTimeout);\r\n audioQueueTimeout = null;\r\n }\r\n\r\n util.wtcpDebug(`WtcpAudio.PlayerEnabled: audio player is now ${playerActive ? 'on' : 'off'}`);\r\n }\r\n });\r\n\r\n function asFloat(pct) {\r\n return pct < 0 ? 0 : pct >= 100 ? 1 : pct / 100;\r\n }\r\n\r\n /* remove this after some testing\r\n function convertToMono(input) {\r\n var splitter = context.createChannelSplitter(2);\r\n var merger = context.createChannelMerger(2);\r\n\r\n input.connect(splitter);\r\n splitter.connect(merger, 0, 0);\r\n splitter.connect(merger, 0, 1);\r\n return merger;\r\n } */\r\n\r\n function audioBufferSourceNodeEnded(e) {\r\n if (++audioSamplesEnded === audioSamplesStarted) {\r\n audioPlaying = false;\r\n audioSamplesEnded = 0;\r\n audioSamplesStarted = 0;\r\n }\r\n }\r\n\r\n function setGain(val) {\r\n gainNode.gain.value = asFloat(val);\r\n }\r\n\r\n function draw() {\r\n // Draw the time domain chart.\r\n var bufferLength = analyser.frequencyBinCount;\r\n var sliceWidth = visCanvas.width * 1.0 / bufferLength;\r\n var x = 0, v = 0, y = 0;\r\n var drawCtx = visCanvas.getContext('2d');\r\n drawCtx.clearRect(0, 0, visCanvas.width, visCanvas.height);\r\n drawCtx.lineWidth = 2;\r\n drawCtx.strokeStyle = 'white';\r\n drawCtx.beginPath();\r\n\r\n analyser.getByteTimeDomainData(times);\r\n\r\n for (var i = 0; i < bufferLength; i++) {\r\n v = times[i] / 128.0;\r\n y = v * visCanvas.height / 2;\r\n\r\n if (i === 0)\r\n drawCtx.moveTo(x, y);\r\n else\r\n drawCtx.lineTo(x, y);\r\n\r\n x += sliceWidth;\r\n }\r\n\r\n drawCtx.lineTo(visCanvas.width, visCanvas.height / 2);\r\n drawCtx.stroke();\r\n }\r\n\r\n function startAudio(src) {\r\n audioSamplesStarted++;\r\n\r\n src.connect(gainNode);\r\n gainNode.connect(isVisualizing ? analyser : context.destination);\r\n\r\n if (!audioPlaying) {\r\n audioPlaying = true;\r\n //audioEndTime = context.currentTime + .05;\r\n audioEndTime = context.currentTime;\r\n }\r\n src.start(audioEndTime);\r\n audioEndTime += (src.buffer.duration);\r\n\r\n if (isVisualizing)\r\n requestAnimationFrame(draw);\r\n }\r\n\r\n this.playAudio = function(buffer, audioLength) {\r\n if (!playerActive)\r\n return;\r\n\r\n audioQueue.push(buffer);\r\n audioQueueBufferLength += audioLength;\r\n\r\n if (!audioQueueTimeout) {\r\n audioQueueTimeout = setTimeout(function() {\r\n var data = audioQueue;\r\n var len = audioQueueBufferLength;\r\n\r\n audioQueue = [];\r\n audioQueueBufferLength = 0;\r\n\r\n var src = context.createBufferSource();\r\n src.onended = audioBufferSourceNodeEnded;\r\n\r\n var b = data[0];\r\n for (var x = 1; x < data.length; x++) {\r\n b = util.mergeArrayBuffers({ buffer: b, offset: 0 }, { buffer: data[x], offset: 0 });\r\n }\r\n\r\n // Experimental feature - trying to decode Opus. Use if (1) to enable\r\n if (0) {\r\n context.decodeAudioData(buffer, function(data) {\r\n src.buffer = data;\r\n\r\n startAudio(src);\r\n }, function(e) { util.wtcpInfo(\"Error decoding audio\", e); });\r\n } else {\r\n var audioArrayBuffer = context.createBuffer(1, (len / 2), 8000);\r\n audioArrayBuffer.copyToChannel(new Float32Array(b), 0);\r\n src.buffer = audioArrayBuffer;\r\n\r\n util.wtcpDebug(\"Scheduling audio clip: duration = \" + src.buffer.duration + \", Queue depth: \" + data.length + \", buffer length: \" + len);\r\n startAudio(src);\r\n\r\n audioQueueTimeout = null;\r\n }\r\n }, 250);\r\n }\r\n };\r\n\r\n this.sendAudio = function() {\r\n\r\n // scriptProcessorNode's dont work on OfflineAudioContexts in chrome. Its not getting fixed\r\n // because scriptprocessor nodes are going away in favor of Audio Workers, which will work with offlinecontexts\r\n // Will have to use scriptProcessorNode for now\r\n\r\n if (!sendingAudio && typeof context.createMediaStreamSource === \"function\") {\r\n let halting = false;\r\n sendingAudio = true;\r\n\r\n if (micStream) {\r\n\r\n microphone = context.createMediaStreamSource(micStream);\r\n scriptNode = context.createScriptProcessor(settings.processorNodeBufferSize, 1, 1);\r\n biquadFilter = context.createBiquadFilter();\r\n biquadFilter.type = 'lowpass';\r\n biquadFilter.frequency.value = 4000;\r\n biquadFilter.Q.value = 2;\r\n\r\n scriptNode.onaudioprocess = function(e) {\r\n\r\n /* ---------------- OfflineAudioContext method of downsampling audio ---------------------------------------- \r\n // This works but you still get clicking artifacts after every sample\r\n var b, source;\r\n offlineContext = new OfflineAudioContext(1, e.inputBuffer.length / (e.inputBuffer.sampleRate / 8000), 8000);\r\n\r\n offlineContext.oncomplete = function(audioBuffer) {\r\n var buffer = audioBuffer.renderedBuffer.getChannelData(0).buffer;\r\n client.SendMessage(\"processAudio\", 1, {\r\n sampleRate: 8000,\r\n channelData: buffer\r\n }, [buffer]);\r\n };\r\n\r\n downsampleBuffer = offlineContext.createBuffer(1, e.inputBuffer.length, e.inputBuffer.sampleRate);\r\n\r\n b = downsampleBuffer.getChannelData(0);\r\n e.inputBuffer.copyFromChannel(b, 0);\r\n\r\n source = offlineContext.createBufferSource();\r\n source.buffer = downsampleBuffer;\r\n source.connect(offlineContext.destination);\r\n source.start(0);\r\n\r\n offlineContext.startRendering();\r\n\r\n /* ------------------------------------------------------------------------------------------------------------*/\r\n\r\n /* ----------------- Pass audio buffer straight to worker thread where it can be manually down-sampled ------- */\r\n\r\n sampleRate = e.inputBuffer.sampleRate;\r\n channelData = new Float32Array(e.inputBuffer.length);\r\n e.inputBuffer.copyFromChannel(channelData, 0);\r\n\r\n client.SendMessage(\"processAudio\", 1, {\r\n sampleRate: sampleRate,\r\n channelData: channelData.buffer,\r\n flush: !sendingAudio\r\n }, [channelData.buffer]);\r\n\r\n if (!sendingAudio && !halting) {\r\n try {\r\n client.SendMessage(\"endAudio\", 1);\r\n halting = true;\r\n } catch (err) {\r\n endAudioFailure(err);\r\n }\r\n }\r\n /* -------------------------------------------------------------------------------------------------------------*/\r\n }\r\n\r\n microphone.connect(biquadFilter);\r\n biquadFilter.connect(scriptNode);\r\n scriptNode.connect(context.destination);\r\n }\r\n }\r\n };\r\n\r\n this.messageHandlers['audioEnded'] = function() {\r\n microphone.disconnect();\r\n biquadFilter.disconnect();\r\n scriptNode.disconnect();\r\n util.wtcpDebug('audio: audioEnded handled, disconnected microphone and script node');\r\n endAudioSuccess();\r\n };\r\n\r\n this.endAudio = function() {\r\n\r\n return new Promise(function(resolve, reject) {\r\n if (microphone) {\r\n sendingAudio = false;\r\n endAudioSuccess = resolve;\r\n endAudioFailure = reject;\r\n } else {\r\n resolve();\r\n }\r\n });\r\n };\r\n\r\n this.setVolume = function(val) {\r\n setGain(val);\r\n }\r\n\r\n this.visualize = (canvas) => {\r\n times = new Uint8Array(analyser.frequencyBinCount);\r\n visCanvas = canvas;\r\n isVisualizing = true;\r\n };\r\n\r\n var init = function() {\r\n util.setLoggingLevel(settings.loggingLevel);\r\n try {\r\n // Fix up for prefixing\r\n window.AudioContext = window.AudioContext || window.webkitAudioContext;\r\n window.OfflineAudioContext = window.OfflineAudioContext || window.webkitOfflineAudioContext;\r\n context = new AudioContext();\r\n gainNode = context.createGain();\r\n setGain(settings.initialVolume);\r\n analyser = context.createAnalyser();\r\n analyser.minDecibels = -140;\r\n analyser.maxDecibels = 0;\r\n analyser.smoothingTimeConstant = SMOOTHING;\r\n analyser.fftSize = FFT_SIZE;\r\n analyser.connect(context.destination);\r\n } catch (e) {\r\n throw \"Initialization error: \" + e.message;\r\n }\r\n\r\n try {\r\n if (navigator.mediaDevices === undefined) {\r\n util.wtcpError(\"you are not secure running browser.\");\r\n throw \"current DOM is not loaded securely. try to use https instead of http\";\r\n } \r\n if (navigator.mediaDevices.getUserMedia) {\r\n navigator.mediaDevices.getUserMedia({ audio: true })\r\n .then(function(stream) {\r\n micStream = stream;\r\n micEnabled = true;\r\n initStatus = {status: 'ready', message: 'Ready'};\r\n })\r\n .catch(function(err) {\r\n util.wtcpError(\"getUserMedia error\", err);\r\n initStatus = {status: 'error', message: err.message};\r\n });\r\n } else {\r\n navigator.getUserMedia = navigator.getUserMedia ||\r\n navigator.webkitGetUserMedia ||\r\n navigator.mozGetUserMedia ||\r\n navigator.msGetUserMedia;\r\n\r\n navigator.getUserMedia({ audio: true }, function (stream) {\r\n micStream = stream;\r\n micEnabled = true;\r\n initStatus = { status: 'ready', message: 'Ready' };\r\n }, function (err) {\r\n util.wtcpError(\"getUserMedia error: \" + err.message);\r\n initStatus = { status: 'error', message: err.message };\r\n });\r\n } \r\n } catch (e) {\r\n throw \"getUserMedia() is not supported in your browser\";\r\n }\r\n }\r\n\r\n init();\r\n };\r\n\r\n module.exports = wtcp;\r\n})({});","(function () {\n var validator = new RegExp(\"^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$\", \"i\");\n\n function gen(count) {\n var out = \"\";\n for (var i=0; i\n * Licensed under MIT License\n */\n\n(function (window, undefined) {\n\n 'use strict';\n\n //////////////\n // Constants\n /////////////\n\n\n var LIBVERSION = '0.7.28',\n EMPTY = '',\n UNKNOWN = '?',\n FUNC_TYPE = 'function',\n UNDEF_TYPE = 'undefined',\n OBJ_TYPE = 'object',\n STR_TYPE = 'string',\n MAJOR = 'major', // deprecated\n MODEL = 'model',\n NAME = 'name',\n TYPE = 'type',\n VENDOR = 'vendor',\n VERSION = 'version',\n ARCHITECTURE= 'architecture',\n CONSOLE = 'console',\n MOBILE = 'mobile',\n TABLET = 'tablet',\n SMARTTV = 'smarttv',\n WEARABLE = 'wearable',\n EMBEDDED = 'embedded',\n UA_MAX_LENGTH = 255;\n\n\n ///////////\n // Helper\n //////////\n\n\n var util = {\n extend : function (regexes, extensions) {\n var mergedRegexes = {};\n for (var i in regexes) {\n if (extensions[i] && extensions[i].length % 2 === 0) {\n mergedRegexes[i] = extensions[i].concat(regexes[i]);\n } else {\n mergedRegexes[i] = regexes[i];\n }\n }\n return mergedRegexes;\n },\n has : function (str1, str2) {\n return typeof str1 === STR_TYPE ? str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1 : false;\n },\n lowerize : function (str) {\n return str.toLowerCase();\n },\n major : function (version) {\n return typeof(version) === STR_TYPE ? version.replace(/[^\\d\\.]/g,'').split(\".\")[0] : undefined;\n },\n trim : function (str, len) {\n str = str.replace(/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g, '');\n return typeof(len) === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);\n }\n };\n\n\n ///////////////\n // Map helper\n //////////////\n\n\n var mapper = {\n\n rgx : function (ua, arrays) {\n\n var i = 0, j, k, p, q, matches, match;\n\n // loop through all regexes maps\n while (i < arrays.length && !matches) {\n\n var regex = arrays[i], // even sequence (0,2,4,..)\n props = arrays[i + 1]; // odd sequence (1,3,5,..)\n j = k = 0;\n\n // try matching uastring with regexes\n while (j < regex.length && !matches) {\n\n matches = regex[j++].exec(ua);\n\n if (!!matches) {\n for (p = 0; p < props.length; p++) {\n match = matches[++k];\n q = props[p];\n // check if given property is actually array\n if (typeof q === OBJ_TYPE && q.length > 0) {\n if (q.length == 2) {\n if (typeof q[1] == FUNC_TYPE) {\n // assign modified match\n this[q[0]] = q[1].call(this, match);\n } else {\n // assign given value, ignore regex match\n this[q[0]] = q[1];\n }\n } else if (q.length == 3) {\n // check whether function or regex\n if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {\n // call function (usually string mapper)\n this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;\n } else {\n // sanitize match using given regex\n this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;\n }\n } else if (q.length == 4) {\n this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;\n }\n } else {\n this[q] = match ? match : undefined;\n }\n }\n }\n }\n i += 2;\n }\n },\n\n str : function (str, map) {\n\n for (var i in map) {\n // check if array\n if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {\n for (var j = 0; j < map[i].length; j++) {\n if (util.has(map[i][j], str)) {\n return (i === UNKNOWN) ? undefined : i;\n }\n }\n } else if (util.has(map[i], str)) {\n return (i === UNKNOWN) ? undefined : i;\n }\n }\n return str;\n }\n };\n\n\n ///////////////\n // String map\n //////////////\n\n\n var maps = {\n\n browser : {\n // Safari < 3.0\n oldSafari : {\n version : {\n '1.0' : '/8',\n '1.2' : '/1',\n '1.3' : '/3',\n '2.0' : '/412',\n '2.0.2' : '/416',\n '2.0.3' : '/417',\n '2.0.4' : '/419',\n '?' : '/'\n }\n },\n oldEdge : {\n version : {\n '0.1' : '12.',\n '21' : '13.',\n '31' : '14.',\n '39' : '15.',\n '41' : '16.',\n '42' : '17.',\n '44' : '18.'\n }\n }\n },\n\n os : {\n windows : {\n version : {\n 'ME' : '4.90',\n 'NT 3.11' : 'NT3.51',\n 'NT 4.0' : 'NT4.0',\n '2000' : 'NT 5.0',\n 'XP' : ['NT 5.1', 'NT 5.2'],\n 'Vista' : 'NT 6.0',\n '7' : 'NT 6.1',\n '8' : 'NT 6.2',\n '8.1' : 'NT 6.3',\n '10' : ['NT 6.4', 'NT 10.0'],\n 'RT' : 'ARM'\n }\n }\n }\n };\n\n\n //////////////\n // Regex map\n /////////////\n\n\n var regexes = {\n\n browser : [[\n\n /\\b(?:crmo|crios)\\/([\\w\\.]+)/i // Chrome for Android/iOS\n ], [VERSION, [NAME, 'Chrome']], [\n /edg(?:e|ios|a)?\\/([\\w\\.]+)/i // Microsoft Edge\n ], [VERSION, [NAME, 'Edge']], [\n // breaking change (reserved for next major release):\n ///edge\\/([\\w\\.]+)/i // Old Edge (Trident)\n //], [[VERSION, mapper.str, maps.browser.oldEdge.version], [NAME, 'Edge']], [\n\n // Presto based\n /(opera\\smini)\\/([\\w\\.-]+)/i, // Opera Mini\n /(opera\\s[mobiletab]{3,6})\\b.+version\\/([\\w\\.-]+)/i, // Opera Mobi/Tablet\n /(opera)(?:.+version\\/|[\\/\\s]+)([\\w\\.]+)/i, // Opera\n ], [NAME, VERSION], [\n /opios[\\/\\s]+([\\w\\.]+)/i // Opera mini on iphone >= 8.0\n ], [VERSION, [NAME, 'Opera Mini']], [\n /\\sopr\\/([\\w\\.]+)/i // Opera Webkit\n ], [VERSION, [NAME, 'Opera']], [\n\n // Mixed\n /(kindle)\\/([\\w\\.]+)/i, // Kindle\n /(lunascape|maxthon|netfront|jasmine|blazer)[\\/\\s]?([\\w\\.]*)/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer\n // Trident based\n /(avant\\s|iemobile|slim)(?:browser)?[\\/\\s]?([\\w\\.]*)/i, // Avant/IEMobile/SlimBrowser\n /(ba?idubrowser)[\\/\\s]?([\\w\\.]+)/i, // Baidu Browser\n /(?:ms|\\()(ie)\\s([\\w\\.]+)/i, // Internet Explorer\n\n // Webkit/KHTML based\n /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon)\\/([\\w\\.-]+)/i,\n // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon\n /(rekonq|puffin|brave|whale|qqbrowserlite|qq)\\/([\\w\\.]+)/i, // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ, aka ShouQ\n /(weibo)__([\\d\\.]+)/i // Weibo\n ], [NAME, VERSION], [\n /(?:[\\s\\/]uc?\\s?browser|(?:juc.+)ucweb)[\\/\\s]?([\\w\\.]+)/i // UCBrowser\n ], [VERSION, [NAME, 'UCBrowser']], [\n /(?:windowswechat)?\\sqbcore\\/([\\w\\.]+)\\b.*(?:windowswechat)?/i // WeChat Desktop for Windows Built-in Browser\n ], [VERSION, [NAME, 'WeChat(Win) Desktop']], [\n /micromessenger\\/([\\w\\.]+)/i // WeChat\n ], [VERSION, [NAME, 'WeChat']], [\n /konqueror\\/([\\w\\.]+)/i // Konqueror\n ], [VERSION, [NAME, 'Konqueror']], [\n /trident.+rv[:\\s]([\\w\\.]{1,9})\\b.+like\\sgecko/i // IE11\n ], [VERSION, [NAME, 'IE']], [\n /yabrowser\\/([\\w\\.]+)/i // Yandex\n ], [VERSION, [NAME, 'Yandex']], [\n /(avast|avg)\\/([\\w\\.]+)/i // Avast/AVG Secure Browser\n ], [[NAME, /(.+)/, '$1 Secure Browser'], VERSION], [\n /focus\\/([\\w\\.]+)/i // Firefox Focus\n ], [VERSION, [NAME, 'Firefox Focus']], [\n /opt\\/([\\w\\.]+)/i // Opera Touch\n ], [VERSION, [NAME, 'Opera Touch']], [\n /coc_coc_browser\\/([\\w\\.]+)/i // Coc Coc Browser\n ], [VERSION, [NAME, 'Coc Coc']], [\n /dolfin\\/([\\w\\.]+)/i // Dolphin\n ], [VERSION, [NAME, 'Dolphin']], [\n /coast\\/([\\w\\.]+)/i // Opera Coast\n ], [VERSION, [NAME, 'Opera Coast']],\n [/xiaomi\\/miuibrowser\\/([\\w\\.]+)/i // MIUI Browser\n ], [VERSION, [NAME, 'MIUI Browser']], [\n /fxios\\/([\\w\\.-]+)/i // Firefox for iOS\n ], [VERSION, [NAME, 'Firefox']], [\n /(qihu|qhbrowser|qihoobrowser|360browser)/i // 360\n ], [[NAME, '360 Browser']], [\n /(oculus|samsung|sailfish)browser\\/([\\w\\.]+)/i\n ], [[NAME, /(.+)/, '$1 Browser'], VERSION], [ // Oculus/Samsung/Sailfish Browser\n /(comodo_dragon)\\/([\\w\\.]+)/i // Comodo Dragon\n ], [[NAME, /_/g, ' '], VERSION], [\n /\\s(electron)\\/([\\w\\.]+)\\ssafari/i, // Electron-based App\n /(tesla)(?:\\sqtcarbrowser|\\/(20[12]\\d\\.[\\w\\.-]+))/i, // Tesla\n /m?(qqbrowser|baiduboxapp|2345Explorer)[\\/\\s]?([\\w\\.]+)/i // QQBrowser/Baidu App/2345 Browser\n ], [NAME, VERSION], [\n /(MetaSr)[\\/\\s]?([\\w\\.]+)/i, // SouGouBrowser\n /(LBBROWSER)/i // LieBao Browser\n ], [NAME], [\n\n // WebView\n /;fbav\\/([\\w\\.]+);/i // Facebook App for iOS & Android with version\n ], [VERSION, [NAME, 'Facebook']], [\n /FBAN\\/FBIOS|FB_IAB\\/FB4A/i // Facebook App for iOS & Android without version\n ], [[NAME, 'Facebook']], [\n /safari\\s(line)\\/([\\w\\.]+)/i, // Line App for iOS\n /\\b(line)\\/([\\w\\.]+)\\/iab/i, // Line App for Android\n /(chromium|instagram)[\\/\\s]([\\w\\.-]+)/i // Chromium/Instagram\n ], [NAME, VERSION], [\n /\\bgsa\\/([\\w\\.]+)\\s.*safari\\//i // Google Search Appliance on iOS\n ], [VERSION, [NAME, 'GSA']], [\n\n /headlesschrome(?:\\/([\\w\\.]+)|\\s)/i // Chrome Headless\n ], [VERSION, [NAME, 'Chrome Headless']], [\n\n /\\swv\\).+(chrome)\\/([\\w\\.]+)/i // Chrome WebView\n ], [[NAME, 'Chrome WebView'], VERSION], [\n\n /droid.+\\sversion\\/([\\w\\.]+)\\b.+(?:mobile\\ssafari|safari)/i // Android Browser\n ], [VERSION, [NAME, 'Android Browser']], [\n\n /(chrome|omniweb|arora|[tizenoka]{5}\\s?browser)\\/v?([\\w\\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia\n ], [NAME, VERSION], [\n\n /version\\/([\\w\\.]+)\\s.*mobile\\/\\w+\\s(safari)/i // Mobile Safari\n ], [VERSION, [NAME, 'Mobile Safari']], [\n /version\\/([\\w\\.]+)\\s.*(mobile\\s?safari|safari)/i // Safari & Safari Mobile\n ], [VERSION, NAME], [\n /webkit.+?(mobile\\s?safari|safari)(\\/[\\w\\.]+)/i // Safari < 3.0\n ], [NAME, [VERSION, mapper.str, maps.browser.oldSafari.version]], [\n\n /(webkit|khtml)\\/([\\w\\.]+)/i\n ], [NAME, VERSION], [\n\n // Gecko based\n /(navigator|netscape)\\/([\\w\\.-]+)/i // Netscape\n ], [[NAME, 'Netscape'], VERSION], [\n /ile\\svr;\\srv:([\\w\\.]+)\\).+firefox/i // Firefox Reality\n ], [VERSION, [NAME, 'Firefox Reality']], [\n /ekiohf.+(flow)\\/([\\w\\.]+)/i, // Flow\n /(swiftfox)/i, // Swiftfox\n /(icedragon|iceweasel|camino|chimera|fennec|maemo\\sbrowser|minimo|conkeror)[\\/\\s]?([\\w\\.\\+]+)/i,\n // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror\n /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\\/([\\w\\.-]+)$/i,\n // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix\n /(firefox)\\/([\\w\\.]+)\\s[\\w\\s\\-]+\\/[\\w\\.]+$/i, // Other Firefox-based\n /(mozilla)\\/([\\w\\.]+)\\s.+rv\\:.+gecko\\/\\d+/i, // Mozilla\n\n // Other\n /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir)[\\/\\s]?([\\w\\.]+)/i,\n // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir\n /(links)\\s\\(([\\w\\.]+)/i, // Links\n /(gobrowser)\\/?([\\w\\.]*)/i, // GoBrowser\n /(ice\\s?browser)\\/v?([\\w\\._]+)/i, // ICE Browser\n /(mosaic)[\\/\\s]([\\w\\.]+)/i // Mosaic\n ], [NAME, VERSION]\n ],\n\n cpu : [[\n\n /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\\)]/i // AMD64 (x64)\n ], [[ARCHITECTURE, 'amd64']], [\n\n /(ia32(?=;))/i // IA32 (quicktime)\n ], [[ARCHITECTURE, util.lowerize]], [\n\n /((?:i[346]|x)86)[;\\)]/i // IA32 (x86)\n ], [[ARCHITECTURE, 'ia32']], [\n\n /\\b(aarch64|armv?8e?l?)\\b/i // ARM64\n ], [[ARCHITECTURE, 'arm64']], [\n\n /\\b(arm(?:v[67])?ht?n?[fl]p?)\\b/i // ARMHF\n ], [[ARCHITECTURE, 'armhf']], [\n\n // PocketPC mistakenly identified as PowerPC\n /windows\\s(ce|mobile);\\sppc;/i\n ], [[ARCHITECTURE, 'arm']], [\n\n /((?:ppc|powerpc)(?:64)?)(?:\\smac|;|\\))/i // PowerPC\n ], [[ARCHITECTURE, /ower/, '', util.lowerize]], [\n\n /(sun4\\w)[;\\)]/i // SPARC\n ], [[ARCHITECTURE, 'sparc']], [\n\n /((?:avr32|ia64(?=;))|68k(?=\\))|\\barm(?:64|(?=v(?:[1-7]|[5-7]1)l?|;|eabi))|(?=atmel\\s)avr|(?:irix|mips|sparc)(?:64)?\\b|pa-risc)/i\n // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC\n ], [[ARCHITECTURE, util.lowerize]]\n ],\n\n device : [[\n\n //////////////////////////\n // MOBILES & TABLETS\n // Ordered by popularity\n /////////////////////////\n\n // Samsung\n /\\b(sch-i[89]0\\d|shw-m380s|sm-[pt]\\w{2,4}|gt-[pn]\\d{2,4}|sgh-t8[56]9|nexus\\s10)/i\n ], [MODEL, [VENDOR, 'Samsung'], [TYPE, TABLET]], [\n /\\b((?:s[cgp]h|gt|sm)-\\w+|galaxy\\snexus)/i,\n /\\ssamsung[\\s-]([\\w-]+)/i,\n /sec-(sgh\\w+)/i\n ], [MODEL, [VENDOR, 'Samsung'], [TYPE, MOBILE]], [\n\n // Apple\n /\\((ip(?:hone|od)[\\s\\w]*);/i // iPod/iPhone\n ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [\n /\\((ipad);[\\w\\s\\),;-]+apple/i, // iPad\n /applecoremedia\\/[\\w\\.]+\\s\\((ipad)/i,\n /\\b(ipad)\\d\\d?,\\d\\d?[;\\]].+ios/i\n ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [\n\n // Huawei\n /\\b((?:agr|ags[23]|bah2?|sht?)-a?[lw]\\d{2})/i,\n ], [MODEL, [VENDOR, 'Huawei'], [TYPE, TABLET]], [\n /d\\/huawei([\\w\\s-]+)[;\\)]/i,\n /\\b(nexus\\s6p|vog-[at]?l\\d\\d|ane-[at]?l[x\\d]\\d|eml-a?l\\d\\da?|lya-[at]?l\\d[\\dc]|clt-a?l\\d\\di?|ele-l\\d\\d)/i,\n /\\b(\\w{2,4}-[atu][ln][01259][019])[;\\)\\s]/i\n ], [MODEL, [VENDOR, 'Huawei'], [TYPE, MOBILE]], [\n\n // Xiaomi\n /\\b(poco[\\s\\w]+)(?:\\sbuild|\\))/i, // Xiaomi POCO\n /\\b;\\s(\\w+)\\sbuild\\/hm\\1/i, // Xiaomi Hongmi 'numeric' models\n /\\b(hm[\\s\\-_]?note?[\\s_]?(?:\\d\\w)?)\\sbuild/i, // Xiaomi Hongmi\n /\\b(redmi[\\s\\-_]?(?:note|k)?[\\w\\s_]+)(?:\\sbuild|\\))/i, // Xiaomi Redmi\n /\\b(mi[\\s\\-_]?(?:a\\d|one|one[\\s_]plus|note lte)?[\\s_]?(?:\\d?\\w?)[\\s_]?(?:plus)?)\\sbuild/i // Xiaomi Mi\n ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [\n /\\b(mi[\\s\\-_]?(?:pad)(?:[\\w\\s_]+))(?:\\sbuild|\\))/i // Mi Pad tablets\n ],[[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [\n\n // OPPO\n /;\\s(\\w+)\\sbuild.+\\soppo/i,\n /\\s(cph[12]\\d{3}|p(?:af|c[al]|d\\w|e[ar])[mt]\\d0|x9007)\\b/i\n ], [MODEL, [VENDOR, 'OPPO'], [TYPE, MOBILE]], [\n\n // Vivo\n /\\svivo\\s(\\w+)(?:\\sbuild|\\))/i,\n /\\s(v[12]\\d{3}\\w?[at])(?:\\sbuild|;)/i\n ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [\n\n // Realme\n /\\s(rmx[12]\\d{3})(?:\\sbuild|;)/i\n ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [\n\n // Motorola\n /\\s(milestone|droid(?:[2-4x]|\\s(?:bionic|x2|pro|razr))?:?(\\s4g)?)\\b[\\w\\s]+build\\//i,\n /\\smot(?:orola)?[\\s-](\\w*)/i,\n /((?:moto[\\s\\w\\(\\)]+|xt\\d{3,4}|nexus\\s6)(?=\\sbuild|\\)))/i\n ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [\n /\\s(mz60\\d|xoom[\\s2]{0,2})\\sbuild\\//i\n ], [MODEL, [VENDOR, 'Motorola'], [TYPE, TABLET]], [\n\n // LG\n /((?=lg)?[vl]k\\-?\\d{3})\\sbuild|\\s3\\.[\\s\\w;-]{10}lg?-([06cv9]{3,4})/i\n ], [MODEL, [VENDOR, 'LG'], [TYPE, TABLET]], [\n /(lm-?f100[nv]?|nexus\\s[45])/i,\n /lg[e;\\s\\/-]+((?!browser|netcast)\\w+)/i,\n /\\blg(\\-?[\\d\\w]+)\\sbuild/i\n ], [MODEL, [VENDOR, 'LG'], [TYPE, MOBILE]], [\n\n // Lenovo\n /(ideatab[\\w\\-\\s]+)/i,\n /lenovo\\s?(s(?:5000|6000)(?:[\\w-]+)|tab(?:[\\s\\w]+)|yt[\\d\\w-]{6}|tb[\\d\\w-]{6})/i // Lenovo tablets\n ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [\n\n // Nokia\n /(?:maemo|nokia).*(n900|lumia\\s\\d+)/i,\n /nokia[\\s_-]?([\\w\\.-]*)/i\n ], [[MODEL, /_/g, ' '], [VENDOR, 'Nokia'], [TYPE, MOBILE]], [\n\n // Google\n /droid.+;\\s(pixel\\sc)[\\s)]/i // Google Pixel C\n ], [MODEL, [VENDOR, 'Google'], [TYPE, TABLET]], [\n /droid.+;\\s(pixel[\\s\\daxl]{0,6})(?:\\sbuild|\\))/i // Google Pixel\n ], [MODEL, [VENDOR, 'Google'], [TYPE, MOBILE]], [\n\n // Sony\n /droid.+\\s([c-g]\\d{4}|so[-l]\\w+|xq-a\\w[4-7][12])(?=\\sbuild\\/|\\).+chrome\\/(?![1-6]{0,1}\\d\\.))/i\n ], [MODEL, [VENDOR, 'Sony'], [TYPE, MOBILE]], [\n /sony\\stablet\\s[ps]\\sbuild\\//i,\n /(?:sony)?sgp\\w+(?:\\sbuild\\/|\\))/i\n ], [[MODEL, 'Xperia Tablet'], [VENDOR, 'Sony'], [TYPE, TABLET]], [\n\n // OnePlus\n /\\s(kb2005|in20[12]5|be20[12][59])\\b/i,\n /\\ba000(1)\\sbuild/i, // OnePlus\n /\\boneplus\\s(a\\d{4})[\\s)]/i\n ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [\n\n // Amazon\n /(alexa)webm/i,\n /(kf[a-z]{2}wi)(\\sbuild\\/|\\))/i, // Kindle Fire without Silk\n /(kf[a-z]+)(\\sbuild\\/|\\)).+silk\\//i // Kindle Fire HD\n ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [\n /(sd|kf)[0349hijorstuw]+(\\sbuild\\/|\\)).+silk\\//i // Fire Phone\n ], [[MODEL, 'Fire Phone'], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [\n\n // BlackBerry\n /\\((playbook);[\\w\\s\\),;-]+(rim)/i // BlackBerry PlayBook\n ], [MODEL, VENDOR, [TYPE, TABLET]], [\n /((?:bb[a-f]|st[hv])100-\\d)/i,\n /\\(bb10;\\s(\\w+)/i // BlackBerry 10\n ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [\n\n // Asus\n /(?:\\b|asus_)(transfo[prime\\s]{4,10}\\s\\w+|eeepc|slider\\s\\w+|nexus\\s7|padfone|p00[cj])/i\n ], [MODEL, [VENDOR, 'ASUS'], [TYPE, TABLET]], [\n /\\s(z[es]6[027][01][km][ls]|zenfone\\s\\d\\w?)\\b/i\n ], [MODEL, [VENDOR, 'ASUS'], [TYPE, MOBILE]], [\n\n // HTC\n /(nexus\\s9)/i // HTC Nexus 9\n ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [\n /(htc)[;_\\s-]{1,2}([\\w\\s]+(?=\\)|\\sbuild)|\\w+)/i, // HTC\n\n // ZTE\n /(zte)-(\\w*)/i,\n /(alcatel|geeksphone|nexian|panasonic|(?=;\\s)sony)[_\\s-]?([\\w-]*)/i // Alcatel/GeeksPhone/Nexian/Panasonic/Sony\n ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [\n\n // Acer\n /droid[x\\d\\.\\s;]+\\s([ab][1-7]\\-?[0178a]\\d\\d?)/i\n ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [\n\n // Meizu\n /droid.+;\\s(m[1-5]\\snote)\\sbuild/i,\n /\\bmz-([\\w-]{2,})/i\n ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [\n\n // MIXED\n /(blackberry|benq|palm(?=\\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\\s_-]?([\\w-]*)/i,\n // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron\n /(hp)\\s([\\w\\s]+\\w)/i, // HP iPAQ\n /(asus)-?(\\w+)/i, // Asus\n /(microsoft);\\s(lumia[\\s\\w]+)/i, // Microsoft Lumia\n /(lenovo)[_\\s-]?([\\w-]+)/i, // Lenovo\n /linux;.+(jolla);/i, // Jolla\n /droid.+;\\s(oppo)\\s?([\\w\\s]+)\\sbuild/i // OPPO\n ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n\n /(archos)\\s(gamepad2?)/i, // Archos\n /(hp).+(touchpad(?!.+tablet)|tablet)/i, // HP TouchPad\n /(kindle)\\/([\\w\\.]+)/i, // Kindle\n /\\s(nook)[\\w\\s]+build\\/(\\w+)/i, // Nook\n /(dell)\\s(strea[kpr\\s\\d]*[\\dko])/i, // Dell Streak\n /[;\\/]\\s?(le[\\s\\-]+pan)[\\s\\-]+(\\w{1,9})\\sbuild/i, // Le Pan Tablets\n /[;\\/]\\s?(trinity)[\\-\\s]*(t\\d{3})\\sbuild/i, // Trinity Tablets\n /\\b(gigaset)[\\s\\-]+(q\\w{1,9})\\sbuild/i, // Gigaset Tablets\n /\\b(vodafone)\\s([\\w\\s]+)(?:\\)|\\sbuild)/i // Vodafone\n ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n /\\s(surface\\sduo)\\s/i // Surface Duo\n ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, TABLET]], [\n /droid\\s[\\d\\.]+;\\s(fp\\du?)\\sbuild/i\n ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [\n /\\s(u304aa)\\sbuild/i // AT&T\n ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [\n /sie-(\\w*)/i // Siemens\n ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [\n /[;\\/]\\s?(rct\\w+)\\sbuild/i // RCA Tablets\n ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [\n /[;\\/\\s](venue[\\d\\s]{2,7})\\sbuild/i // Dell Venue Tablets\n ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [\n /[;\\/]\\s?(q(?:mv|ta)\\w+)\\sbuild/i // Verizon Tablet\n ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [\n /[;\\/]\\s(?:barnes[&\\s]+noble\\s|bn[rt])([\\w\\s\\+]*)\\sbuild/i // Barnes & Noble Tablet\n ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [\n /[;\\/]\\s(tm\\d{3}\\w+)\\sbuild/i\n ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [\n /;\\s(k88)\\sbuild/i // ZTE K Series Tablet\n ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [\n /;\\s(nx\\d{3}j)\\sbuild/i // ZTE Nubia\n ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [\n /[;\\/]\\s?(gen\\d{3})\\sbuild.*49h/i // Swiss GEN Mobile\n ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [\n /[;\\/]\\s?(zur\\d{3})\\sbuild/i // Swiss ZUR Tablet\n ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [\n /[;\\/]\\s?((zeki)?tb.*\\b)\\sbuild/i // Zeki Tablets\n ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [\n /[;\\/]\\s([yr]\\d{2})\\sbuild/i,\n /[;\\/]\\s(dragon[\\-\\s]+touch\\s|dt)(\\w{5})\\sbuild/i // Dragon Touch Tablet\n ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [\n /[;\\/]\\s?(ns-?\\w{0,9})\\sbuild/i // Insignia Tablets\n ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [\n /[;\\/]\\s?((nxa|Next)-?\\w{0,9})\\sbuild/i // NextBook Tablets\n ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [\n /[;\\/]\\s?(xtreme\\_)?(v(1[045]|2[015]|[3469]0|7[05]))\\sbuild/i\n ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [ // Voice Xtreme Phones\n /[;\\/]\\s?(lvtel\\-)?(v1[12])\\sbuild/i // LvTel Phones\n ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [\n /;\\s(ph-1)\\s/i\n ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [ // Essential PH-1\n /[;\\/]\\s?(v(100md|700na|7011|917g).*\\b)\\sbuild/i // Envizen Tablets\n ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [\n /[;\\/]\\s?(trio[\\s\\w\\-\\.]+)\\sbuild/i // MachSpeed Tablets\n ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [\n /[;\\/]\\s?tu_(1491)\\sbuild/i // Rotor Tablets\n ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [\n /(shield[\\w\\s]+)\\sbuild/i // Nvidia Shield Tablets\n ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, TABLET]], [\n /(sprint)\\s(\\w+)/i // Sprint Phones\n ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n /(kin\\.[onetw]{3})/i // Microsoft Kin\n ], [[MODEL, /\\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [\n /droid\\s[\\d\\.]+;\\s(cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\\)/i // Zebra\n ], [MODEL, [VENDOR, 'Zebra'], [TYPE, TABLET]], [\n /droid\\s[\\d\\.]+;\\s(ec30|ps20|tc[2-8]\\d[kx])\\)/i\n ], [MODEL, [VENDOR, 'Zebra'], [TYPE, MOBILE]], [\n\n ///////////////////\n // CONSOLES\n ///////////////////\n\n /\\s(ouya)\\s/i, // Ouya\n /(nintendo)\\s([wids3utch]+)/i // Nintendo\n ], [VENDOR, MODEL, [TYPE, CONSOLE]], [\n /droid.+;\\s(shield)\\sbuild/i // Nvidia\n ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [\n /(playstation\\s[345portablevi]+)/i // Playstation\n ], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [\n /[\\s\\(;](xbox(?:\\sone)?(?!;\\sxbox))[\\s\\);]/i // Microsoft Xbox\n ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, CONSOLE]], [\n\n ///////////////////\n // SMARTTVS\n ///////////////////\n\n /smart-tv.+(samsung)/i // Samsung\n ], [VENDOR, [TYPE, SMARTTV]], [\n /hbbtv.+maple;(\\d+)/i\n ], [[MODEL, /^/, 'SmartTV'], [VENDOR, 'Samsung'], [TYPE, SMARTTV]], [\n /(?:linux;\\snetcast.+smarttv|lg\\snetcast\\.tv-201\\d)/i, // LG SmartTV\n ], [[VENDOR, 'LG'], [TYPE, SMARTTV]], [\n /(apple)\\s?tv/i // Apple TV\n ], [VENDOR, [MODEL, 'Apple TV'], [TYPE, SMARTTV]], [\n /crkey/i // Google Chromecast\n ], [[MODEL, 'Chromecast'], [VENDOR, 'Google'], [TYPE, SMARTTV]], [\n /droid.+aft([\\w])(\\sbuild\\/|\\))/i // Fire TV\n ], [MODEL, [VENDOR, 'Amazon'], [TYPE, SMARTTV]], [\n /\\(dtv[\\);].+(aquos)/i // Sharp\n ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [\n /hbbtv\\/\\d+\\.\\d+\\.\\d+\\s+\\([\\w\\s]*;\\s*(\\w[^;]*);([^;]*)/i // HbbTV devices\n ], [[VENDOR, util.trim], [MODEL, util.trim], [TYPE, SMARTTV]], [\n /[\\s\\/\\(](android\\s|smart[-\\s]?|opera\\s)tv[;\\)\\s]/i // SmartTV from Unidentified Vendors\n ], [[TYPE, SMARTTV]], [\n\n ///////////////////\n // WEARABLES\n ///////////////////\n\n /((pebble))app\\/[\\d\\.]+\\s/i // Pebble\n ], [VENDOR, MODEL, [TYPE, WEARABLE]], [\n /droid.+;\\s(glass)\\s\\d/i // Google Glass\n ], [MODEL, [VENDOR, 'Google'], [TYPE, WEARABLE]], [\n /droid\\s[\\d\\.]+;\\s(wt63?0{2,3})\\)/i\n ], [MODEL, [VENDOR, 'Zebra'], [TYPE, WEARABLE]], [\n\n ///////////////////\n // EMBEDDED\n ///////////////////\n\n /(tesla)(?:\\sqtcarbrowser|\\/20[12]\\d\\.[\\w\\.-]+)/i // Tesla\n ], [VENDOR, [TYPE, EMBEDDED]], [\n\n ////////////////////\n // MIXED (GENERIC)\n ///////////////////\n\n /droid .+?; ([^;]+?)(?: build|\\) applewebkit).+? mobile safari/i // Android Phones from Unidentified Vendors\n ], [MODEL, [TYPE, MOBILE]], [\n /droid .+?;\\s([^;]+?)(?: build|\\) applewebkit).+?(?! mobile) safari/i // Android Tablets from Unidentified Vendors\n ], [MODEL, [TYPE, TABLET]], [\n /\\s(tablet|tab)[;\\/]/i, // Unidentifiable Tablet\n /\\s(mobile)(?:[;\\/]|\\ssafari)/i // Unidentifiable Mobile\n ], [[TYPE, util.lowerize]], [\n /(android[\\w\\.\\s\\-]{0,9});.+build/i // Generic Android Device\n ], [MODEL, [VENDOR, 'Generic']], [\n /(phone)/i\n ], [[TYPE, MOBILE]]\n ],\n\n engine : [[\n\n /windows.+\\sedge\\/([\\w\\.]+)/i // EdgeHTML\n ], [VERSION, [NAME, 'EdgeHTML']], [\n\n /webkit\\/537\\.36.+chrome\\/(?!27)([\\w\\.]+)/i // Blink\n ], [VERSION, [NAME, 'Blink']], [\n\n /(presto)\\/([\\w\\.]+)/i, // Presto\n /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\\/([\\w\\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna\n /ekioh(flow)\\/([\\w\\.]+)/i, // Flow\n /(khtml|tasman|links)[\\/\\s]\\(?([\\w\\.]+)/i, // KHTML/Tasman/Links\n /(icab)[\\/\\s]([23]\\.[\\d\\.]+)/i // iCab\n ], [NAME, VERSION], [\n\n /rv\\:([\\w\\.]{1,9})\\b.+(gecko)/i // Gecko\n ], [VERSION, NAME]\n ],\n\n os : [[\n\n // Windows\n /microsoft\\s(windows)\\s(vista|xp)/i // Windows (iTunes)\n ], [NAME, VERSION], [\n /(windows)\\snt\\s6\\.2;\\s(arm)/i, // Windows RT\n /(windows\\sphone(?:\\sos)*)[\\s\\/]?([\\d\\.\\s\\w]*)/i, // Windows Phone\n /(windows\\smobile|windows)[\\s\\/]?([ntce\\d\\.\\s]+\\w)(?!.+xbox)/i\n ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [\n /(win(?=3|9|n)|win\\s9x\\s)([nt\\d\\.]+)/i\n ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [\n\n // iOS/macOS\n /ip[honead]{2,4}\\b(?:.*os\\s([\\w]+)\\slike\\smac|;\\sopera)/i, // iOS\n /cfnetwork\\/.+darwin/i\n ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [\n /(mac\\sos\\sx)\\s?([\\w\\s\\.]*)/i,\n /(macintosh|mac(?=_powerpc)\\s)(?!.+haiku)/i // Mac OS\n ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [\n\n // Mobile OSes // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki/Sailfish OS\n /(android|webos|palm\\sos|qnx|bada|rim\\stablet\\sos|meego|sailfish|contiki)[\\/\\s-]?([\\w\\.]*)/i,\n /(blackberry)\\w*\\/([\\w\\.]*)/i, // Blackberry\n /(tizen|kaios)[\\/\\s]([\\w\\.]+)/i, // Tizen/KaiOS\n /\\((series40);/i // Series 40\n ], [NAME, VERSION], [\n /\\(bb(10);/i // BlackBerry 10\n ], [VERSION, [NAME, 'BlackBerry']], [\n /(?:symbian\\s?os|symbos|s60(?=;)|series60)[\\/\\s-]?([\\w\\.]*)/i // Symbian\n ], [VERSION, [NAME, 'Symbian']], [\n /mozilla.+\\(mobile;.+gecko.+firefox/i // Firefox OS\n ], [[NAME, 'Firefox OS']], [\n /web0s;.+rt(tv)/i,\n /\\b(?:hp)?wos(?:browser)?\\/([\\w\\.]+)/i // WebOS\n ], [VERSION, [NAME, 'webOS']], [\n\n // Google Chromecast\n /crkey\\/([\\d\\.]+)/i // Google Chromecast\n ], [VERSION, [NAME, 'Chromecast']], [\n /(cros)\\s[\\w]+\\s([\\w\\.]+\\w)/i // Chromium OS\n ], [[NAME, 'Chromium OS'], VERSION],[\n\n // Console\n /(nintendo|playstation)\\s([wids345portablevuch]+)/i, // Nintendo/Playstation\n /(xbox);\\s+xbox\\s([^\\);]+)/i, // Microsoft Xbox (360, One, X, S, Series X, Series S)\n\n // GNU/Linux based\n /(mint)[\\/\\s\\(\\)]?(\\w*)/i, // Mint\n /(mageia|vectorlinux)[;\\s]/i, // Mageia/VectorLinux\n /(joli|[kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?=\\slinux)|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus|raspbian)(?:\\sgnu\\/linux)?(?:\\slinux)?[\\/\\s-]?(?!chrom|package)([\\w\\.-]*)/i,\n // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware\n // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus\n /(hurd|linux)\\s?([\\w\\.]*)/i, // Hurd/Linux\n /(gnu)\\s?([\\w\\.]*)/i, // GNU\n\n // BSD based\n /\\s([frentopc-]{0,4}bsd|dragonfly)\\s?(?!amd|[ix346]{1,2}86)([\\w\\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly\n /(haiku)\\s(\\w+)/i // Haiku\n ], [NAME, VERSION], [\n\n // Other\n /(sunos)\\s?([\\w\\.\\d]*)/i // Solaris\n ], [[NAME, 'Solaris'], VERSION], [\n /((?:open)?solaris)[\\/\\s-]?([\\w\\.]*)/i, // Solaris\n /(aix)\\s((\\d)(?=\\.|\\)|\\s)[\\w\\.])*/i, // AIX\n /(plan\\s9|minix|beos|os\\/2|amigaos|morphos|risc\\sos|openvms|fuchsia)/i, // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS/Fuchsia\n /(unix)\\s?([\\w\\.]*)/i // UNIX\n ], [NAME, VERSION]\n ]\n };\n\n\n /////////////////\n // Constructor\n ////////////////\n var UAParser = function (ua, extensions) {\n\n if (typeof ua === 'object') {\n extensions = ua;\n ua = undefined;\n }\n\n if (!(this instanceof UAParser)) {\n return new UAParser(ua, extensions).getResult();\n }\n\n var _ua = ua || ((typeof window !== 'undefined' && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY);\n var _rgxmap = extensions ? util.extend(regexes, extensions) : regexes;\n\n this.getBrowser = function () {\n var _browser = { name: undefined, version: undefined };\n mapper.rgx.call(_browser, _ua, _rgxmap.browser);\n _browser.major = util.major(_browser.version); // deprecated\n return _browser;\n };\n this.getCPU = function () {\n var _cpu = { architecture: undefined };\n mapper.rgx.call(_cpu, _ua, _rgxmap.cpu);\n return _cpu;\n };\n this.getDevice = function () {\n var _device = { vendor: undefined, model: undefined, type: undefined };\n mapper.rgx.call(_device, _ua, _rgxmap.device);\n return _device;\n };\n this.getEngine = function () {\n var _engine = { name: undefined, version: undefined };\n mapper.rgx.call(_engine, _ua, _rgxmap.engine);\n return _engine;\n };\n this.getOS = function () {\n var _os = { name: undefined, version: undefined };\n mapper.rgx.call(_os, _ua, _rgxmap.os);\n return _os;\n };\n this.getResult = function () {\n return {\n ua : this.getUA(),\n browser : this.getBrowser(),\n engine : this.getEngine(),\n os : this.getOS(),\n device : this.getDevice(),\n cpu : this.getCPU()\n };\n };\n this.getUA = function () {\n return _ua;\n };\n this.setUA = function (ua) {\n _ua = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? util.trim(ua, UA_MAX_LENGTH) : ua;\n return this;\n };\n this.setUA(_ua);\n return this;\n };\n\n UAParser.VERSION = LIBVERSION;\n UAParser.BROWSER = {\n NAME : NAME,\n MAJOR : MAJOR, // deprecated\n VERSION : VERSION\n };\n UAParser.CPU = {\n ARCHITECTURE : ARCHITECTURE\n };\n UAParser.DEVICE = {\n MODEL : MODEL,\n VENDOR : VENDOR,\n TYPE : TYPE,\n CONSOLE : CONSOLE,\n MOBILE : MOBILE,\n SMARTTV : SMARTTV,\n TABLET : TABLET,\n WEARABLE: WEARABLE,\n EMBEDDED: EMBEDDED\n };\n UAParser.ENGINE = {\n NAME : NAME,\n VERSION : VERSION\n };\n UAParser.OS = {\n NAME : NAME,\n VERSION : VERSION\n };\n\n ///////////\n // Export\n //////////\n\n\n // check js environment\n if (typeof(exports) !== UNDEF_TYPE) {\n // nodejs env\n if (typeof module !== UNDEF_TYPE && module.exports) {\n exports = module.exports = UAParser;\n }\n exports.UAParser = UAParser;\n } else {\n // requirejs env (optional)\n if (typeof(define) === 'function' && define.amd) {\n define(function () {\n return UAParser;\n });\n } else if (typeof window !== 'undefined') {\n // browser env\n window.UAParser = UAParser;\n }\n }\n\n // jQuery/Zepto specific (optional)\n // Note:\n // In AMD env the global scope should be kept clean, but jQuery is an exception.\n // jQuery always exports to global scope, unless jQuery.noConflict(true) is used,\n // and we should catch that.\n var $ = typeof window !== 'undefined' && (window.jQuery || window.Zepto);\n if ($ && !$.ua) {\n var parser = new UAParser();\n $.ua = parser.getResult();\n $.ua.get = function () {\n return parser.getUA();\n };\n $.ua.set = function (uastring) {\n parser.setUA(uastring);\n var result = parser.getResult();\n for (var prop in result) {\n $.ua[prop] = result[prop];\n }\n };\n }\n\n})(typeof window === 'object' ? window : this);\n"],"sourceRoot":"/source/"}