UNPKG

rtcmulticonnection-v3

Version:

RTCMultiConnection is a WebRTC JavaScript wrapper library runs top over RTCPeerConnection API to support all possible peer-to-peer features.

4 lines (3 loc) 119 kB
// Last time updated: 2016-03-14 12:07:07 PM UTC "use strict";!function(){function RTCMultiConnection(roomid,forceOptions){function onUserLeft(remoteUserId){connection.deletePeer(remoteUserId)}function connectSocket(connectCallback){if(socket)return void(connectCallback&&connectCallback(socket));if("undefined"==typeof SocketConnection)if("undefined"!=typeof FirebaseConnection)window.SocketConnection=FirebaseConnection;else{if("undefined"==typeof PubNubConnection)throw"SocketConnection.js seems missed.";window.SocketConnection=PubNubConnection}socket=new SocketConnection(connection,function(s){socket=s,connectCallback&&connectCallback(socket)})}function beforeUnload(shiftModerationControlOnLeave,dontCloseSocket){connection.closeBeforeUnload&&(connection.isInitiator===!0&&connection.dontMakeMeModerator(),connection.peers.getAllParticipants().forEach(function(participant){mPeer.onNegotiationNeeded({userLeft:!0},participant),connection.peers[participant]&&connection.peers[participant].peer&&connection.peers[participant].peer.close(),delete connection.peers[participant]}),dontCloseSocket||connection.closeSocket(),connection.broadcasters=[],connection.isInitiator=!1)}function applyConstraints(stream,mediaConstraints){return stream?(mediaConstraints.audio&&stream.getAudioTracks().forEach(function(track){track.applyConstraints(mediaConstraints.audio)}),void(mediaConstraints.video&&stream.getVideoTracks().forEach(function(track){track.applyConstraints(mediaConstraints.video)}))):void(connection.enableLogs&&console.error("No stream to applyConstraints."))}function replaceTrack(track,remoteUserId,isVideoTrack){return remoteUserId?void mPeer.replaceTrack(track,remoteUserId,isVideoTrack):void connection.peers.getAllParticipants().forEach(function(participant){mPeer.replaceTrack(track,participant,isVideoTrack)})}function setStreamEndHandler(stream,isRemote){isRemote=!!isRemote,stream.alreadySetEndHandler||(stream.alreadySetEndHandler=!0,stream&&stream.addEventListener&&stream.addEventListener("ended",function(){stream.idInstance&&currentUserMediaRequest.remove(stream.idInstance),isRemote||(delete connection.attachStreams[connection.attachStreams.indexOf(stream)],-1===connection.removeStreams.indexOf(stream)&&connection.removeStreams.push(stream),connection.attachStreams=removeNullEntries(connection.attachStreams),connection.removeStreams=removeNullEntries(connection.removeStreams),connection.observers.all());var streamEvent=connection.streamEvents[stream.streamid];streamEvent||(streamEvent={stream:stream,streamid:stream.streamid,type:isRemote?"remote":"local",userid:connection.userid,extra:connection.extra,mediaElement:connection.streamEvents[stream.streamid]?connection.streamEvents[stream.streamid].mediaElement:null}),(streamEvent.userid!==connection.userid||"remote"!==streamEvent.type)&&(connection.onstreamended(streamEvent),delete connection.streamEvents[stream.streamid])},!1))}function keepNextBroadcasterOnServer(){if(connection.isInitiator&&!connection.session.oneway&&!connection.session.broadcast&&"many-to-many"===connection.direction){var firstBroadcaster=connection.broadcasters[0],otherBroadcasters=[];connection.broadcasters.forEach(function(broadcaster){broadcaster!==firstBroadcaster&&otherBroadcasters.push(broadcaster)}),connection.autoCloseEntireSession||connection.shiftModerationControl(firstBroadcaster,otherBroadcasters,!0)}}forceOptions=forceOptions||{};var connection=this;connection.channel=connection.sessionid=(roomid||location.href.replace(/\/|:|#|\?|\$|\^|%|\.|`|~|!|\+|@|\[|\||]|\|*. /g,"").split("\n").join("").split("\r").join(""))+"";var mPeer=new MultiPeers(connection);mPeer.onGettingLocalMedia=function(stream){stream.type="local",setStreamEndHandler(stream),getRMCMediaElement(stream,function(mediaElement){mediaElement.id=stream.streamid,mediaElement.muted=!0,mediaElement.volume=0,-1===connection.attachStreams.indexOf(stream)&&connection.attachStreams.push(stream),"undefined"!=typeof StreamsHandler&&StreamsHandler.setHandlers(stream,!0,connection),connection.streamEvents[stream.streamid]={stream:stream,type:"local",mediaElement:mediaElement,userid:connection.userid,extra:connection.extra,streamid:stream.streamid,blobURL:mediaElement.src||URL.createObjectURL(stream),isAudioMuted:!0},setHarkEvents(connection,connection.streamEvents[stream.streamid]),setMuteHandlers(connection,connection.streamEvents[stream.streamid]),connection.onstream(connection.streamEvents[stream.streamid])},connection),connection.observers.all()},mPeer.onGettingRemoteMedia=function(stream,remoteUserId){stream.type="remote",setStreamEndHandler(stream,"remote-stream"),getRMCMediaElement(stream,function(mediaElement){mediaElement.id=stream.streamid,"undefined"!=typeof StreamsHandler&&StreamsHandler.setHandlers(stream,!1,connection),connection.streamEvents[stream.streamid]={stream:stream,type:"remote",userid:remoteUserId,extra:connection.peers[remoteUserId]?connection.peers[remoteUserId].extra:{},mediaElement:mediaElement,streamid:stream.streamid,blobURL:mediaElement.src||URL.createObjectURL(stream)},setMuteHandlers(connection,connection.streamEvents[stream.streamid]),connection.onstream(connection.streamEvents[stream.streamid])},connection)},mPeer.onRemovingRemoteMedia=function(stream,remoteUserId){var streamEvent=connection.streamEvents[stream.streamid];streamEvent||(streamEvent={stream:stream,type:"remote",userid:remoteUserId,extra:connection.peers[remoteUserId]?connection.peers[remoteUserId].extra:{},streamid:stream.streamid,mediaElement:connection.streamEvents[stream.streamid]?connection.streamEvents[stream.streamid].mediaElement:null}),connection.onstreamended(streamEvent),delete connection.streamEvents[stream.streamid]},mPeer.onNegotiationNeeded=function(message,remoteUserId,callback){connectSocket(function(){socket.emit(connection.socketMessageEvent,"password"in message?message:{remoteUserId:message.remoteUserId||remoteUserId,message:message,sender:connection.userid},callback||function(){})})},mPeer.onUserLeft=onUserLeft,mPeer.disconnectWith=function(remoteUserId,callback){socket&&socket.emit("disconnect-with",remoteUserId,callback||function(){}),connection.deletePeer(remoteUserId)},connection.broadcasters=[],connection.socketOptions={transport:"polling"};var socket;connection.openOrJoin=function(localUserid,password){connection.checkPresence(localUserid,function(isRoomExists,roomid){if("function"==typeof password&&(password(isRoomExists,roomid),password=null),isRoomExists){connection.sessionid=roomid;var localPeerSdpConstraints=!1,remotePeerSdpConstraints=!1,isOneWay=!!connection.session.oneway,isDataOnly=isData(connection.session);remotePeerSdpConstraints={OfferToReceiveAudio:connection.sdpConstraints.mandatory.OfferToReceiveAudio,OfferToReceiveVideo:connection.sdpConstraints.mandatory.OfferToReceiveVideo},localPeerSdpConstraints={OfferToReceiveAudio:isOneWay?!!connection.session.audio:connection.sdpConstraints.mandatory.OfferToReceiveAudio,OfferToReceiveVideo:isOneWay?!!connection.session.video||!!connection.session.screen:connection.sdpConstraints.mandatory.OfferToReceiveVideo};var connectionDescription={remoteUserId:connection.sessionid,message:{newParticipationRequest:!0,isOneWay:isOneWay,isDataOnly:isDataOnly,localPeerSdpConstraints:localPeerSdpConstraints,remotePeerSdpConstraints:remotePeerSdpConstraints},sender:connection.userid,password:password||!1};return void mPeer.onNegotiationNeeded(connectionDescription)}connection.userid;connection.userid=connection.sessionid=localUserid||connection.sessionid,connection.userid+="",socket.emit("changed-uuid",connection.userid),password&&socket.emit("set-password",password),connection.isInitiator=!0,isData(connection.session)||connection.captureUserMedia()})},connection.open=function(localUserid,isPublicModerator){connection.userid;return connection.userid=connection.sessionid=localUserid||connection.sessionid,connection.userid+="",connection.isInitiator=!0,connectSocket(function(){socket.emit("changed-uuid",connection.userid),1==isPublicModerator&&connection.becomePublicModerator()}),isData(connection.session)?void("function"==typeof isPublicModerator&&isPublicModerator()):void connection.captureUserMedia("function"==typeof isPublicModerator?isPublicModerator:null)},connection.becomePublicModerator=function(){connection.isInitiator&&socket.emit("become-a-public-moderator")},connection.dontMakeMeModerator=function(){socket.emit("dont-make-me-moderator")},connection.deletePeer=function(remoteUserId){if(remoteUserId){if(connection.onleave({userid:remoteUserId,extra:connection.peers[remoteUserId]?connection.peers[remoteUserId].extra:{}}),connection.peers[remoteUserId]){connection.peers[remoteUserId].streams.forEach(function(stream){stream.stop()});var peer=connection.peers[remoteUserId].peer;if(peer&&"closed"!==peer.iceConnectionState)try{peer.close()}catch(e){}connection.peers[remoteUserId]&&(connection.peers[remoteUserId].peer=null,delete connection.peers[remoteUserId])}if(-1!==connection.broadcasters.indexOf(remoteUserId)){var newArray=[];connection.broadcasters.forEach(function(broadcaster){broadcaster!==remoteUserId&&newArray.push(broadcaster)}),connection.broadcasters=newArray,keepNextBroadcasterOnServer()}}},connection.rejoin=function(connectionDescription){if(!connection.isInitiator&&connectionDescription&&Object.keys(connectionDescription).length){var extra={};connection.peers[connectionDescription.remoteUserId]&&(extra=connection.peers[connectionDescription.remoteUserId].extra,connection.deletePeer(connectionDescription.remoteUserId)),connectionDescription&&connectionDescription.remoteUserId&&(connection.join(connectionDescription.remoteUserId),connection.onReConnecting({userid:connectionDescription.remoteUserId,extra:extra}))}},connection.join=connection.connect=function(remoteUserId,options){connection.sessionid=(remoteUserId?remoteUserId.sessionid||remoteUserId.remoteUserId||remoteUserId:!1)||connection.sessionid,connection.sessionid+="";var localPeerSdpConstraints=!1,remotePeerSdpConstraints=!1,isOneWay=!1,isDataOnly=!1;if(remoteUserId&&remoteUserId.session||!remoteUserId||"string"==typeof remoteUserId){var session=remoteUserId?remoteUserId.session||connection.session:connection.session;isOneWay=!!session.oneway,isDataOnly=isData(session),remotePeerSdpConstraints={OfferToReceiveAudio:connection.sdpConstraints.mandatory.OfferToReceiveAudio,OfferToReceiveVideo:connection.sdpConstraints.mandatory.OfferToReceiveVideo},localPeerSdpConstraints={OfferToReceiveAudio:isOneWay?!!connection.session.audio:connection.sdpConstraints.mandatory.OfferToReceiveAudio,OfferToReceiveVideo:isOneWay?!!connection.session.video||!!connection.session.screen:connection.sdpConstraints.mandatory.OfferToReceiveVideo}}options=options||{},"undefined"!=typeof options.localPeerSdpConstraints&&(localPeerSdpConstraints=options.localPeerSdpConstraints),"undefined"!=typeof options.remotePeerSdpConstraints&&(remotePeerSdpConstraints=options.remotePeerSdpConstraints),"undefined"!=typeof options.isOneWay&&(isOneWay=options.isOneWay),"undefined"!=typeof options.isDataOnly&&(isDataOnly=options.isDataOnly);var connectionDescription={remoteUserId:connection.sessionid,message:{newParticipationRequest:!0,isOneWay:isOneWay,isDataOnly:isDataOnly,localPeerSdpConstraints:localPeerSdpConstraints,remotePeerSdpConstraints:remotePeerSdpConstraints},sender:connection.userid,password:!1};return connectSocket(function(){connection.peers[connection.sessionid]||mPeer.onNegotiationNeeded(connectionDescription)}),connectionDescription},connection.connectWithAllParticipants=function(remoteUserId){mPeer.onNegotiationNeeded("connectWithAllParticipants",remoteUserId||connection.sessionid)},connection.removeFromBroadcastersList=function(remoteUserId){mPeer.onNegotiationNeeded("removeFromBroadcastersList",remoteUserId||connection.sessionid),connection.peers.getAllParticipants(remoteUserId||connection.sessionid).forEach(function(participant){mPeer.onNegotiationNeeded("dropPeerConnection",participant),connection.deletePeer(participant)}),connection.attachStreams.forEach(function(stream){stream.stop()})},connection.getUserMedia=connection.captureUserMedia=function(callback,session){function invokeGetUserMedia(localMediaConstraints,getUserMedia_callback){var isScreen=!1;localMediaConstraints&&(isScreen=localMediaConstraints.isScreen,delete localMediaConstraints.isScreen),getUserMediaHandler({onGettingLocalMedia:function(stream){return stream.isAudio=stream.isVideo=stream.isScreen=!1,isScreen?stream.isScreen=!0:session.audio&&session.video?stream.isVideo=!0:session.audio&&(stream.isAudio=!0),mPeer.onGettingLocalMedia(stream),getUserMedia_callback?getUserMedia_callback():void(callback&&callback(stream))},onLocalMediaError:function(error,constraints){return mPeer.onLocalMediaError(error,constraints),constraints.audio&&constraints.video&&-1!==(error.name||"").toString().indexOf("DevicesNotFound")?(constraints.video=!1,void invokeGetUserMedia(constraints,getUserMedia_callback)):void(callback&&callback())},localMediaConstraints:localMediaConstraints||{audio:session.audio?connection.mediaConstraints.audio:!1,video:session.video?connection.mediaConstraints.video:!1}})}return connection.observers.all(),session=session||connection.session,connection.dontCaptureUserMedia||isData(session)?void(callback&&callback()):void((session.audio||session.video||session.screen)&&(session.screen?connection.getScreenConstraints(function(error,screen_constraints){if(error)throw error;invokeGetUserMedia({video:screen_constraints,isScreen:!0},session.audio||session.video?invokeGetUserMedia:!1)}):(session.audio||session.video)&&invokeGetUserMedia()))},connection.closeBeforeUnload=!0,window.addEventListener("beforeunload",beforeUnload,!1),connection.userid=getRandomString(),connection.changeUserId=function(newUserId,callback){connection.userid=newUserId||getRandomString(),socket.emit("changed-uuid",connection.userid,callback||function(){})},connection.observers={extra:function(){observeObject(connection.extra,function(changes){socket.emit("extra-data-updated",connection.extra)})},attachStreams:function(){observeObject(connection.attachStreams,function(changes){changes.forEach(function(change){"add"===change.type&&setStreamEndHandler(change.object[change.name]),("remove"===change.type||"delete"===change.type)&&-1===connection.removeStreams.indexOf(change.object[change.name])&&connection.removeStreams.push(change.object[change.name]),connection.attachStreams=removeNullEntries(connection.attachStreams),connection.removeStreams=removeNullEntries(connection.removeStreams),connection.observers.all()})})},all:function(){this.extra(),this.attachStreams(),socket&&socket.emit("extra-data-updated",connection.extra)}},connection.extra={},connection.attachStreams=[],connection.removeStreams=[],connection.observers.all(),connection.session={audio:!0,video:!0},connection.enableFileSharing=!1,connection.bandwidth={screen:512,audio:128,video:512},connection.codecs={audio:"opus",video:"VP9"},connection.processSdp=function(sdp){return isMobileDevice||isFirefox?sdp:(sdp=CodecsHandler.setApplicationSpecificBandwidth(sdp,connection.bandwidth,!!connection.session.screen),sdp=CodecsHandler.setVideoBitrates(sdp,{min:8*connection.bandwidth.video*1024,max:8*connection.bandwidth.video*1024}),sdp=CodecsHandler.setOpusAttributes(sdp,{maxaveragebitrate:8*connection.bandwidth.audio*1024,maxplaybackrate:8*connection.bandwidth.audio*1024,stereo:1,maxptime:3}),"VP9"===connection.codecs.video&&(sdp=CodecsHandler.preferVP9(sdp)),"H264"===connection.codecs.video&&(sdp=CodecsHandler.removeVPX(sdp)),"G722"===connection.codecs.audio&&(sdp=CodecsHandler.removeNonG722(sdp)),sdp)},"undefined"!=typeof CodecsHandler&&(connection.BandwidthHandler=connection.CodecsHandler=CodecsHandler),connection.mediaConstraints={audio:{mandatory:{},optional:[{bandwidth:8*connection.bandwidth.audio*1024||1048576}]},video:{mandatory:{},optional:[{bandwidth:8*connection.bandwidth.audio*1024||1048576},{googLeakyBucket:!0},{facingMode:"user"}]}},isFirefox&&(connection.mediaConstraints={audio:!0,video:!0}),forceOptions.useDefaultDevices||isMobileDevice||DetectRTC.load(function(){var lastAudioDevice,lastVideoDevice;if(DetectRTC.MediaDevices.forEach(function(device){"audioinput"===device.kind&&connection.mediaConstraints.audio!==!1&&(lastAudioDevice=device),"videoinput"===device.kind&&connection.mediaConstraints.video!==!1&&(lastVideoDevice=device)}),lastAudioDevice){if(isFirefox)return void(connection.mediaConstraints.audio!==!0?connection.mediaConstraints.audio.deviceId=lastAudioDevice.id:connection.mediaConstraints.audio={deviceId:lastAudioDevice.id});1==connection.mediaConstraints.audio&&(connection.mediaConstraints.audio={mandatory:{},optional:[]}),connection.mediaConstraints.audio.optional||(connection.mediaConstraints.audio.optional=[]);var optional=[{sourceId:lastAudioDevice.id}];connection.mediaConstraints.audio.optional=optional.concat(connection.mediaConstraints.audio.optional)}if(lastVideoDevice){if(isFirefox)return void(connection.mediaConstraints.video!==!0?connection.mediaConstraints.video.deviceId=lastVideoDevice.id:connection.mediaConstraints.video={deviceId:lastVideoDevice.id});1==connection.mediaConstraints.video&&(connection.mediaConstraints.video={mandatory:{},optional:[]}),connection.mediaConstraints.video.optional||(connection.mediaConstraints.video.optional=[]);var optional=[{sourceId:lastVideoDevice.id}];connection.mediaConstraints.video.optional=optional.concat(connection.mediaConstraints.video.optional)}}),connection.sdpConstraints={mandatory:{OfferToReceiveAudio:!0,OfferToReceiveVideo:!0},optional:[{VoiceActivityDetection:!1}]},connection.optionalArgument={optional:[{DtlsSrtpKeyAgreement:!0},{googImprovedWifiBwe:!0},{googScreencastMinBitrate:300},{googIPv6:!0},{googDscp:!0},{googCpuUnderuseThreshold:55},{googCpuOveruseThreshold:85},{googSuspendBelowMinBitrate:!0},{googCpuOveruseDetection:!0}],mandatory:{}},connection.iceServers=IceServersHandler.getIceServers(connection),connection.candidates={host:!0,stun:!0,turn:!0},connection.iceProtocols={tcp:!0,udp:!0},connection.onopen=function(event){connection.enableLogs&&console.info("Data connection has been opened between you & ",event.userid)},connection.onclose=function(event){connection.enableLogs&&console.warn("Data connection has been closed between you & ",event.userid)},connection.onerror=function(error){connection.enableLogs&&console.error(error.userid,"data-error",error)},connection.onmessage=function(event){connection.enableLogs&&console.debug("data-message",event.userid,event.data)},connection.send=function(data,remoteUserId){connection.peers.send(data,remoteUserId)},connection.close=connection.disconnect=connection.leave=function(){beforeUnload(!1,!0)},connection.closeEntireSession=function(callback){callback=callback||function(){},socket.emit("close-entire-session",function looper(){return connection.getAllParticipants().length?void setTimeout(looper,100):(connection.onEntireSessionClosed({sessionid:connection.sessionid,userid:connection.userid,extra:connection.extra}),void connection.changeUserId(null,function(){connection.close(),callback()}))})},connection.onEntireSessionClosed=function(event){connection.enableLogs&&console.info("Entire session is closed: ",event.sessionid,event.extra)},connection.onstream=function(e){var parentNode=connection.videosContainer;parentNode.insertBefore(e.mediaElement,parentNode.firstChild),isMobileDevice&&setTimeout(function(){e.mediaElement.play()},5e3)},connection.onstreamended=function(e){e.mediaElement||(e.mediaElement=document.getElementById(e.streamid)),e.mediaElement&&e.mediaElement.parentNode&&e.mediaElement.parentNode.removeChild(e.mediaElement)},connection.direction="many-to-many",connection.removeStream=function(streamid){var stream;return connection.attachStreams.forEach(function(localStream){localStream.id===streamid&&(stream=localStream)}),stream?void(-1===connection.removeStreams.indexOf(stream)&&(connection.removeStreams.push(stream),connection.peers.getAllParticipants().forEach(function(participant){mPeer.renegotiatePeer(participant)}))):void console.warn("No such stream exists.",streamid)},connection.addStream=function(session,remoteUserId){function invokeGetUserMedia(localMediaConstraints,callback){getUserMediaHandler({onGettingLocalMedia:function(stream){var videoConstraints=localMediaConstraints?localMediaConstraints.video:connection.mediaConstraints;return videoConstraints&&(videoConstraints.mediaSource||videoConstraints.mozMediaSource?stream.isScreen=!0:videoConstraints.mandatory&&videoConstraints.mandatory.chromeMediaSource&&(stream.isScreen=!0)),stream.isScreen||(stream.isVideo=stream.getVideoTracks().length,stream.isAudio=!stream.isVideo&&stream.getAudioTracks().length),mPeer.onGettingLocalMedia(stream),session.streamCallback&&session.streamCallback(stream),callback?callback():void connection.renegotiate(remoteUserId)},onLocalMediaError:function(error,constraints){return mPeer.onLocalMediaError(error,constraints),constraints.audio&&constraints.video&&-1!==(error.name||"").toString().indexOf("DevicesNotFound")?(constraints.video=!1,void invokeGetUserMedia(constraints,callback)):callback?callback():void connection.renegotiate(remoteUserId)},localMediaConstraints:localMediaConstraints||{audio:session.audio?connection.mediaConstraints.audio:!1,video:session.video?connection.mediaConstraints.video:!1}})}return session.getAudioTracks?(-1===connection.attachStreams.indexOf(session)&&(session.streamid||(session.streamid=session.id),connection.attachStreams.push(session)),void connection.renegotiate(remoteUserId)):isData(session)?void connection.renegotiate(remoteUserId):void((!session.audio||session.video||session.screen)&&(session.screen?connection.getScreenConstraints(function(error,screen_constraints){return error?alert(error):void invokeGetUserMedia({video:screen_constraints},session.audio||session.video?invokeGetUserMedia:!1)}):(session.audio||session.video)&&invokeGetUserMedia()))},connection.applyConstraints=function(mediaConstraints,streamid){if(!MediaStreamTrack||!MediaStreamTrack.prototype.applyConstraints)return void alert("track.applyConstraints is NOT supported in your browser.");if(streamid){return connection.streamEvents[streamid]&&(stream=connection.streamEvents[streamid].stream),void applyConstraints(stream,mediaConstraints)}connection.attachStreams.forEach(function(stream){applyConstraints(stream,mediaConstraints)})},connection.replaceTrack=function(session,remoteUserId,isVideoTrack){function invokeGetUserMedia(localMediaConstraints,callback){getUserMediaHandler({onGettingLocalMedia:function(stream){return mPeer.onGettingLocalMedia(stream),callback?callback():void connection.replaceTrack(stream,remoteUserId,isVideoTrack||session.video||session.screen)},onLocalMediaError:function(error,constraints){return mPeer.onLocalMediaError(error,constraints),constraints.audio&&constraints.video&&-1!==(error.name||"").toString().indexOf("DevicesNotFound")?(constraints.video=!1,void invokeGetUserMedia(constraints,callback)):void(callback&&callback())},localMediaConstraints:localMediaConstraints||{audio:session.audio?connection.mediaConstraints.audio:!1,video:session.video?connection.mediaConstraints.video:!1}})}if(session=session||{},!RTCPeerConnection.prototype.getSenders)return void connection.addStream(session);if(session instanceof MediaStreamTrack)return void replaceTrack(session,remoteUserId,isVideoTrack);if(session instanceof MediaStream)return session.getVideoTracks().length&&replaceTrack(session.getVideoTracks()[0],remoteUserId,!0),void(session.getAudioTracks().length&&replaceTrack(session.getAudioTracks()[0],remoteUserId,!1));if(isData(session))throw"connection.replaceTrack requires audio and/or video and/or screen.";(!session.audio||session.video||session.screen)&&(session.screen?connection.getScreenConstraints(function(error,screen_constraints){return error?alert(error):void invokeGetUserMedia({video:screen_constraints},session.audio||session.video?invokeGetUserMedia:!1)}):(session.audio||session.video)&&invokeGetUserMedia())},connection.resetTrack=function(remoteUsersIds,isVideoTrack){remoteUsersIds||(remoteUsersIds=connection.getAllParticipants()),"string"==typeof remoteUsersIds&&(remoteUsersIds=[remoteUsersIds]),remoteUsersIds.forEach(function(participant){var peer=connection.peers[participant].peer;"undefined"!=typeof isVideoTrack&&isVideoTrack!==!0||!peer.lastVideoTrack||connection.replaceTrack(peer.lastVideoTrack,participant,!0),"undefined"!=typeof isVideoTrack&&isVideoTrack!==!1||!peer.lastAudioTrack||connection.replaceTrack(peer.lastAudioTrack,participant,!1)})},connection.renegotiate=function(remoteUserId){return remoteUserId?void mPeer.renegotiatePeer(remoteUserId):void connection.peers.getAllParticipants().forEach(function(participant){mPeer.renegotiatePeer(participant)})},connection.onMediaError=function(error,constraints){connection.enableLogs&&console.error(error,constraints)},connection.addNewBroadcaster=function(broadcasterId,userPreferences){connection.broadcasters.length&&setTimeout(function(){mPeer.connectNewParticipantWithAllBroadcasters(broadcasterId,userPreferences,connection.broadcasters.join("|-,-|"))},1e4),connection.session.oneway||connection.session.broadcast||"many-to-many"!==connection.direction||-1!==connection.broadcasters.indexOf(broadcasterId)||(connection.broadcasters.push(broadcasterId),keepNextBroadcasterOnServer())},connection.autoCloseEntireSession=!1,connection.filesContainer=connection.videosContainer=document.body||document.documentElement,connection.isInitiator=!1,connection.shareFile=mPeer.shareFile,"undefined"!=typeof FileProgressBarHandler&&FileProgressBarHandler.handle(connection),"undefined"!=typeof TranslationHandler&&TranslationHandler.handle(connection),connection.token=getRandomString,connection.onNewParticipant=function(participantId,userPreferences){connection.acceptParticipationRequest(participantId,userPreferences)},connection.acceptParticipationRequest=function(participantId,userPreferences){userPreferences.successCallback&&(userPreferences.successCallback(),delete userPreferences.successCallback),mPeer.createNewPeer(participantId,userPreferences)},connection.onShiftedModerationControl=function(sender,existingBroadcasters){connection.acceptModerationControl(sender,existingBroadcasters)},connection.acceptModerationControl=function(sender,existingBroadcasters){connection.isInitiator=!0,connection.broadcasters=existingBroadcasters,connection.peers.getAllParticipants().forEach(function(participant){mPeer.onNegotiationNeeded({changedUUID:sender,oldUUID:connection.userid,newUUID:sender},participant)}),connection.userid=sender,socket.emit("changed-uuid",connection.userid)},connection.shiftModerationControl=function(remoteUserId,existingBroadcasters,firedOnLeave){mPeer.onNegotiationNeeded({shiftedModerationControl:!0,broadcasters:existingBroadcasters,firedOnLeave:!!firedOnLeave},remoteUserId)},"undefined"!=typeof StreamsHandler&&(connection.StreamsHandler=StreamsHandler),connection.onleave=function(userid){},connection.invokeSelectFileDialog=function(callback){var selector=new FileSelector;selector.selectSingleFile(callback)},connection.getPublicModerators=function(userIdStartsWith,callback){"function"==typeof userIdStartsWith&&(callback=userIdStartsWith),connectSocket(function(socket){socket.emit("get-public-moderators","string"==typeof userIdStartsWith?userIdStartsWith:"",callback)})},connection.onmute=function(e){e.mediaElement&&("both"===e.muteType||"video"===e.muteType?(e.mediaElement.src=null,e.mediaElement.pause(),e.mediaElement.poster=e.snapshot||"https://cdn.webrtc-experiment.com/images/muted.png"):"audio"===e.muteType&&(e.mediaElement.muted=!0))},connection.onunmute=function(e){e.mediaElement&&("both"===e.unmuteType||"video"===e.unmuteType?(e.mediaElement.poster=null,e.mediaElement.src=URL.createObjectURL(e.stream),e.mediaElement.play()):"audio"===e.unmuteType&&(e.mediaElement.muted=!1))},connection.onExtraDataUpdated=function(event){event.status="online",connection.onUserStatusChanged(event,!0)},connection.onJoinWithPassword=function(remoteUserId){console.warn(remoteUserId,"is password protected. Please join with password.")},connection.onInvalidPassword=function(remoteUserId,oldPassword){console.warn(remoteUserId,"is password protected. Please join with valid password. Your old password",oldPassword,"is wrong.")},connection.onPasswordMaxTriesOver=function(remoteUserId){console.warn(remoteUserId,"is password protected. Your max password tries exceeded the limit.")},connection.getAllParticipants=function(sender){return connection.peers.getAllParticipants(sender)},"undefined"!=typeof StreamsHandler&&(StreamsHandler.onSyncNeeded=function(streamid,action,type){connection.peers.getAllParticipants().forEach(function(participant){mPeer.onNegotiationNeeded({streamid:streamid,action:action,streamSyncNeeded:!0,type:type||"both"},participant)})}),connection.connectSocket=function(callback){connectSocket(callback)},connection.closeSocket=function(){socket&&("undefined"!=typeof socket.disconnect&&socket.disconnect(),socket=null)},connection.getSocket=function(callback){return socket?callback&&callback(socket):connectSocket(callback),socket},connection.getRemoteStreams=mPeer.getRemoteStreams;var skipStreams=["selectFirst","selectAll","forEach"];if(connection.streamEvents={selectFirst:function(options){if(!options){var firstStream;for(var str in connection.streamEvents)-1!==skipStreams.indexOf(str)||firstStream||(firstStream=connection.streamEvents[str]);return firstStream}},selectAll:function(){}},connection.socketURL="/",connection.socketMessageEvent="RTCMultiConnection-Message",connection.socketCustomEvent="RTCMultiConnection-Custom-Message",connection.DetectRTC=DetectRTC,connection.onUserStatusChanged=function(event,dontWriteLogs){connection.enableLogs&&!dontWriteLogs&&console.info(event.userid,event.status)},connection.getUserMediaHandler=getUserMediaHandler,connection.multiPeersHandler=mPeer,connection.enableLogs=!0,connection.setCustomSocketHandler=function(customSocketHandler){"undefined"!=typeof SocketConnection&&(SocketConnection=customSocketHandler)},connection.chunkSize=65e3,connection.maxParticipantsAllowed=1e3,connection.disconnectWith=mPeer.disconnectWith,connection.checkPresence=function(remoteUserId,callback){mPeer.onNegotiationNeeded({detectPresence:!0,userid:(remoteUserId||connection.sessionid)+""},"system",callback)},connection.onReadyForOffer=function(remoteUserId,userPreferences){connection.multiPeersHandler.createNewPeer(remoteUserId,userPreferences)},connection.setUserPreferences=function(userPreferences){return connection.dontAttachStream&&(userPreferences.dontAttachLocalStream=!0),connection.dontGetRemoteStream&&(userPreferences.dontGetRemoteStream=!0),userPreferences},connection.updateExtraData=function(){socket.emit("extra-data-updated",connection.extra)},connection.enableScalableBroadcast=!1,connection.maxRelayLimitPerUser=3,connection.dontCaptureUserMedia=!1,connection.dontAttachStream=!1,connection.dontGetRemoteStream=!1,connection.onReConnecting=function(event){connection.enableLogs&&console.info("ReConnecting with",event.userid,"...")},connection.beforeAddingStream=function(stream){return stream},connection.beforeRemovingStream=function(stream){return stream},"undefined"!=typeof isChromeExtensionAvailable&&(connection.checkIfChromeExtensionAvailable=isChromeExtensionAvailable),"undefined"!=typeof isFirefoxExtensionAvailable&&(connection.checkIfChromeExtensionAvailable=isFirefoxExtensionAvailable),"undefined"!=typeof getChromeExtensionStatus&&(connection.getChromeExtensionStatus=getChromeExtensionStatus),connection.getScreenConstraints=function(callback){getScreenConstraints(function(error,screen_constraints){error||(screen_constraints=connection.modifyScreenConstraints(screen_constraints),callback(error,screen_constraints))})},connection.modifyScreenConstraints=function(screen_constraints){return screen_constraints},connection.onPeerStateChanged=function(state){ connection.enableLogs&&-1!==state.iceConnectionState.search(/closed|failed/gi)&&console.error("Peer connection is closed between you & ",state.userid,state.extra,"state:",state.iceConnectionState)},connection.isOnline=!0,listenEventHandler("online",function(){connection.isOnline=!0}),listenEventHandler("offline",function(){connection.isOnline=!1}),connection.isLowBandwidth=!1,navigator&&navigator.connection&&navigator.connection.type&&(connection.isLowBandwidth=-1!==navigator.connection.type.toString().toLowerCase().search(/wifi|cell/g),connection.isLowBandwidth)){if(connection.bandwidth={audio:30,video:30,screen:30},connection.mediaConstraints.audio&&connection.mediaConstraints.audio.optional.length){var newArray=[];connection.mediaConstraints.audio.optional.forEach(function(opt){"undefined"==typeof opt.bandwidth&&newArray.push(opt)}),connection.mediaConstraints.audio.optional=newArray}if(connection.mediaConstraints.video&&connection.mediaConstraints.video.optional.length){var newArray=[];connection.mediaConstraints.video.optional.forEach(function(opt){"undefined"==typeof opt.bandwidth&&newArray.push(opt)}),connection.mediaConstraints.video.optional=newArray}}connection.getExtraData=function(remoteUserId){if(!remoteUserId)throw"remoteUserId is required.";return connection.peers[remoteUserId]?connection.peers[remoteUserId].extra:{}},forceOptions.autoOpenOrJoin&&connection.openOrJoin(connection.sessionid),connection.onUserIdAlreadyTaken=function(useridAlreadyTaken,yourNewUserId){connection.enableLogs&&console.warn("Userid already taken.",useridAlreadyTaken,"Your new userid:",yourNewUserId)}}function SocketConnection(connection,connectCallback){var parameters="";parameters+="?userid="+connection.userid,parameters+="&msgEvent="+connection.socketMessageEvent,parameters+="&socketCustomEvent="+connection.socketCustomEvent,connection.enableScalableBroadcast&&(parameters+="&enableScalableBroadcast=true",parameters+="&maxRelayLimitPerUser="+(connection.maxRelayLimitPerUser||2));var socket;try{socket=io((connection.socketURL||"/")+parameters)}catch(e){socket=io.connect((connection.socketURL||"/")+parameters,connection.socketOptions)}var mPeer=connection.multiPeersHandler;return socket.on("extra-data-updated",function(remoteUserId,extra){connection.peers[remoteUserId]&&(connection.peers[remoteUserId].extra=extra,connection.onExtraDataUpdated({userid:remoteUserId,extra:extra}))}),socket.on(connection.socketMessageEvent,function(message){if(message.remoteUserId==connection.userid){if(connection.peers[message.sender]&&connection.peers[message.sender].extra!=message.extra&&(connection.peers[message.sender].extra=message.extra,connection.onExtraDataUpdated({userid:message.sender,extra:message.extra})),message.message.streamSyncNeeded&&connection.peers[message.sender]){var stream=connection.streamEvents[message.message.streamid];if(!stream||!stream.stream)return;var action=message.message.action;if("ended"===action||"stream-removed"===action)return void connection.onstreamended(stream);var type="both"!=message.message.type?message.message.type:null;return void stream.stream[action](type)}if("connectWithAllParticipants"===message.message)return-1===connection.broadcasters.indexOf(message.sender)&&connection.broadcasters.push(message.sender),void mPeer.onNegotiationNeeded({allParticipants:connection.getAllParticipants(message.sender)},message.sender);if("removeFromBroadcastersList"===message.message)return void(-1!==connection.broadcasters.indexOf(message.sender)&&(delete connection.broadcasters[connection.broadcasters.indexOf(message.sender)],connection.broadcasters=removeNullEntries(connection.broadcasters)));if("dropPeerConnection"===message.message)return void connection.deletePeer(message.sender);if(message.message.allParticipants)return-1===message.message.allParticipants.indexOf(message.sender)&&message.message.allParticipants.push(message.sender),void message.message.allParticipants.forEach(function(participant){mPeer[connection.peers[participant]?"renegotiatePeer":"createNewPeer"](participant,{localPeerSdpConstraints:{OfferToReceiveAudio:connection.sdpConstraints.mandatory.OfferToReceiveAudio,OfferToReceiveVideo:connection.sdpConstraints.mandatory.OfferToReceiveVideo},remotePeerSdpConstraints:{OfferToReceiveAudio:connection.session.oneway?!!connection.session.audio:connection.sdpConstraints.mandatory.OfferToReceiveAudio,OfferToReceiveVideo:connection.session.oneway?!!connection.session.video||!!connection.session.screen:connection.sdpConstraints.mandatory.OfferToReceiveVideo},isOneWay:!!connection.session.oneway||"one-way"===connection.direction,isDataOnly:isData(connection.session)})});if(message.message.newParticipant){if(message.message.newParticipant==connection.userid)return;if(connection.peers[message.message.newParticipant])return;return void mPeer.createNewPeer(message.message.newParticipant,message.message.userPreferences||{localPeerSdpConstraints:{OfferToReceiveAudio:connection.sdpConstraints.mandatory.OfferToReceiveAudio,OfferToReceiveVideo:connection.sdpConstraints.mandatory.OfferToReceiveVideo},remotePeerSdpConstraints:{OfferToReceiveAudio:connection.session.oneway?!!connection.session.audio:connection.sdpConstraints.mandatory.OfferToReceiveAudio,OfferToReceiveVideo:connection.session.oneway?!!connection.session.video||!!connection.session.screen:connection.sdpConstraints.mandatory.OfferToReceiveVideo},isOneWay:!!connection.session.oneway||"one-way"===connection.direction,isDataOnly:isData(connection.session)})}if((message.message.readyForOffer||message.message.addMeAsBroadcaster)&&connection.addNewBroadcaster(message.sender),message.message.newParticipationRequest&&message.sender!==connection.userid){connection.peers[message.sender]&&connection.deletePeer(message.sender);var userPreferences={extra:message.extra||{},localPeerSdpConstraints:message.message.remotePeerSdpConstraints||{OfferToReceiveAudio:connection.sdpConstraints.mandatory.OfferToReceiveAudio,OfferToReceiveVideo:connection.sdpConstraints.mandatory.OfferToReceiveVideo},remotePeerSdpConstraints:message.message.localPeerSdpConstraints||{OfferToReceiveAudio:connection.session.oneway?!!connection.session.audio:connection.sdpConstraints.mandatory.OfferToReceiveAudio,OfferToReceiveVideo:connection.session.oneway?!!connection.session.video||!!connection.session.screen:connection.sdpConstraints.mandatory.OfferToReceiveVideo},isOneWay:"undefined"!=typeof message.message.isOneWay?message.message.isOneWay:!!connection.session.oneway||"one-way"===connection.direction,isDataOnly:"undefined"!=typeof message.message.isDataOnly?message.message.isDataOnly:isData(connection.session),dontGetRemoteStream:"undefined"!=typeof message.message.isOneWay?message.message.isOneWay:!!connection.session.oneway||"one-way"===connection.direction,dontAttachLocalStream:!!message.message.dontGetRemoteStream,connectionDescription:message,successCallback:function(){("undefined"!=typeof message.message.isOneWay?message.message.isOneWay:!!connection.session.oneway||"one-way"===connection.direction)&&connection.addNewBroadcaster(message.sender,userPreferences),(connection.session.oneway||"one-way"===connection.direction||isData(connection.session))&&connection.addNewBroadcaster(message.sender,userPreferences)}};return void connection.onNewParticipant(message.sender,userPreferences)}return message.message.shiftedModerationControl?void connection.onShiftedModerationControl(message.sender,message.message.broadcasters):(message.message.changedUUID&&connection.peers[message.message.oldUUID]&&(connection.peers[message.message.newUUID]=connection.peers[message.message.oldUUID],delete connection.peers[message.message.oldUUID]),message.message.userLeft?(mPeer.onUserLeft(message.sender),void(message.message.autoCloseEntireSession&&connection.leave())):void mPeer.addNegotiatedMessage(message.message,message.sender))}}),socket.on("user-left",function(userid){onUserLeft(userid),connection.onUserStatusChanged({userid:userid,status:"offline",extra:connection.peers[userid]?connection.peers[userid].extra||{}:{}}),connection.onleave({userid:userid,extra:{}})}),socket.on("connect",function(){connection.enableLogs&&console.info("socket.io connection is opened."),socket.emit("extra-data-updated",connection.extra),connectCallback&&connectCallback(socket)}),socket.on("disconnect",function(){connection.enableLogs&&(console.info("socket.io connection is closed"),console.warn("socket.io reconnecting"))}),socket.on("join-with-password",function(remoteUserId){connection.onJoinWithPassword(remoteUserId)}),socket.on("invalid-password",function(remoteUserId,oldPassword){connection.onInvalidPassword(remoteUserId,oldPassword)}),socket.on("password-max-tries-over",function(remoteUserId){connection.onPasswordMaxTriesOver(remoteUserId)}),socket.on("user-disconnected",function(remoteUserId){remoteUserId!==connection.userid&&(connection.onUserStatusChanged({userid:remoteUserId,status:"offline",extra:connection.peers[remoteUserId]?connection.peers[remoteUserId].extra||{}:{}}),connection.deletePeer(remoteUserId))}),socket.on("user-connected",function(userid){userid!==connection.userid&&connection.onUserStatusChanged({userid:userid,status:"online",extra:connection.peers[userid]?connection.peers[userid].extra||{}:{}})}),socket.on("closed-entire-session",function(sessionid,extra){connection.leave(),connection.onEntireSessionClosed({sessionid:sessionid,userid:sessionid,extra:extra})}),socket.on("userid-already-taken",function(useridAlreadyTaken,yourNewUserId){connection.isInitiator=!1,connection.userid=yourNewUserId,connection.onUserIdAlreadyTaken(useridAlreadyTaken,yourNewUserId)}),socket.on("logs",function(log){connection.enableLogs&&console.debug("server-logs",log)}),socket}function MultiPeers(connection){function initFileBufferReader(){fbr=new FileBufferReader,fbr.onProgress=function(chunk){connection.onFileProgress(chunk)},fbr.onBegin=function(file){connection.onFileStart(file)},fbr.onEnd=function(file){connection.onFileEnd(file)}}var self=this,skipPeers=["getAllParticipants","getLength","selectFirst","streams","send","forEach"];connection.peers={getLength:function(){var numberOfPeers=0;for(var peer in this)-1==skipPeers.indexOf(peer)&&numberOfPeers++;return numberOfPeers},selectFirst:function(){var firstPeer;for(var peer in this)-1==skipPeers.indexOf(peer)&&(firstPeer=this[peer]);return firstPeer},getAllParticipants:function(sender){var allPeers=[];for(var peer in this)-1==skipPeers.indexOf(peer)&&peer!=sender&&allPeers.push(peer);return allPeers},forEach:function(callbcak){this.getAllParticipants().forEach(function(participant){callbcak(connection.peers[participant])})},send:function(data,remoteUserId){var that=this;if(!isNull(data.size)&&!isNull(data.type))return void self.shareFile(data,remoteUserId);if(!("text"===data.type||data instanceof ArrayBuffer||data instanceof DataView))return void TextSender.send({text:data,channel:this,connection:connection,remoteUserId:remoteUserId});if("text"===data.type&&(data=JSON.stringify(data)),remoteUserId){var remoteUser=connection.peers[remoteUserId];if(remoteUser)return void remoteUser.channels.forEach(function(channel){channel.send(data)})}this.getAllParticipants().forEach(function(participant){that[participant].channels.forEach(function(channel){channel.send(data)})})}},this.uuid=connection.userid,this.getLocalConfig=function(remoteSdp,remoteUserId,userPreferences){return userPreferences||(userPreferences={}),{streamsToShare:userPreferences.streamsToShare||{},rtcMultiConnection:connection,connectionDescription:userPreferences.connectionDescription,userid:remoteUserId,localPeerSdpConstraints:userPreferences.localPeerSdpConstraints,remotePeerSdpConstraints:userPreferences.remotePeerSdpConstraints,dontGetRemoteStream:!!userPreferences.dontGetRemoteStream,dontAttachLocalStream:!!userPreferences.dontAttachLocalStream,renegotiatingPeer:!!userPreferences.renegotiatingPeer,peerRef:userPreferences.peerRef,onLocalSdp:function(localSdp){self.onNegotiationNeeded(localSdp,remoteUserId)},onLocalCandidate:function(localCandidate){localCandidate=OnIceCandidateHandler.processCandidates(connection,localCandidate),localCandidate&&self.onNegotiationNeeded(localCandidate,remoteUserId)},remoteSdp:remoteSdp,onDataChannelMessage:function(message){if(!fbr&&connection.enableFileSharing&&initFileBufferReader(),"string"==typeof message||!connection.enableFileSharing)return void self.onDataChannelMessage(message,remoteUserId);var that=this;return message instanceof ArrayBuffer||message instanceof DataView?void fbr.convertToObject(message,function(object){that.onDataChannelMessage(object)}):message.readyForNextChunk?void fbr.getNextChunk(message.uuid,function(nextChunk,isLastChunk){connection.peers[remoteUserId].channels.forEach(function(channel){channel.send(nextChunk)})},remoteUserId):void fbr.addChunk(message,function(promptNextChunk){connection.peers[remoteUserId].peer.channel.send(promptNextChunk)})},onDataChannelError:function(error){self.onDataChannelError(error,remoteUserId)},onDataChannelOpened:function(channel){self.onDataChannelOpened(channel,remoteUserId)},onDataChannelClosed:function(event){self.onDataChannelClosed(event,remoteUserId)},onRemoteStream:function(stream){if(connection.peers[remoteUserId].streams.push(stream),isPluginRTC){var mediaElement=document.createElement("video"),body=connection.videosContainer;return body.insertBefore(mediaElement,body.firstChild),void setTimeout(function(){Plugin.attachMediaStream(mediaElement,stream),self.onGettingRemoteMedia(mediaElement,remoteUserId)},3e3)}self.onGettingRemoteMedia(stream,remoteUserId)},onRemoteStreamRemoved:function(stream){self.onRemovingRemoteMedia(stream,remoteUserId)},onPeerStateChanged:function(states){self.onPeerStateChanged(states),"new"===states.iceConnectionState&&self.onNegotiationStarted(remoteUserId,states),"connected"===states.iceConnectionState&&self.onNegotiationCompleted(remoteUserId,states),-1!==states.iceConnectionState.search(/closed|failed/gi)&&(self.onUserLeft(remoteUserId),self.disconnectWith(remoteUserId))}}},this.createNewPeer=function(remoteUserId,userPreferences){if(!(connection.maxParticipantsAllowed<=connection.getAllParticipants().length)){if(userPreferences=userPreferences||{},!userPreferences.isOneWay&&!userPreferences.isDataOnly)return userPreferences.isOneWay=!0,void this.onNegotiationNeeded({enableMedia:!0,userPreferences:userPreferences},remoteUserId);userPreferences=connection.setUserPreferences(userPreferences,remoteUserId);var localConfig=this.getLocalConfig(null,remoteUserId,userPreferences);connection.peers[remoteUserId]=new PeerInitiator(localConfig)}},this.createAnsweringPeer=function(remoteSdp,remoteUserId,userPreferences){userPreferences=connection.setUserPreferences(userPreferences||{},remoteUserId);var localConfig=this.getLocalConfig(remoteSdp,remoteUserId,userPreferences);connection.peers[remoteUserId]=new PeerInitiator(localConfig)},this.renegotiatePeer=function(remoteUserId,userPreferences,remoteSdp){if(!connection.peers[remoteUserId])return void(connection.enableLogs&&console.error("This peer ("+remoteUserId+") does not exists. Renegotiation skipped."));userPreferences||(userPreferences={}),userPreferences.renegotiatingPeer=!0,userPreferences.peerRef=connection.peers[remoteUserId].peer;var localConfig=this.getLocalConfig(remoteSdp,remoteUserId,userPreferences);connection.peers[remoteUserId]=new PeerInitiator(localConfig)},this.replaceTrack=function(track,remoteUserId,isVideoTrack){if(!connection.peers[remoteUserId])throw"This peer ("+remoteUserId+") does not exists.";var peer=connection.peers[remoteUserId].peer;return peer.getSenders&&"function"==typeof peer.getSenders&&peer.getSenders().length?void peer.getSenders().forEach(function(rtpSender){isVideoTrack&&rtpSender.track instanceof VideoStreamTrack&&(connection.peers[remoteUserId].peer.lastVideoTrack=rtpSender.track,rtpSender.replaceTrack(track)),!isVideoTrack&&rtpSender.track instanceof AudioStreamTrack&&(connection.peers[remoteUserId].peer.lastAudioTrack=rtpSender.track,rtpSender.replaceTrack(track))}):(console.warn("RTPSender.replaceTrack is NOT supported."),void this.renegotiatePeer(remoteUserId))},this.onNegotiationNeeded=function(message,remoteUserId){},this.addNegotiatedMessage=function(message,remoteUserId){function invokeGetUserMedia(mediaConstraints){getUserMediaHandler({onGettingLocalMedia:function(localStream){self.onGettingLocalMedia(localStream);var streamsToShare={};connection.attachStreams.forEach(function(stream){streamsToShare[stream.streamid]={isAudio:!!stream.isAudio,isVideo:!!stream.isVideo,isScreen:!!stream.isScreen}}),message.userPreferences.streamsToShare=streamsToShare,self.onNegotiationNeeded({readyForOffer:!0,userPreferences:message.userPreferences},remoteUserId)},onLocalMediaError:function(error,constraints){return self.onLocalMediaError(error,constraints),constraints.audio&&constraints.video&&-1!==(error.name||"").toString().indexOf("DevicesNotFound")?(constraints.video=!1,void invokeGetUserMedia(constraints)):void self.onNegotiationNeeded({readyForOffer:!0,userPreferences:message.userPreferences},remoteUserId)},localMediaConstraints:mediaConstraints})}if(message.type&&message.sdp)return"answer"==message.type&&connection.peers[remoteUserId]&&connection.peers[remoteUserId].addRemoteSdp(message),"offer"==message.type&&(message.renegotiatingPeer?this.renegotiatePeer(remoteUserId,null,message):this.createAnsweringPeer(message,remoteUserId)),void(connection.enableLogs&&console.log("Remote peer's sdp:",message.sdp));if(message.candidate)return connection.peers[remoteUserId]&&connection.peers[remoteUserId].addRemoteCandidate(message),void(connection.enableLogs&&console.log("Remote peer's candidate pairs:",message.candidate));if(message.enableMedia){if(connection.attachStreams.length||connection.dontCaptureUserMedia){var streamsToShare={};return connection.attachStreams.for