2017-03-21 15:30:51 +00:00
2019-06-03 17:00:33 +00:00
( function ( $ ) { function findLine ( sdpLines , prefix , substr ) { return findLineInRange ( sdpLines , 0 , - 1 , prefix , substr ) ; }
function findLineInRange ( sdpLines , startLine , endLine , prefix , substr ) { var realEndLine = ( endLine != - 1 ) ? endLine : sdpLines . length ; for ( var i = startLine ; i < realEndLine ; ++ i ) { if ( sdpLines [ i ] . indexOf ( prefix ) === 0 ) { if ( ! substr || sdpLines [ i ] . toLowerCase ( ) . indexOf ( substr . toLowerCase ( ) ) !== - 1 ) { return i ; } } }
return null ; }
function getCodecPayloadType ( sdpLine ) { var pattern = new RegExp ( 'a=rtpmap:(\\d+) \\w+\\/\\d+' ) ; var result = sdpLine . match ( pattern ) ; return ( result && result . length == 2 ) ? result [ 1 ] : null ; }
function setDefaultCodec ( mLine , payload ) { var elements = mLine . split ( ' ' ) ; var newLine = [ ] ; var index = 0 ; for ( var i = 0 ; i < elements . length ; i ++ ) { if ( index === 3 ) { newLine [ index ++ ] = payload ; }
if ( elements [ i ] !== payload ) newLine [ index ++ ] = elements [ i ] ; }
return newLine . join ( ' ' ) ; }
$ . FSRTC = function ( options ) { this . options = $ . extend ( { useVideo : null , useStereo : false , userData : null , localVideo : null , screenShare : false , useCamera : "any" , iceServers : false , videoParams : { } , audioParams : { } , callbacks : { onICEComplete : function ( ) { } , onICE : function ( ) { } , onOfferSDP : function ( ) { } } , useStream : null , } , options ) ; this . audioEnabled = true ; this . videoEnabled = true ; this . mediaData = { SDP : null , profile : { } , candidateList : [ ] } ; this . constraints = { offerToReceiveAudio : this . options . useSpeak === "none" ? false : true , offerToReceiveVideo : this . options . useVideo ? true : false , } ; if ( self . options . useVideo ) { self . options . useVideo . style . display = 'none' ; }
setCompat ( ) ; checkCompat ( ) ; } ; $ . FSRTC . validRes = [ ] ; $ . FSRTC . prototype . useVideo = function ( obj , local ) { var self = this ; if ( obj ) { self . options . useVideo = obj ; self . options . localVideo = local ; self . constraints . offerToReceiveVideo = true ; } else { self . options . useVideo = null ; self . options . localVideo = null ; self . constraints . offerToReceiveVideo = false ; }
if ( self . options . useVideo ) { self . options . useVideo . style . display = 'none' ; } } ; $ . FSRTC . prototype . useStereo = function ( on ) { var self = this ; self . options . useStereo = on ; } ; $ . FSRTC . prototype . stereoHack = function ( sdp ) { var self = this ; if ( ! self . options . useStereo ) { return sdp ; }
var sdpLines = sdp . split ( '\r\n' ) ; var opusIndex = findLine ( sdpLines , 'a=rtpmap' , 'opus/48000' ) , opusPayload ; if ( ! opusIndex ) { return sdp ; } else { opusPayload = getCodecPayloadType ( sdpLines [ opusIndex ] ) ; }
var fmtpLineIndex = findLine ( sdpLines , 'a=fmtp:' + opusPayload . toString ( ) ) ; if ( fmtpLineIndex === null ) { sdpLines [ opusIndex ] = sdpLines [ opusIndex ] + '\r\na=fmtp:' + opusPayload . toString ( ) + " stereo=1; sprop-stereo=1" } else { sdpLines [ fmtpLineIndex ] = sdpLines [ fmtpLineIndex ] . concat ( '; stereo=1; sprop-stereo=1' ) ; }
sdp = sdpLines . join ( '\r\n' ) ; return sdp ; } ; function setCompat ( ) { }
function checkCompat ( ) { return true ; }
function onStreamError ( self , e ) { console . log ( 'There has been a problem retrieving the streams - did you allow access? Check Device Resolution' , e ) ; doCallback ( self , "onError" , e ) ; }
function onStreamSuccess ( self , stream ) { console . log ( "Stream Success" ) ; doCallback ( self , "onStream" , stream ) ; }
function onRemoteStreamSuccess ( self , stream ) { console . log ( "Remote Stream Success" ) ; doCallback ( self , "onRemoteStream" , stream ) ; }
function onICE ( self , candidate ) { self . mediaData . candidate = candidate ; self . mediaData . candidateList . push ( self . mediaData . candidate ) ; doCallback ( self , "onICE" ) ; }
function doCallback ( self , func , arg ) { if ( func in self . options . callbacks ) { self . options . callbacks [ func ] ( self , arg ) ; } }
function onICEComplete ( self , candidate ) { console . log ( "ICE Complete" ) ; doCallback ( self , "onICEComplete" ) ; }
function onChannelError ( self , e ) { console . error ( "Channel Error" , e ) ; doCallback ( self , "onError" , e ) ; }
function onICESDP ( self , sdp ) { self . mediaData . SDP = self . stereoHack ( sdp . sdp ) ; console . log ( "ICE SDP" ) ; doCallback ( self , "onICESDP" ) ; }
function onAnswerSDP ( self , sdp ) { self . answer . SDP = self . stereoHack ( sdp . sdp ) ; console . log ( "ICE ANSWER SDP" ) ; doCallback ( self , "onAnswerSDP" , self . answer . SDP ) ; }
function onMessage ( self , msg ) { console . log ( "Message" ) ; doCallback ( self , "onICESDP" , msg ) ; }
FSRTCattachMediaStream = function ( element , stream ) { if ( typeof element . srcObject !== 'undefined' ) { element . srcObject = stream ; } else { console . error ( 'Error attaching stream to element.' ) ; } }
function onRemoteStream ( self , stream ) { if ( self . options . useVideo ) { self . options . useVideo . style . display = 'block' ; var iOS = [ 'iPad' , 'iPhone' , 'iPod' ] . indexOf ( navigator . platform ) >= 0 ; if ( iOS ) { self . options . useVideo . setAttribute ( "playsinline" , true ) ; } }
var element = self . options . useAudio ; console . log ( "REMOTE STREAM" , stream , element ) ; FSRTCattachMediaStream ( element , stream ) ; self . remoteStream = stream ; onRemoteStreamSuccess ( self , stream ) ; }
function onOfferSDP ( self , sdp ) { self . mediaData . SDP = self . stereoHack ( sdp . sdp ) ; console . log ( "Offer SDP" ) ; doCallback ( self , "onOfferSDP" ) ; }
$ . FSRTC . prototype . answer = function ( sdp , onSuccess , onError ) { this . peer . addAnswerSDP ( { type : "answer" , sdp : sdp } , onSuccess , onError ) ; } ; $ . FSRTC . prototype . stopPeer = function ( ) { if ( self . peer ) { console . log ( "stopping peer" ) ; self . peer . stop ( ) ; } }
$ . FSRTC . prototype . stop = function ( ) { var self = this ; if ( self . options . useVideo ) { self . options . useVideo . style . display = 'none' ; self . options . useVideo [ 'src' ] = '' ; }
2019-07-25 19:48:25 +00:00
if ( self . localStream && ! self . options . useStream ) { var tracks = self . localStream . getTracks ( ) ; console . log ( "Stopping localStream tracks:" , tracks ) ; tracks . forEach ( function ( track ) { track . stop ( ) } )
2019-06-03 17:00:33 +00:00
self . localStream = null ; }
if ( self . options . localVideo ) { deactivateLocalVideo ( self . options . localVideo ) ; }
2019-07-25 19:48:25 +00:00
if ( self . options . localVideoStream && ! self . options . useStream ) { var tracks = self . options . localVideoStream . getTracks ( ) ; console . log ( "Stopping localVideoStream tracks:" , tracks ) ; tracks . forEach ( function ( track ) { track . stop ( ) } ) }
2019-06-03 17:00:33 +00:00
if ( self . peer ) { console . log ( "stopping peer" ) ; self . peer . stop ( ) ; } } ; $ . FSRTC . prototype . getMute = function ( ) { var self = this ; return self . audioEnabled ; }
$ . FSRTC . prototype . setMute = function ( what ) { var self = this ; if ( ! self . localStream ) { return false ; }
var audioTracks = self . localStream . getAudioTracks ( ) ; for ( var i = 0 , len = audioTracks . length ; i < len ; i ++ ) { switch ( what ) { case "on" : audioTracks [ i ] . enabled = true ; break ; case "off" : audioTracks [ i ] . enabled = false ; break ; case "toggle" : audioTracks [ i ] . enabled = ! audioTracks [ i ] . enabled ; default : break ; }
self . audioEnabled = audioTracks [ i ] . enabled ; }
return ! self . audioEnabled ; }
$ . FSRTC . prototype . getVideoMute = function ( ) { var self = this ; return self . videoEnabled ; }
$ . FSRTC . prototype . setVideoMute = function ( what ) { var self = this ; if ( ! self . localStream ) { return false ; }
var videoTracks = self . localStream . getVideoTracks ( ) ; for ( var i = 0 , len = videoTracks . length ; i < len ; i ++ ) { switch ( what ) { case "on" : videoTracks [ i ] . enabled = true ; break ; case "off" : videoTracks [ i ] . enabled = false ; break ; case "toggle" : videoTracks [ i ] . enabled = ! videoTracks [ i ] . enabled ; default : break ; }
self . videoEnabled = videoTracks [ i ] . enabled ; }
return ! self . videoEnabled ; }
$ . FSRTC . prototype . createAnswer = function ( params ) { var self = this ; self . type = "answer" ; self . remoteSDP = params . sdp ; console . debug ( "inbound sdp: " , params . sdp ) ; function onSuccess ( stream ) { self . localStream = stream ; self . peer = FSRTCPeerConnection ( { type : self . type , attachStream : self . localStream , onICE : function ( candidate ) { return onICE ( self , candidate ) ; } , onICEComplete : function ( ) { return onICEComplete ( self ) ; } , onRemoteStream : function ( stream ) { return onRemoteStream ( self , stream ) ; } , onICESDP : function ( sdp ) { return onICESDP ( self , sdp ) ; } , onChannelError : function ( e ) { return onChannelError ( self , e ) ; } , constraints : self . constraints , iceServers : self . options . iceServers , offerSDP : { type : "offer" , sdp : self . remoteSDP } , turnServer : self . options . turnServer } ) ; onStreamSuccess ( self , stream ) ; }
function onError ( e ) { onStreamError ( self , e ) ; }
var mediaParams = getMediaParams ( self ) ; console . log ( "Audio constraints" , mediaParams . audio ) ; console . log ( "Video constraints" , mediaParams . video ) ; if ( self . options . useVideo && self . options . localVideo && ! self . options . useStream ) { getUserMedia ( { constraints : { audio : false , video : { deviceId : params . useCamera } , } , localVideo : self . options . localVideo , useCameraLabel : self . options . useCameraLabel , useMicLabel : self . options . useMicLabel , onsuccess : function ( e ) { self . options . localVideoStream = e ; console . log ( "local video ready" ) ; } , onerror : function ( e ) { console . error ( "local video error!" , e ) ; } } ) ; }
if ( self . options . useStream ) { if ( self . options . useVideo ) { self . options . localVideoStream = self . options . useStream ; if ( self . options . localVideo ) { activateLocalVideo ( self . options . localVideo , self . options . useStream ) ; } }
onSuccess ( self . options . useStream ) ; }
else { getUserMedia ( { constraints : { audio : mediaParams . audio , video : mediaParams . video } , video : mediaParams . useVideo , useCameraLabel : self . options . useCameraLabel , useMicLabel : self . options . useMicLabel , onsuccess : onSuccess , onerror : onError } ) ; } } ; function getMediaParams ( obj ) { var audio ; if ( obj . options . useMic && obj . options . useMic === "none" ) { console . log ( "Microphone Disabled" ) ; audio = false ; } else if ( obj . options . videoParams && obj . options . screenShare ) { console . error ( "SCREEN SHARE" , obj . options . videoParams ) ; audio = false ; } else { audio = { } ; if ( obj . options . audioParams ) { audio = obj . options . audioParams ; }
if ( obj . options . useMic !== "any" ) { audio . deviceId = assignMediaIdToConstraint ( obj . options . useMic ) ; } }
if ( obj . options . useVideo && obj . options . localVideo && ! obj . options . useStream ) { getUserMedia ( { constraints : { audio : false , video : { deviceId : obj . options . useCamera } , } , localVideo : obj . options . localVideo , useCameraLabel : obj . options . useCameraLabel , useMicLabel : obj . options . useMicLabel , onsuccess : function ( e ) { obj . options . localVideoStream = e ; console . log ( "local video ready" ) ; } , onerror : function ( e ) { console . error ( "local video error!" , e ) ; } } ) ; }
var video = { } ; var bestFrameRate = obj . options . videoParams . vertoBestFrameRate ; var minFrameRate = obj . options . videoParams . minFrameRate || 15 ; delete obj . options . videoParams . vertoBestFrameRate ; if ( obj . options . screenShare ) { if ( ! obj . options . useCamera && ! ! navigator . mozGetUserMedia ) { var dowin = window . confirm ( "Do you want to share an application window? If not you can share an entire screen." ) ; video = { width : { min : obj . options . videoParams . minWidth , max : obj . options . videoParams . maxWidth } , height : { min : obj . options . videoParams . minHeight , max : obj . options . videoParams . maxHeight } , mediaSource : dowin ? "window" : "screen" } } else { var opt = [ ] ; if ( obj . options . useCamera ) { opt . push ( { sourceId : obj . options . useCamera } ) ; }
if ( bestFrameRate ) { opt . push ( { minFrameRate : bestFrameRate } ) ; opt . push ( { maxFrameRate : bestFrameRate } ) ; }
video = { mandatory : obj . options . videoParams , optional : opt } ; } } else { video = { width : { min : obj . options . videoParams . minWidth , max : obj . options . videoParams . maxWidth } , height : { min : obj . options . videoParams . minHeight , max : obj . options . videoParams . maxHeight } } ; var useVideo = obj . options . useVideo ; if ( useVideo && obj . options . useCamera && obj . options . useCamera !== "none" ) { if ( obj . options . useCamera !== "any" ) { video = assignMediaIdToConstraint ( obj . options . useCamera , video ) ; }
if ( bestFrameRate ) { video . frameRate = { ideal : bestFrameRate , min : minFrameRate , max : 30 } ; } } else { console . log ( "Camera Disabled" ) ; video = false ; useVideo = false ; } }
return { audio : audio , video : video , useVideo : useVideo } ; }
$ . FSRTC . prototype . call = function ( profile ) { checkCompat ( ) ; var self = this ; var screen = false ; self . type = "offer" ; if ( self . options . videoParams && self . options . screenShare ) { screen = true ; }
function onSuccess ( stream ) { self . localStream = stream ; if ( screen ) { self . constraints . offerToReceiveVideo = false ; self . constraints . offerToReceiveAudio = false ; self . constraints . offerToSendAudio = false ; }
self . peer = FSRTCPeerConnection ( { type : self . type , attachStream : self . localStream , onICE : function ( candidate ) { return onICE ( self , candidate ) ; } , onICEComplete : function ( ) { return onICEComplete ( self ) ; } , onRemoteStream : screen ? function ( stream ) { } : function ( stream ) { return onRemoteStream ( self , stream ) ; } , onOfferSDP : function ( sdp ) { return onOfferSDP ( self , sdp ) ; } , onICESDP : function ( sdp ) { return onICESDP ( self , sdp ) ; } , onChannelError : function ( e ) { return onChannelError ( self , e ) ; } , constraints : self . constraints , iceServers : self . options . iceServers , turnServer : self . options . turnServer } ) ; onStreamSuccess ( self , stream ) ; }
function onError ( e ) { onStreamError ( self , e ) ; }
var mediaParams = getMediaParams ( self ) ; console . log ( "Audio constraints" , mediaParams . audio ) ; console . log ( "Video constraints" , mediaParams . video ) ; if ( self . options . useStream ) { if ( self . options . useVideo ) { self . options . localVideoStream = self . options . useStream ; if ( self . options . localVideo ) { activateLocalVideo ( self . options . localVideo , self . options . useStream ) ; } }
onSuccess ( self . options . useStream ) ; }
else if ( mediaParams . audio || mediaParams . video ) { getUserMedia ( { constraints : { audio : mediaParams . audio , video : mediaParams . video } , video : mediaParams . useVideo , onsuccess : onSuccess , onerror : onError , useCameraLabel : self . options . useCameraLabel , useMicLabel : self . options . useMicLabel , } ) ; } else { onSuccess ( null ) ; } } ; function FSRTCPeerConnection ( options ) { var gathering = false , done = false ; var config = { } ; var default _ice = [ { urls : [ 'stun:stun.l.google.com:19302' ] } ] ; if ( self . options . turnServer ) { default _ice . push ( self . options . turnServer ) }
if ( options . iceServers ) { if ( typeof ( options . iceServers ) === "boolean" ) { config . iceServers = default _ice ; } else { config . iceServers = options . iceServers ; } }
config . bundlePolicy = "max-compat" ; config . sdpSemantics = "plan-b" ; var peer = new window . RTCPeerConnection ( config ) ; openOffererChannel ( ) ; var x = 0 ; function ice _handler ( ) { done = true ; gathering = null ; if ( options . onICEComplete ) { options . onICEComplete ( ) ; }
if ( options . type == "offer" ) { options . onICESDP ( peer . localDescription ) ; } else { if ( ! x && options . onICESDP ) { options . onICESDP ( peer . localDescription ) ; } } }
peer . onicecandidate = function ( event ) { if ( done ) { return ; }
if ( ! gathering ) { gathering = setTimeout ( ice _handler , 1000 ) ; }
if ( event ) { if ( event . candidate ) { options . onICE ( event . candidate ) ; } } else { done = true ; if ( gathering ) { clearTimeout ( gathering ) ; gathering = null ; }
ice _handler ( ) ; } } ; if ( options . attachStream ) { options . attachStream . getAudioTracks ( ) . forEach ( function ( track ) { peer . addTrack ( track , options . attachStream ) } ) ; options . attachStream . getVideoTracks ( ) . forEach ( function ( track ) { peer . addTrack ( track , options . attachStream ) } ) ; }
if ( options . attachStreams && options . attachStreams . length ) { var streams = options . attachStreams ; for ( var i = 0 ; i < streams . length ; i ++ ) { peer . addStream ( streams [ i ] ) ; } }
2019-07-25 19:48:25 +00:00
peer . ontrack = function ( event ) { console . log ( 'Peer Track' , event )
var remoteMediaStream = event . streams [ 0 ] ; remoteMediaStream . oninactive = function ( ) { if ( options . onRemoteStreamEnded ) options . onRemoteStreamEnded ( remoteMediaStream ) ; } ; if ( options . onRemoteStream ) options . onRemoteStream ( remoteMediaStream ) ; } ; function createOffer ( ) { if ( ! options . onOfferSDP ) return ; peer . createOffer ( function ( sessionDescription ) { sessionDescription . sdp = serializeSdp ( sessionDescription . sdp ) ; peer . setLocalDescription ( sessionDescription ) ; options . onOfferSDP ( sessionDescription ) ; } , onSdpError , options . constraints ) ; }
2019-06-03 17:00:33 +00:00
function createAnswer ( ) { if ( options . type != "answer" ) return ; peer . setRemoteDescription ( new window . RTCSessionDescription ( options . offerSDP ) , onSdpSuccess , onSdpError ) ; peer . createAnswer ( function ( sessionDescription ) { sessionDescription . sdp = serializeSdp ( sessionDescription . sdp ) ; peer . setLocalDescription ( sessionDescription ) ; if ( options . onAnswerSDP ) { options . onAnswerSDP ( sessionDescription ) ; } } , onSdpError ) ; }
if ( ( options . onChannelMessage ) || ! options . onChannelMessage ) { createOffer ( ) ; createAnswer ( ) ; }
function setBandwidth ( sdp ) { sdp = sdp . replace ( /b=AS([^\r\n]+\r\n)/g , '' ) ; sdp = sdp . replace ( /a=mid:data\r\n/g , 'a=mid:data\r\nb=AS:1638400\r\n' ) ; return sdp ; }
function getInteropSDP ( sdp ) { var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . split ( '' ) , extractedChars = '' ; function getChars ( ) { extractedChars += chars [ parseInt ( Math . random ( ) * 40 ) ] || '' ; if ( extractedChars . length < 40 ) getChars ( ) ; return extractedChars ; }
if ( options . onAnswerSDP ) sdp = sdp . replace ( /(a=crypto:0 AES_CM_128_HMAC_SHA1_32)(.*?)(\r\n)/g , '' ) ; var inline = getChars ( ) + '\r\n' + ( extractedChars = '' ) ; sdp = sdp . indexOf ( 'a=crypto' ) == - 1 ? sdp . replace ( /c=IN/g , 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:' + inline + 'c=IN' ) : sdp ; return sdp ; }
function serializeSdp ( sdp ) { return sdp ; }
var channel ; function openOffererChannel ( ) { if ( ! options . onChannelMessage ) return ; _openOffererChannel ( ) ; return ; }
function _openOffererChannel ( ) { channel = peer . createDataChannel ( options . channel || 'RTCDataChannel' , { reliable : false } ) ; setChannelEvents ( ) ; }
function setChannelEvents ( ) { channel . onmessage = function ( event ) { if ( options . onChannelMessage ) options . onChannelMessage ( event ) ; } ; channel . onopen = function ( ) { if ( options . onChannelOpened ) options . onChannelOpened ( channel ) ; } ; channel . onclose = function ( event ) { if ( options . onChannelClosed ) options . onChannelClosed ( event ) ; console . warn ( 'WebRTC DataChannel closed' , event ) ; } ; channel . onerror = function ( event ) { if ( options . onChannelError ) options . onChannelError ( event ) ; console . error ( 'WebRTC DataChannel error' , event ) ; } ; }
function openAnswererChannel ( ) { peer . ondatachannel = function ( event ) { channel = event . channel ; channel . binaryType = 'blob' ; setChannelEvents ( ) ; } ; return ; }
function useless ( ) { log ( 'Error in fake:true' ) ; }
function onSdpSuccess ( ) { }
function onSdpError ( e ) { if ( options . onChannelError ) { options . onChannelError ( e ) ; }
console . error ( 'sdp error:' , e ) ; }
2019-07-25 19:48:25 +00:00
return { addAnswerSDP : function ( sdp , cbSuccess , cbError ) { peer . setRemoteDescription ( new window . RTCSessionDescription ( sdp ) , cbSuccess ? cbSuccess : onSdpSuccess , cbError ? cbError : onSdpError ) ; } , addICE : function ( candidate ) { peer . addIceCandidate ( new window . RTCIceCandidate ( { sdpMLineIndex : candidate . sdpMLineIndex , candidate : candidate . candidate } ) ) ; } , peer : peer , channel : channel , sendData : function ( message ) { if ( channel ) { channel . send ( message ) ; } } , stop : function ( ) { if ( options . attachStream instanceof MediaStream ) { var tracks = options . attachStream . getTracks ( ) ; tracks . forEach ( function ( track ) { track . stop ( ) } )
options . attachStream = null }
peer . close ( ) ; } } ; }
2019-06-03 17:00:33 +00:00
var video _constraints = { } ; function activateLocalVideo ( el , stream ) { el . srcObject = stream ; el . style . display = 'block' ; }
function deactivateLocalVideo ( el ) { el . srcObject = null ; el . style . display = 'none' ; }
function assureConstraintByLabel ( constraint , fallbackLabel ) { if ( fallbackLabel === undefined && constraint === undefined ) { return Promise . resolve ( constraint ) ; }
if ( typeof ( assureMediaInputId ) !== 'function' ) { console . warn ( 'Tried to use constraint fallbacks but did not found vendor function `assureMediaInputId` on window scope. Did you forget to import `vendor/media-device-id.js` before Verto?' ) ; return Promise . resolve ( constraint ) ; }
if ( typeof ( constraint ) === 'object' && ! constraint . deviceId ) { return Promise . resolve ( constraint ) ; }
if ( constraint . deviceId ) { if ( typeof ( constraint . deviceId ) === 'string' ) { return new Promise ( function ( resolve ) { assureMediaInputId ( fallbackLabel , constraint . deviceId ) . then ( function ( id ) { resolve ( Object . assign ( { } , constraint , { deviceId : id } ) ) ; } ) . catch ( function ( ) { resolve ( constraint ) ; } ) ; } ) ; }
if ( typeof ( constraint . deviceId ) === 'object' && typeof ( constraint . deviceId . exact ) === 'string' ) { return new Promise ( function ( resolve ) { assureMediaInputId ( fallbackLabel , constraint . deviceId . exact ) . then ( function ( id ) { resolve ( assignMediaIdToConstraint ( id , constraint ) ) ; } ) . catch ( function ( ) { resolve ( constraint ) ; } ) ; } ) ; } }
return Promise . resolve ( constraint ) ; }
function trustyGetUserMedia ( options , constraints ) { navigator . mediaDevices . getUserMedia ( constraints ) . then ( function ( stream ) { if ( options . localVideo ) { activateLocalVideo ( options . localVideo , stream ) ; }
if ( options . onsuccess ) { options . onsuccess ( stream ) ; } } ) . catch ( options . onerror || function ( e ) { console . error ( e ) ; } ) ; }
function assignMediaIdToConstraint ( mediaId , rest ) { return Object . assign ( { } , rest || { } , { deviceId : { exact : mediaId } } ) ; }
function getUserMedia ( options ) { var constraints = options . constraints || { audio : true , video : video _constraints , } ; Promise . all ( [ assureConstraintByLabel ( constraints . audio , options . useMicLabel ) , assureConstraintByLabel ( constraints . video , options . useCameraLabel ) , ] ) . then ( function ( assurances ) { trustyGetUserMedia ( options , { audio : assurances [ 0 ] , video : assurances [ 1 ] } ) ; } ) . catch ( function ( error ) { console . error ( 'Unexpected error on media id assurance attempts:' , error , 'Options:' , options ) ; } ) ; }
$ . FSRTC . resSupported = function ( w , h ) { for ( var i in $ . FSRTC . validRes ) { if ( $ . FSRTC . validRes [ i ] [ 0 ] == w && $ . FSRTC . validRes [ i ] [ 1 ] == h ) { return true ; } }
return false ; }
$ . FSRTC . bestResSupported = function ( ) { var w = 0 , h = 0 ; for ( var i in $ . FSRTC . validRes ) { if ( $ . FSRTC . validRes [ i ] [ 0 ] >= w && $ . FSRTC . validRes [ i ] [ 1 ] >= h ) { w = $ . FSRTC . validRes [ i ] [ 0 ] ; h = $ . FSRTC . validRes [ i ] [ 1 ] ; } }
return [ w , h ] ; }
var resList = [ [ 160 , 120 ] , [ 320 , 180 ] , [ 320 , 240 ] , [ 640 , 360 ] , [ 640 , 480 ] , [ 1280 , 720 ] , [ 1920 , 1080 ] ] ; var resI = 0 ; var ttl = 0 ; var checkRes = function ( cam , func ) { if ( resI >= resList . length ) { var res = { 'validRes' : $ . FSRTC . validRes , 'bestResSupported' : $ . FSRTC . bestResSupported ( ) } ; localStorage . setItem ( "res_" + cam , $ . toJSON ( res ) ) ; if ( func ) return func ( res ) ; return ; }
w = resList [ resI ] [ 0 ] ; h = resList [ resI ] [ 1 ] ; resI ++ ; var video = { width : { exact : w } , height : { exact : h } } ; if ( cam !== "any" ) { video = assignMediaIdToConstraint ( cam , video ) ; }
2019-07-25 19:48:25 +00:00
getUserMedia ( { constraints : { audio : ttl ++ == 0 , video : video } , onsuccess : function ( e ) { e . getTracks ( ) . forEach ( function ( track ) { track . stop ( ) } ) ; console . info ( w + "x" + h + " supported." ) ; $ . FSRTC . validRes . push ( [ w , h ] ) ; checkRes ( cam , func ) ; } , onerror : function ( e ) { console . warn ( w + "x" + h + " not supported." ) ; checkRes ( cam , func ) ; } } ) ; }
2019-06-03 17:00:33 +00:00
$ . FSRTC . getValidRes = function ( cam , func ) { var used = [ ] ; var cached = localStorage . getItem ( "res_" + cam ) ; if ( cached ) { var cache = $ . parseJSON ( cached ) ; if ( cache ) { $ . FSRTC . validRes = cache . validRes ; console . log ( "CACHED RES FOR CAM " + cam , cache ) ; } else { console . error ( "INVALID CACHE" ) ; }
return func ? func ( cache ) : null ; }
$ . FSRTC . validRes = [ ] ; resI = 0 ; checkRes ( cam , func ) ; }
2019-07-25 19:48:25 +00:00
$ . FSRTC . checkPerms = function ( runtime , check _audio , check _video ) { getUserMedia ( { constraints : { audio : check _audio , video : check _video } , onsuccess : function ( e ) { e . getTracks ( ) . forEach ( function ( track ) { track . stop ( ) } ) ; console . info ( "media perm init complete" ) ; if ( runtime ) { setTimeout ( runtime , 100 , true ) ; } } , onerror : function ( e ) { if ( check _video && check _audio ) { console . error ( "error, retesting with audio params only" ) ; return $ . FSRTC . checkPerms ( runtime , check _audio , false ) ; }
2019-06-03 17:00:33 +00:00
console . error ( "media perm init error" ) ; if ( runtime ) { runtime ( false ) } } } ) ; } } ) ( jQuery ) ; ( function ( $ ) { $ . JsonRpcClient = function ( options ) { var self = this ; this . options = $ . extend ( { ajaxUrl : null , socketUrl : null , onmessage : null , login : null , passwd : null , sessid : null , loginParams : null , userVariables : null , getSocket : function ( onmessage _cb ) { return self . _getSocket ( onmessage _cb ) ; } } , options ) ; self . ws _cnt = 0 ; this . wsOnMessage = function ( event ) { self . _wsOnMessage ( event ) ; } ; } ; $ . JsonRpcClient . prototype . _ws _socket = null ; $ . JsonRpcClient . prototype . _ws _callbacks = { } ; $ . JsonRpcClient . prototype . _current _id = 1 ; $ . JsonRpcClient . prototype . speedTest = function ( bytes , cb ) { var socket = this . options . getSocket ( this . wsOnMessage ) ; if ( socket !== null ) { this . speedCB = cb ; this . speedBytes = bytes ; socket . send ( "#SPU " + bytes ) ; var loops = bytes / 1024 ; var rem = bytes % 1024 ; var i ; var data = new Array ( 1024 ) . join ( "." ) ; for ( i = 0 ; i < loops ; i ++ ) { socket . send ( "#SPB " + data ) ; }
if ( rem ) { socket . send ( "#SPB " + data ) ; }
socket . send ( "#SPE" ) ; } } ; $ . JsonRpcClient . prototype . call = function ( method , params , success _cb , error _cb ) { if ( ! params ) { params = { } ; }
if ( this . options . sessid ) { params . sessid = this . options . sessid ; }
var request = { jsonrpc : '2.0' , method : method , params : params , id : this . _current _id ++ } ; if ( ! success _cb ) { success _cb = function ( e ) { console . log ( "Success: " , e ) ; } ; }
if ( ! error _cb ) { error _cb = function ( e ) { console . log ( "Error: " , e ) ; } ; }
var socket = this . options . getSocket ( this . wsOnMessage ) ; if ( socket !== null ) { this . _wsCall ( socket , request , success _cb , error _cb ) ; return ; }
if ( this . options . ajaxUrl === null ) { throw "$.JsonRpcClient.call used with no websocket and no http endpoint." ; }
$ . ajax ( { type : 'POST' , url : this . options . ajaxUrl , data : $ . toJSON ( request ) , dataType : 'json' , cache : false , success : function ( data ) { if ( 'error' in data ) error _cb ( data . error , this ) ; success _cb ( data . result , this ) ; } , error : function ( jqXHR , textStatus , errorThrown ) { try { var response = $ . parseJSON ( jqXHR . responseText ) ; if ( 'console' in window ) console . log ( response ) ; error _cb ( response . error , this ) ; } catch ( err ) { error _cb ( { error : jqXHR . responseText } , this ) ; } } } ) ; } ; $ . JsonRpcClient . prototype . notify = function ( method , params ) { if ( this . options . sessid ) { params . sessid = this . options . sessid ; }
var request = { jsonrpc : '2.0' , method : method , params : params } ; var socket = this . options . getSocket ( this . wsOnMessage ) ; if ( socket !== null ) { this . _wsCall ( socket , request ) ; return ; }
if ( this . options . ajaxUrl === null ) { throw "$.JsonRpcClient.notify used with no websocket and no http endpoint." ; }
$ . ajax ( { type : 'POST' , url : this . options . ajaxUrl , data : $ . toJSON ( request ) , dataType : 'json' , cache : false } ) ; } ; $ . JsonRpcClient . prototype . batch = function ( callback , all _done _cb , error _cb ) { var batch = new $ . JsonRpcClient . _batchObject ( this , all _done _cb , error _cb ) ; callback ( batch ) ; batch . _execute ( ) ; } ; $ . JsonRpcClient . prototype . socketReady = function ( ) { if ( this . _ws _socket === null || this . _ws _socket . readyState > 1 ) { return false ; }
return true ; } ; $ . JsonRpcClient . prototype . closeSocket = function ( ) { var self = this ; if ( self . socketReady ( ) ) { self . _ws _socket . onclose = function ( w ) { console . log ( "Closing Socket" ) ; } ; self . _ws _socket . close ( ) ; } } ; $ . JsonRpcClient . prototype . loginData = function ( params ) { var self = this ; self . options . login = params . login ; self . options . passwd = params . passwd ; self . options . loginParams = params . loginParams ; self . options . userVariables = params . userVariables ; } ; $ . JsonRpcClient . prototype . connectSocket = function ( onmessage _cb ) { var self = this ; if ( self . to ) { clearTimeout ( self . to ) ; }
if ( ! self . socketReady ( ) ) { self . authing = false ; if ( self . _ws _socket ) { delete self . _ws _socket ; }
self . _ws _socket = new WebSocket ( self . options . socketUrl ) ; if ( self . _ws _socket ) { self . _ws _socket . onmessage = onmessage _cb ; self . _ws _socket . onclose = function ( w ) { if ( ! self . ws _sleep ) { self . ws _sleep = 1000 ; }
if ( self . options . onWSClose ) { self . options . onWSClose ( self ) ; }
if ( self . ws _cnt > 10 && self . options . wsFallbackURL ) { self . options . socketUrl = self . options . wsFallbackURL ; }
console . error ( "Websocket Lost " + self . ws _cnt + " sleep: " + self . ws _sleep + "msec" ) ; self . to = setTimeout ( function ( ) { console . log ( "Attempting Reconnection...." ) ; self . connectSocket ( onmessage _cb ) ; } , self . ws _sleep ) ; self . ws _cnt ++ ; if ( self . ws _sleep < 3000 && ( self . ws _cnt % 10 ) === 0 ) { self . ws _sleep += 1000 ; } } ; self . _ws _socket . onopen = function ( ) { if ( self . to ) { clearTimeout ( self . to ) ; }
self . ws _sleep = 1000 ; self . ws _cnt = 0 ; if ( self . options . onWSConnect ) { self . options . onWSConnect ( self ) ; }
var req ; while ( ( req = $ . JsonRpcClient . q . pop ( ) ) ) { self . _ws _socket . send ( req ) ; } } ; } }
return self . _ws _socket ? true : false ; } ; $ . JsonRpcClient . prototype . stopRetrying = function ( ) { if ( self . to )
clearTimeout ( self . to ) ; }
$ . JsonRpcClient . prototype . _getSocket = function ( onmessage _cb ) { if ( this . options . socketUrl === null || ! ( "WebSocket" in window ) ) return null ; this . connectSocket ( onmessage _cb ) ; return this . _ws _socket ; } ; $ . JsonRpcClient . q = [ ] ; $ . JsonRpcClient . prototype . _wsCall = function ( socket , request , success _cb , error _cb ) { var request _json = $ . toJSON ( request ) ; if ( socket . readyState < 1 ) { self = this ; $ . JsonRpcClient . q . push ( request _json ) ; } else { socket . send ( request _json ) ; }
if ( 'id' in request && typeof success _cb !== 'undefined' ) { this . _ws _callbacks [ request . id ] = { request : request _json , request _obj : request , success _cb : success _cb , error _cb : error _cb } ; } } ; $ . JsonRpcClient . prototype . _wsOnMessage = function ( event ) { var response ; if ( event . data [ 0 ] == "#" && event . data [ 1 ] == "S" && event . data [ 2 ] == "P" ) { if ( event . data [ 3 ] == "U" ) { this . up _dur = parseInt ( event . data . substring ( 4 ) ) ; } else if ( this . speedCB && event . data [ 3 ] == "D" ) { this . down _dur = parseInt ( event . data . substring ( 4 ) ) ; var up _kps = ( ( ( this . speedBytes * 8 ) / ( this . up _dur / 1000 ) ) / 1024 ) . toFixed ( 0 ) ; var down _kps = ( ( ( this . speedBytes * 8 ) / ( this . down _dur / 1000 ) ) / 1024 ) . toFixed ( 0 ) ; console . info ( "Speed Test: Up: " + up _kps + " Down: " + down _kps ) ; var cb = this . speedCB ; this . speedCB = null ; cb ( event , { upDur : this . up _dur , downDur : this . down _dur , upKPS : up _kps , downKPS : down _kps } ) ; }
return ; }
try { response = $ . parseJSON ( event . data ) ; if ( typeof response === 'object' && 'jsonrpc' in response && response . jsonrpc === '2.0' ) { if ( 'result' in response && this . _ws _callbacks [ response . id ] ) { var success _cb = this . _ws _callbacks [ response . id ] . success _cb ; delete this . _ws _callbacks [ response . id ] ; success _cb ( response . result , this ) ; return ; } else if ( 'error' in response && this . _ws _callbacks [ response . id ] ) { var error _cb = this . _ws _callbacks [ response . id ] . error _cb ; var orig _req = this . _ws _callbacks [ response . id ] . request ; if ( ! self . authing && response . error . code == - 32000 && self . options . login && self . options . passwd ) { self . authing = true ; this . call ( "login" , { login : self . options . login , passwd : self . options . passwd , loginParams : self . options . loginParams , userVariables : self . options . userVariables } , this . _ws _callbacks [ response . id ] . request _obj . method == "login" ? function ( e ) { self . authing = false ; console . log ( "logged in" ) ; delete self . _ws _callbacks [ response . id ] ; if ( self . options . onWSLogin ) { self . options . onWSLogin ( true , self ) ; } } : function ( e ) { self . authing = false ; console . log ( "logged in, resending request id: " + response . id ) ; var socket = self . options . getSocket ( self . wsOnMessage ) ; if ( socket !== null ) { socket . send ( orig _req ) ; }
if ( self . options . onWSLogin ) { self . options . onWSLogin ( true , self ) ; } } , function ( e ) { console . log ( "error logging in, request id:" , response . id ) ; delete self . _ws _callbacks [ response . id ] ; error _cb ( response . error , this ) ; if ( self . options . onWSLogin ) { self . options . onWSLogin ( false , self ) ; } } ) ; return ; }
delete this . _ws _callbacks [ response . id ] ; error _cb ( response . error , this ) ; return ; } } } catch ( err ) { console . log ( "ERROR: " + err ) ; return ; }
if ( typeof this . options . onmessage === 'function' ) { event . eventData = response ; if ( ! event . eventData ) { event . eventData = { } ; }
var reply = this . options . onmessage ( event ) ; if ( reply && typeof reply === "object" && event . eventData . id ) { var msg = { jsonrpc : "2.0" , id : event . eventData . id , result : reply } ; var socket = self . options . getSocket ( self . wsOnMessage ) ; if ( socket !== null ) { socket . send ( $ . toJSON ( msg ) ) ; } } } } ; $ . JsonRpcClient . _batchObject = function ( jsonrpcclient , all _done _cb , error _cb ) { this . _requests = [ ] ; this . jsonrpcclient = jsonrpcclient ; this . all _done _cb = all _done _cb ; this . error _cb = typeof error _cb === 'function' ? error _cb : function ( ) { } ; } ; $ . JsonRpcClient . _batchObject . prototype . call = function ( method , params , success _cb , error _cb ) { if ( ! params ) { params = { } ; }
if ( this . options . sessid ) { params . sessid = this . options . sessid ; }
if ( ! success _cb ) { success _cb = function ( e ) { console . log ( "Success: " , e ) ; } ; }
if ( ! error _cb ) { error _cb = function ( e ) { console . log ( "Error: " , e ) ; } ; }
this . _requests . push ( { request : { jsonrpc : '2.0' , method : method , params : params , id : this . jsonrpcclient . _current _id ++ } , success _cb : success _cb , error _cb : error _cb } ) ; } ; $ . JsonRpcClient . _batchObject . prototype . notify = function ( method , params ) { if ( this . options . sessid ) { params . sessid = this . options . sessid ; }
this . _requests . push ( { request : { jsonrpc : '2.0' , method : method , params : params } } ) ; } ; $ . JsonRpcClient . _batchObject . prototype . _execute = function ( ) { var self = this ; if ( this . _requests . length === 0 ) return ; var batch _request = [ ] ; var handlers = { } ; var i = 0 ; var call ; var success _cb ; var error _cb ; var socket = self . jsonrpcclient . options . getSocket ( self . jsonrpcclient . wsOnMessage ) ; if ( socket !== null ) { for ( i = 0 ; i < this . _requests . length ; i ++ ) { call = this . _requests [ i ] ; success _cb = ( 'success_cb' in call ) ? call . success _cb : undefined ; error _cb = ( 'error_cb' in call ) ? call . error _cb : undefined ; self . jsonrpcclient . _wsCall ( socket , call . request , success _cb , error _cb ) ; }
if ( typeof all _done _cb === 'function' ) all _done _cb ( result ) ; return ; }
for ( i = 0 ; i < this . _requests . length ; i ++ ) { call = this . _requests [ i ] ; batch _request . push ( call . request ) ; if ( 'id' in call . request ) { handlers [ call . request . id ] = { success _cb : call . success _cb , error _cb : call . error _cb } ; } }
success _cb = function ( data ) { self . _batchCb ( data , handlers , self . all _done _cb ) ; } ; if ( self . jsonrpcclient . options . ajaxUrl === null ) { throw "$.JsonRpcClient.batch used with no websocket and no http endpoint." ; }
$ . ajax ( { url : self . jsonrpcclient . options . ajaxUrl , data : $ . toJSON ( batch _request ) , dataType : 'json' , cache : false , type : 'POST' , error : function ( jqXHR , textStatus , errorThrown ) { self . error _cb ( jqXHR , textStatus , errorThrown ) ; } , success : success _cb } ) ; } ; $ . JsonRpcClient . _batchObject . prototype . _batchCb = function ( result , handlers , all _done _cb ) { for ( var i = 0 ; i < result . length ; i ++ ) { var response = result [ i ] ; if ( 'error' in response ) { if ( response . id === null || ! ( response . id in handlers ) ) { if ( 'console' in window ) console . log ( response ) ; } else { handlers [ response . id ] . error _cb ( response . error , this ) ; } } else { if ( ! ( response . id in handlers ) && 'console' in window ) { console . log ( response ) ; } else { handlers [ response . id ] . success _cb ( response . result , this ) ; } } }
if ( typeof all _done _cb === 'function' ) all _done _cb ( result ) ; } ; } ) ( jQuery ) ; ( function ( $ ) { var sources = [ ] ; var generateGUID = ( typeof ( window . crypto ) !== 'undefined' && typeof ( window . crypto . getRandomValues ) !== 'undefined' ) ? function ( ) { var buf = new Uint16Array ( 8 ) ; window . crypto . getRandomValues ( buf ) ; var S4 = function ( num ) { var ret = num . toString ( 16 ) ; while ( ret . length < 4 ) { ret = "0" + ret ; }
return ret ; } ; return ( S4 ( buf [ 0 ] ) + S4 ( buf [ 1 ] ) + "-" + S4 ( buf [ 2 ] ) + "-" + S4 ( buf [ 3 ] ) + "-" + S4 ( buf [ 4 ] ) + "-" + S4 ( buf [ 5 ] ) + S4 ( buf [ 6 ] ) + S4 ( buf [ 7 ] ) ) ; } : function ( ) { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' . replace ( /[xy]/g , function ( c ) { var r = Math . random ( ) * 16 | 0 , v = c == 'x' ? r : ( r & 0x3 | 0x8 ) ; return v . toString ( 16 ) ; } ) ; } ; $ . verto = function ( options , callbacks ) { var verto = this ; $ . verto . saved . push ( verto ) ; verto . options = $ . extend ( { login : null , passwd : null , socketUrl : null , tag : null , localTag : null , videoParams : { } , audioParams : { } , loginParams : { } , deviceParams : { onResCheck : null } , userVariables : { } , iceServers : false , ringSleep : 6000 , sessid : null , useStream : null } , options ) ; if ( verto . options . deviceParams . useCamera ) { $ . FSRTC . getValidRes ( verto . options . deviceParams . useCamera , verto . options . deviceParams . onResCheck ) ; }
if ( ! verto . options . deviceParams . useMic ) { verto . options . deviceParams . useMic = "any" ; }
if ( ! verto . options . deviceParams . useSpeak ) { verto . options . deviceParams . useSpeak = "any" ; }
if ( verto . options . sessid ) { verto . sessid = verto . options . sessid ; } else { verto . sessid = localStorage . getItem ( "verto_session_uuid" ) || generateGUID ( ) ; localStorage . setItem ( "verto_session_uuid" , verto . sessid ) ; }
verto . dialogs = { } ; verto . callbacks = callbacks || { } ; verto . eventSUBS = { } ; verto . rpcClient = new $ . JsonRpcClient ( { login : verto . options . login , passwd : verto . options . passwd , socketUrl : verto . options . socketUrl , wsFallbackURL : verto . options . wsFallbackURL , turnServer : verto . options . turnServer , loginParams : verto . options . loginParams , userVariables : verto . options . userVariables , sessid : verto . sessid , onmessage : function ( e ) { return verto . handleMessage ( e . eventData ) ; } , onWSConnect : function ( o ) { o . call ( 'login' , { } ) ; } , onWSLogin : function ( success ) { if ( verto . callbacks . onWSLogin ) { verto . callbacks . onWSLogin ( verto , success ) ; } } , onWSClose : function ( success ) { if ( verto . callbacks . onWSClose ) { verto . callbacks . onWSClose ( verto , success ) ; }
verto . purge ( ) ; } } ) ; var tag = verto . options . tag ; if ( typeof ( tag ) === "function" ) { tag = tag ( ) ; }
if ( verto . options . ringFile && verto . options . tag ) { verto . ringer = $ ( "#" + tag ) ; }
verto . rpcClient . call ( 'login' , { } ) ; } ; $ . verto . prototype . deviceParams = function ( obj ) { var verto = this ; for ( var i in obj ) { verto . options . deviceParams [ i ] = obj [ i ] ; }
if ( obj . useCamera ) { $ . FSRTC . getValidRes ( verto . options . deviceParams . useCamera , obj ? obj . onResCheck : undefined ) ; } } ; $ . verto . prototype . videoParams = function ( obj ) { var verto = this ; for ( var i in obj ) { verto . options . videoParams [ i ] = obj [ i ] ; } } ; $ . verto . prototype . iceServers = function ( obj ) { var verto = this ; verto . options . iceServers = obj ; } ; $ . verto . prototype . loginData = function ( params ) { var verto = this ; verto . options . login = params . login ; verto . options . passwd = params . passwd ; verto . rpcClient . loginData ( params ) ; } ; $ . verto . prototype . logout = function ( msg ) { var verto = this ; verto . rpcClient . closeSocket ( ) ; if ( verto . callbacks . onWSClose ) { verto . callbacks . onWSClose ( verto , false ) ; }
verto . purge ( ) ; } ; $ . verto . prototype . login = function ( msg ) { var verto = this ; verto . logout ( ) ; verto . rpcClient . call ( 'login' , { } ) ; } ; $ . verto . prototype . message = function ( msg ) { var verto = this ; var err = 0 ; if ( ! msg . to ) { console . error ( "Missing To" ) ; err ++ ; }
if ( ! msg . body ) { console . error ( "Missing Body" ) ; err ++ ; }
if ( err ) { return false ; }
verto . sendMethod ( "verto.info" , { msg : msg } ) ; return true ; } ; $ . verto . prototype . processReply = function ( method , success , e ) { var verto = this ; var i ; switch ( method ) { case "verto.subscribe" : for ( i in e . unauthorizedChannels ) { drop _bad ( verto , e . unauthorizedChannels [ i ] ) ; }
for ( i in e . subscribedChannels ) { mark _ready ( verto , e . subscribedChannels [ i ] ) ; }
break ; case "verto.unsubscribe" : break ; } } ; $ . verto . prototype . sendMethod = function ( method , params ) { var verto = this ; verto . rpcClient . call ( method , params , function ( e ) { verto . processReply ( method , true , e ) ; } , function ( e ) { verto . processReply ( method , false , e ) ; } ) ; } ; function do _sub ( verto , channel , obj ) { }
function drop _bad ( verto , channel ) { console . error ( "drop unauthorized channel: " + channel ) ; delete verto . eventSUBS [ channel ] ; }
function mark _ready ( verto , channel ) { for ( var j in verto . eventSUBS [ channel ] ) { verto . eventSUBS [ channel ] [ j ] . ready = true ; console . log ( "subscribed to channel: " + channel ) ; if ( verto . eventSUBS [ channel ] [ j ] . readyHandler ) { verto . eventSUBS [ channel ] [ j ] . readyHandler ( verto , channel ) ; } } }
var SERNO = 1 ; function do _subscribe ( verto , channel , subChannels , sparams ) { var params = sparams || { } ; var local = params . local ; var obj = { eventChannel : channel , userData : params . userData , handler : params . handler , ready : false , readyHandler : params . readyHandler , serno : SERNO ++ } ; var isnew = false ; if ( ! verto . eventSUBS [ channel ] ) { verto . eventSUBS [ channel ] = [ ] ; subChannels . push ( channel ) ; isnew = true ; }
verto . eventSUBS [ channel ] . push ( obj ) ; if ( local ) { obj . ready = true ; obj . local = true ; }
if ( ! isnew && verto . eventSUBS [ channel ] [ 0 ] . ready ) { obj . ready = true ; if ( obj . readyHandler ) { obj . readyHandler ( verto , channel ) ; } }
return { serno : obj . serno , eventChannel : channel } ; }
$ . verto . prototype . subscribe = function ( channel , sparams ) { var verto = this ; var r = [ ] ; var subChannels = [ ] ; var params = sparams || { } ; if ( typeof ( channel ) === "string" ) { r . push ( do _subscribe ( verto , channel , subChannels , params ) ) ; } else { for ( var i in channel ) { r . push ( do _subscribe ( verto , channel , subChannels , params ) ) ; } }
if ( subChannels . length ) { verto . sendMethod ( "verto.subscribe" , { eventChannel : subChannels . length == 1 ? subChannels [ 0 ] : subChannels , subParams : params . subParams } ) ; }
return r ; } ; $ . verto . prototype . unsubscribe = function ( handle ) { var verto = this ; var i ; if ( ! handle ) { for ( i in verto . eventSUBS ) { if ( verto . eventSUBS [ i ] ) { verto . unsubscribe ( verto . eventSUBS [ i ] ) ; } } } else { var unsubChannels = { } ; var sendChannels = [ ] ; var channel ; if ( typeof ( handle ) == "string" ) { delete verto . eventSUBS [ handle ] ; unsubChannels [ handle ] ++ ; } else { for ( i in handle ) { if ( typeof ( handle [ i ] ) == "string" ) { channel = handle [ i ] ; delete verto . eventSUBS [ channel ] ; unsubChannels [ channel ] ++ ; } else { var repl = [ ] ; channel = handle [ i ] . eventChannel ; for ( var j in verto . eventSUBS [ channel ] ) { if ( verto . eventSUBS [ channel ] [ j ] . serno == handle [ i ] . serno ) { } else { repl . push ( verto . eventSUBS [ channel ] [ j ] ) ; } }
verto . eventSUBS [ channel ] = repl ; if ( verto . eventSUBS [ channel ] . length === 0 ) { delete verto . eventSUBS [ channel ] ; unsubChannels [ channel ] ++ ; } } } }
for ( var u in unsubChannels ) { console . log ( "Sending Unsubscribe for: " , u ) ; sendChannels . push ( u ) ; }
if ( sendChannels . length ) { verto . sendMethod ( "verto.unsubscribe" , { eventChannel : sendChannels . length == 1 ? sendChannels [ 0 ] : sendChannels } ) ; } } } ; $ . verto . prototype . broadcast = function ( channel , params ) { var verto = this ; var msg = { eventChannel : channel , data : { } } ; for ( var i in params ) { msg . data [ i ] = params [ i ] ; }
verto . sendMethod ( "verto.broadcast" , msg ) ; } ; $ . verto . prototype . purge = function ( callID ) { var verto = this ; var x = 0 ; var i ; for ( i in verto . dialogs ) { if ( ! x ) { console . log ( "purging dialogs" ) ; }
x ++ ; verto . dialogs [ i ] . setState ( $ . verto . enum . state . purge ) ; }
for ( i in verto . eventSUBS ) { if ( verto . eventSUBS [ i ] ) { console . log ( "purging subscription: " + i ) ; delete verto . eventSUBS [ i ] ; } } } ; $ . verto . prototype . hangup = function ( callID ) { var verto = this ; if ( callID ) { var dialog = verto . dialogs [ callID ] ; if ( dialog ) { dialog . hangup ( ) ; } } else { for ( var i in verto . dialogs ) { verto . dialogs [ i ] . hangup ( ) ; } } } ; $ . verto . prototype . newCall = function ( args , callbacks ) { var verto = this ; if ( ! verto . rpcClient . socketReady ( ) ) { console . error ( "Not Connected..." ) ; return ; }
if ( args [ "useCamera" ] ) { verto . options . deviceParams [ "useCamera" ] = args [ "useCamera" ] ; verto . options . deviceParams [ "useCameraLabel" ] = args [ "useCameraLabel" ] ; }
var dialog = new $ . verto . dialog ( $ . verto . enum . direction . outbound , this , args ) ; if ( callbacks ) { dialog . callbacks = callbacks ; }
dialog . invite ( ) ; return dialog ; } ; $ . verto . prototype . handleMessage = function ( data ) { var verto = this ; if ( ! ( data && data . method ) ) { console . error ( "Invalid Data" , data ) ; return ; }
if ( data . params . callID ) { var dialog = verto . dialogs [ data . params . callID ] ; if ( data . method === "verto.attach" && dialog ) { delete dialog . verto . dialogs [ dialog . callID ] ; dialog . rtc . stop ( ) ; dialog = null ; }
if ( dialog ) { switch ( data . method ) { case 'verto.bye' : dialog . hangup ( data . params ) ; break ; case 'verto.answer' : dialog . handleAnswer ( data . params ) ; break ; case 'verto.media' : dialog . handleMedia ( data . params ) ; break ; case 'verto.display' : dialog . handleDisplay ( data . params ) ; break ; case 'verto.info' : dialog . handleInfo ( data . params ) ; break ; default : console . debug ( "INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED" , dialog , data . method ) ; break ; } } else { switch ( data . method ) { case 'verto.attach' : data . params . attach = true ; if ( data . params . sdp && data . params . sdp . indexOf ( "m=video" ) > 0 ) { data . params . useVideo = true ; }
if ( data . params . sdp && data . params . sdp . indexOf ( "stereo=1" ) > 0 ) { data . params . useStereo = true ; }
dialog = new $ . verto . dialog ( $ . verto . enum . direction . inbound , verto , data . params ) ; dialog . setState ( $ . verto . enum . state . recovering ) ; break ; case 'verto.invite' : if ( data . params . sdp && data . params . sdp . indexOf ( "m=video" ) > 0 ) { data . params . wantVideo = true ; }
if ( data . params . sdp && data . params . sdp . indexOf ( "stereo=1" ) > 0 ) { data . params . useStereo = true ; }
dialog = new $ . verto . dialog ( $ . verto . enum . direction . inbound , verto , data . params ) ; break ; default : console . debug ( "INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED" ) ; break ; } }
return { method : data . method } ; } else { switch ( data . method ) { case 'verto.punt' : verto . purge ( ) ; verto . logout ( ) ; break ; case 'verto.event' : var list = null ; var key = null ; if ( data . params ) { key = data . params . eventChannel ; }
if ( key ) { list = verto . eventSUBS [ key ] ; if ( ! list ) { list = verto . eventSUBS [ key . split ( "." ) [ 0 ] ] ; } }
if ( ! list && key && key === verto . sessid ) { if ( verto . callbacks . onMessage ) { verto . callbacks . onMessage ( verto , null , $ . verto . enum . message . pvtEvent , data . params ) ; } } else if ( ! list && key && verto . dialogs [ key ] ) { verto . dialogs [ key ] . sendMessage ( $ . verto . enum . message . pvtEvent , data . params ) ; } else if ( ! list ) { if ( ! key ) { key = "UNDEFINED" ; }
console . error ( "UNSUBBED or invalid EVENT " + key + " IGNORED" ) ; } else { for ( var i in list ) { var sub = list [ i ] ; if ( ! sub || ! sub . ready ) { console . error ( "invalid EVENT for " + key + " IGNORED" ) ; } else if ( sub . handler ) { sub . handler ( verto , data . params , sub . userData ) ; } else if ( verto . callbacks . onEvent ) { verto . callbacks . onEvent ( verto , data . params , sub . userData ) ; } else { console . log ( "EVENT:" , data . params ) ; } } }
break ; case "verto.info" : if ( verto . callbacks . onMessage ) { verto . callbacks . onMessage ( verto , null , $ . verto . enum . message . info , data . params . msg ) ; }
console . debug ( "MESSAGE from: " + data . params . msg . from , data . params . msg . body ) ; break ; case 'verto.clientReady' : if ( verto . callbacks . onMessage ) { verto . callbacks . onMessage ( verto , null , $ . verto . enum . message . clientReady , data . params ) ; }
console . debug ( "CLIENT READY" , data . params ) ; break ; default : console . error ( "INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED" , data . method ) ; break ; } } } ; var del _array = function ( array , name ) { var r = [ ] ; var len = array . length ; for ( var i = 0 ; i < len ; i ++ ) { if ( array [ i ] != name ) { r . push ( array [ i ] ) ; } }
return r ; } ; var hashArray = function ( ) { var vha = this ; var hash = { } ; var array = [ ] ; vha . reorder = function ( a ) { array = a ; var h = hash ; hash = { } ; var len = array . length ; for ( var i = 0 ; i < len ; i ++ ) { var key = array [ i ] ; if ( h [ key ] ) { hash [ key ] = h [ key ] ; delete h [ key ] ; } }
h = undefined ; } ; vha . clear = function ( ) { hash = undefined ; array = undefined ; hash = { } ; array = [ ] ; } ; vha . add = function ( name , val , insertAt ) { var redraw = false ; if ( ! hash [ name ] ) { if ( insertAt === undefined || insertAt < 0 || insertAt >= array . length ) { array . push ( name ) ; } else { var x = 0 ; var n = [ ] ; var len = array . length ; for ( var i = 0 ; i < len ; i ++ ) { if ( x ++ == insertAt ) { n . push ( name ) ; }
n . push ( array [ i ] ) ; }
array = undefined ; array = n ; n = undefined ; redraw = true ; } }
hash [ name ] = val ; return redraw ; } ; vha . del = function ( name ) { var r = false ; if ( hash [ name ] ) { array = del _array ( array , name ) ; delete hash [ name ] ; r = true ; } else { console . error ( "can't del nonexistant key " + name ) ; }
return r ; } ; vha . get = function ( name ) { return hash [ name ] ; } ; vha . order = function ( ) { return array ; } ; vha . hash = function ( ) { return hash ; } ; vha . indexOf = function ( name ) { var len = array . length ; for ( var i = 0 ; i < len ; i ++ ) { if ( array [ i ] == name ) { return i ; } } } ; vha . arrayLen = function ( ) { return array . length ; } ; vha . asArray = function ( ) { var r = [ ] ; var len = array . length ; for ( var i = 0 ; i < len ; i ++ ) { var key = array [ i ] ; r . push ( hash [ key ] ) ; }
return r ; } ; vha . each = function ( cb ) { var len = array . length ; for ( var i = 0 ; i < len ; i ++ ) { cb ( array [ i ] , hash [ array [ i ] ] ) ; } } ; vha . dump = function ( html ) { var str = "" ; vha . each ( function ( name , val ) { str += "name: " + name + " val: " + JSON . stringify ( val ) + ( html ? "<br>" : "\n" ) ; } ) ; return str ; } ; } ; $ . verto . liveArray = function ( verto , context , name , config ) { var la = this ; var lastSerno = 0 ; var binding = null ; var user _obj = config . userObj ; var local = false ; hashArray . call ( la ) ; la . _add = la . add ; la . _del = la . del ; la . _reorder = la . reorder ; la . _clear = la . clear ; la . context = context ; la . name = name ; la . user _obj = user _obj ; la . verto = verto ; la . broadcast = function ( channel , obj ) { verto . broadcast ( channel , obj ) ; } ; la . errs = 0 ; la . clear = function ( ) { la . _clear ( ) ; lastSerno = 0 ; if ( la . onChange ) { la . onChange ( la , { action : "clear" } ) ; } } ; la . checkSerno = function ( serno ) { if ( serno < 0 ) { return true ; }
if ( lastSerno > 0 && serno != ( lastSerno + 1 ) ) { if ( la . onErr ) { la . onErr ( la , { lastSerno : lastSerno , serno : serno } ) ; }
la . errs ++ ; console . debug ( la . errs ) ; if ( la . errs < 3 ) { la . bootstrap ( la . user _obj ) ; }
return false ; } else { lastSerno = serno ; return true ; } } ; la . reorder = function ( serno , a ) { if ( la . checkSerno ( serno ) ) { la . _reorder ( a ) ; if ( la . onChange ) { la . onChange ( la , { serno : serno , action : "reorder" } ) ; } } } ; la . init = function ( serno , val , key , index ) { if ( key === null || key === undefined ) { key = serno ; }
if ( la . checkSerno ( serno ) ) { if ( la . onChange ) { la . onChange ( la , { serno : serno , action : "init" , index : index , key : key , data : val } ) ; } } } ; la . bootObj = function ( serno , val ) { if ( la . checkSerno ( serno ) ) { for ( var i in val ) { la . _add ( val [ i ] [ 0 ] , val [ i ] [ 1 ] ) ; }
if ( la . onChange ) { la . onChange ( la , { serno : serno , action : "bootObj" , data : val , redraw : true } ) ; } } } ; la . add = function ( serno , val , key , index ) { if ( key === null || key === undefined ) { key = serno ; }
if ( la . checkSerno ( serno ) ) { var redraw = la . _add ( key , val , index ) ; if ( la . onChange ) { la . onChange ( la , { serno : serno , action : "add" , index : index , key : key , data : val , redraw : redraw } ) ; } } } ; la . modify = function ( serno , val , key , index ) { if ( key === null || key === undefined ) { key = serno ; }
if ( la . checkSerno ( serno ) ) { la . _add ( key , val , index ) ; if ( la . onChange ) { la . onChange ( la , { serno : serno , action : "modify" , key : key , data : val , index : index } ) ; } } } ; la . del = function ( serno , key , index ) { if ( key === null || key === undefined ) { key = serno ; }
if ( la . checkSerno ( serno ) ) { if ( index === null || index < 0 || index === undefined ) { index = la . indexOf ( key ) ; }
var ok = la . _del ( key ) ; if ( ok && la . onChange ) { la . onChange ( la , { serno : serno , action : "del" , key : key , index : index } ) ; } } } ; var eventHandler = function ( v , e , la ) { var packet = e . data ; if ( packet . name != la . name ) { return ; }
switch ( packet . action ) { case "init" : la . init ( packet . wireSerno , packet . data , packet . hashKey , packet . arrIndex ) ; break ; case "bootObj" : la . bootObj ( packet . wireSerno , packet . data ) ; break ; case "add" : la . add ( packet . wireSerno , packet . data , packet . hashKey , packet . arrIndex ) ; break ; case "modify" : if ( ! ( packet . arrIndex || packet . hashKey ) ) { console . error ( "Invalid Packet" , packet ) ; } else { la . modify ( packet . wireSerno , packet . data , packet . hashKey , packet . arrIndex ) ; }
break ; case "del" : if ( ! ( packet . arrIndex || packet . hashKey ) ) { console . error ( "Invalid Packet" , packet ) ; } else { la . del ( packet . wireSerno , packet . hashKey , packet . arrIndex ) ; }
break ; case "clear" : la . clear ( ) ; break ; case "reorder" : la . reorder ( packet . wireSerno , packet . order ) ; break ; default : if ( la . checkSerno ( packet . wireSerno ) ) { if ( la . onChange ) { la . onChange ( la , { serno : packet . wireSerno , action : packet . action , data : packet . data } ) ; } }
break ; } } ; if ( la . context ) { binding = la . verto . subscribe ( la . context , { handler : eventHandler , userData : la , subParams : config . subParams } ) ; }
la . destroy = function ( ) { la . _clear ( ) ; la . verto . unsubscribe ( binding ) ; } ; la . sendCommand = function ( cmd , obj ) { var self = la ; self . broadcast ( self . context , { liveArray : { command : cmd , context : self . context , name : self . name , obj : obj } } ) ; } ; la . bootstrap = function ( obj ) { var self = la ; la . sendCommand ( "bootstrap" , obj ) ; } ; la . changepage = function ( obj ) { var self = la ; self . clear ( ) ; self . broadcast ( self . context , { liveArray : { command : "changepage" , context : la . context , name : la . name , obj : obj } } ) ; } ; la . heartbeat = function ( obj ) { var self = la ; var callback = function ( ) { self . heartbeat . call ( self , obj ) ; } ; self . broadcast ( self . context , { liveArray : { command : "heartbeat" , context : self . context , name : self . name , obj : obj } } ) ; self . hb _pid = setTimeout ( callback , 30000 ) ; } ; la . bootstrap ( la . user _obj ) ; } ; $ . verto . liveTable = function ( verto , context , name , jq , config ) { var dt ; var la = new $ . verto . liveArray ( verto , context , name , { subParams : config . subParams } ) ; var lt = this ; lt . liveArray = la ; lt . dataTable = dt ; lt . verto = verto ; lt . destroy = function ( ) { if ( dt ) { dt . fnDestroy ( ) ; }
if ( la ) { la . destroy ( ) ; }
dt = null ; la = null ; } ; la . onErr = function ( obj , args ) { console . error ( "Error: " , obj , args ) ; } ; function genRow ( data ) { if ( typeof ( data [ 4 ] ) === "string" && data [ 4 ] . indexOf ( "{" ) > - 1 ) { var tmp = $ . parseJSON ( data [ 4 ] ) ; data [ 4 ] = tmp . oldStatus ; data [ 5 ] = null ; }
return data ; }
function genArray ( obj ) { var data = obj . asArray ( ) ; for ( var i in data ) { data [ i ] = genRow ( data [ i ] ) ; }
return data ; }
la . onChange = function ( obj , args ) { var index = 0 ; var iserr = 0 ; if ( ! dt ) { if ( ! config . aoColumns ) { if ( args . action != "init" ) { return ; }
config . aoColumns = [ ] ; for ( var i in args . data ) { config . aoColumns . push ( { "sTitle" : args . data [ i ] } ) ; } }
dt = jq . dataTable ( config ) ; }
if ( dt && ( args . action == "del" || args . action == "modify" ) ) { index = args . index ; if ( index === undefined && args . key ) { index = la . indexOf ( args . key ) ; }
if ( index === undefined ) { console . error ( "INVALID PACKET Missing INDEX\n" , args ) ; return ; } }
if ( config . onChange ) { config . onChange ( obj , args ) ; }
try { switch ( args . action ) { case "bootObj" : if ( ! args . data ) { console . error ( "missing data" ) ; return ; }
dt . fnClearTable ( ) ; dt . fnAddData ( genArray ( obj ) ) ; dt . fnAdjustColumnSizing ( ) ; break ; case "add" : if ( ! args . data ) { console . error ( "missing data" ) ; return ; }
if ( args . redraw > - 1 ) { dt . fnClearTable ( ) ; dt . fnAddData ( genArray ( obj ) ) ; } else { dt . fnAddData ( genRow ( args . data ) ) ; }
dt . fnAdjustColumnSizing ( ) ; break ; case "modify" : if ( ! args . data ) { return ; }
dt . fnUpdate ( genRow ( args . data ) , index ) ; dt . fnAdjustColumnSizing ( ) ; break ; case "del" : dt . fnDeleteRow ( index ) ; dt . fnAdjustColumnSizing ( ) ; break ; case "clear" : dt . fnClearTable ( ) ; break ; case "reorder" : dt . fnClearTable ( ) ; dt . fnAddData ( genArray ( obj ) ) ; break ; case "hide" : jq . hide ( ) ; break ; case "show" : jq . show ( ) ; break ; } } catch ( err ) { console . error ( "ERROR: " + err ) ; iserr ++ ; }
if ( iserr ) { obj . errs ++ ; if ( obj . errs < 3 ) { obj . bootstrap ( obj . user _obj ) ; } } else { obj . errs = 0 ; } } ; la . onChange ( la , { action : "init" } ) ; } ; var CONFMAN _SERNO = 1 ; $ . verto . conf = function ( verto , params ) { var conf = this ; conf . params = $ . extend ( { dialog : null , hasVid : false , laData : null , onBroadcast : null , onLaChange : null , onLaRow : null } , params ) ; conf . verto = verto ; conf . serno = CONFMAN _SERNO ++ ; createMainModeratorMethods ( ) ; verto . subscribe ( conf . params . laData . modChannel , { handler : function ( v , e ) { if ( conf . params . onBroadcast ) { conf . params . onBroadcast ( verto , conf , e . data ) ; } } } ) ; verto . subscribe ( conf . params . laData . infoChannel , { handler : function ( v , e ) { if ( typeof ( conf . params . infoCallback ) === "function" ) { conf . params . infoCallback ( v , e ) ; } } } ) ; verto . subscribe ( conf . params . laData . chatChannel , { handler : function ( v , e ) { if ( typeof ( conf . params . chatCallback ) === "function" ) { conf . params . chatCallback ( v , e ) ; } } } ) ; } ; $ . verto . conf . prototype . modCommand = function ( cmd , id , value ) { var conf = this ; conf . verto . rpcClient . call ( "verto.broadcast" , { "eventChannel" : conf . params . laData . modChannel , "data" : { "application" : "conf-control" , "command" : cmd , "id" : id , "value" : value } } ) ; } ; $ . verto . conf . prototype . destroy = function ( ) { var conf = this ; conf . destroyed = true ; conf . params . onBroadcast ( conf . verto , conf , 'destroy' ) ; if ( conf . params . laData . modChannel ) { conf . verto . unsubscribe ( conf . params . laData . modChannel ) ; }
if ( conf . params . laData . chatChannel ) { conf . verto . unsubscribe ( conf . params . laData . chatChannel ) ; }
if ( conf . params . laData . infoChannel ) { conf . verto . unsubscribe ( conf . params . laData . infoChannel ) ; } } ; function createMainModeratorMethods ( ) { $ . verto . conf . prototype . listVideoLayouts = function ( ) { this . modCommand ( "list-videoLayouts" , null , null ) ; } ; $ . verto . conf . prototype . play = function ( file ) { this . modCommand ( "play" , null , file ) ; } ; $ . verto . conf . prototype . stop = function ( ) { this . modCommand ( "stop" , null , "all" ) ; } ; $ . verto . conf . prototype . deaf = function ( memberID ) { this . modCommand ( "deaf" , parseInt ( memberID ) ) ; } ; $ . verto . conf . prototype . undeaf = function ( memberID ) { this . modCommand ( "undeaf" , parseInt ( memberID ) ) ; } ; $ . verto . conf . prototype . record = function ( file ) { this . modCommand ( "recording" , null , [ "start" , file ] ) ; } ; $ . verto . conf . prototype . stopRecord = function ( ) { this . modCommand ( "recording" , null , [ "stop" , "all" ] ) ; } ; $ . verto . conf . prototype . snapshot = function ( file ) { if ( ! this . params . hasVid ) { throw 'Conference has no video' ; }
this . modCommand ( "vid-write-png" , null , file ) ; } ; $ . verto . conf . prototype . setVideoLayout = function ( layout , canvasID ) { if ( ! this . params . hasVid ) { throw 'Conference has no video' ; }
if ( canvasID ) { this . modCommand ( "vid-layout" , null , [ layout , canvasID ] ) ; } else { this . modCommand ( "vid-layout" , null , layout ) ; } } ; $ . verto . conf . prototype . kick = function ( memberID ) { this . modCommand ( "kick" , parseInt ( memberID ) ) ; } ; $ . verto . conf . prototype . muteMic = function ( memberID ) { this . modCommand ( "tmute" , parseInt ( memberID ) ) ; } ; $ . verto . conf . prototype . muteVideo = function ( memberID ) { if ( ! this . params . hasVid ) { throw 'Conference has no video' ; }
this . modCommand ( "tvmute" , parseInt ( memberID ) ) ; } ; $ . verto . conf . prototype . presenter = function ( memberID ) { if ( ! this . params . hasVid ) { throw 'Conference has no video' ; }
this . modCommand ( "vid-res-id" , parseInt ( memberID ) , "presenter" ) ; } ; $ . verto . conf . prototype . videoFloor = function ( memberID ) { if ( ! this . params . hasVid ) { throw 'Conference has no video' ; }
this . modCommand ( "vid-floor" , parseInt ( memberID ) , "force" ) ; } ; $ . verto . conf . prototype . banner = function ( memberID , text ) { if ( ! this . params . hasVid ) { throw 'Conference has no video' ; }
this . modCommand ( "vid-banner" , parseInt ( memberID ) , escape ( text ) ) ; } ; $ . verto . conf . prototype . volumeDown = function ( memberID ) { this . modCommand ( "volume_out" , parseInt ( memberID ) , "down" ) ; } ; $ . verto . conf . prototype . volumeUp = function ( memberID ) { this . modCommand ( "volume_out" , parseInt ( memberID ) , "up" ) ; } ; $ . verto . conf . prototype . gainDown = function ( memberID ) { this . modCommand ( "volume_in" , parseInt ( memberID ) , "down" ) ; } ; $ . verto . conf . prototype . gainUp = function ( memberID ) { this . modCommand ( "volume_in" , parseInt ( memberID ) , "up" ) ; } ; $ . verto . conf . prototype . transfer = function ( memberID , exten ) { this . modCommand ( "transfer" , parseInt ( memberID ) , exten ) ; } ; $ . verto . conf . prototype . sendChat = function ( message , type ) { var conf = this ; conf . verto . rpcClient . call ( "verto.broadcast" , { "eventChannel" : conf . params . laData . chatChannel , "data" : { "action" : "send" , "message" : message , "type" : type } } ) ; } ; }
$ . verto . modfuncs = { } ; $ . verto . confMan = function ( verto , params ) { var confMan = this ; confMan . params = $ . extend ( { tableID : null , statusID : null , mainModID : null , dialog : null , hasVid : false , laData : null , onBroadcast : null , onLaChange : null , onLaRow : null } , params ) ; confMan . verto = verto ; confMan . serno = CONFMAN _SERNO ++ ; confMan . canvasCount = confMan . params . laData . canvasCount ; function genMainMod ( jq ) { var play _id = "play_" + confMan . serno ; var stop _id = "stop_" + confMan . serno ; var recording _id = "recording_" + confMan . serno ; var snapshot _id = "snapshot_" + confMan . serno ; var rec _stop _id = "recording_stop" + confMan . serno ; var div _id = "confman_" + confMan . serno ; var html = "<div id='" + div _id + "'><br>" + "<button class='ctlbtn' id='" + play _id + "'>Play</button>" + "<button class='ctlbtn' id='" + stop _id + "'>Stop</button>" + "<button class='ctlbtn' id='" + recording _id + "'>Record</button>" + "<button class='ctlbtn' id='" + rec _stop _id + "'>Record Stop</button>" +
( confMan . params . hasVid ? "<button class='ctlbtn' id='" + snapshot _id + "'>PNG Snapshot</button>" : "" ) + "<br><br></div>" ; jq . html ( html ) ; $ . verto . modfuncs . change _video _layout = function ( id , canvas _id ) { var val = $ ( "#" + id + " option:selected" ) . text ( ) ; if ( val !== "none" ) { confMan . modCommand ( "vid-layout" , null , [ val , canvas _id ] ) ; } } ; if ( confMan . params . hasVid ) { for ( var j = 0 ; j < confMan . canvasCount ; j ++ ) { var vlayout _id = "confman_vid_layout_" + j + "_" + confMan . serno ; var vlselect _id = "confman_vl_select_" + j + "_" + confMan . serno ; var vlhtml = "<div id='" + vlayout _id + "'><br>" + "<b>Video Layout Canvas " + ( j + 1 ) + "</b> <select onChange='$.verto.modfuncs.change_video_layout(\"" + vlayout _id + "\", \"" + ( j + 1 ) + "\")' id='" + vlselect _id + "'></select> " + "<br><br></div>" ; jq . append ( vlhtml ) ; }
$ ( "#" + snapshot _id ) . click ( function ( ) { var file = prompt ( "Please enter file name" , "" ) ; if ( file ) { confMan . modCommand ( "vid-write-png" , null , file ) ; } } ) ; }
$ ( "#" + play _id ) . click ( function ( ) { var file = prompt ( "Please enter file name" , "" ) ; if ( file ) { confMan . modCommand ( "play" , null , file ) ; } } ) ; $ ( "#" + stop _id ) . click ( function ( ) { confMan . modCommand ( "stop" , null , "all" ) ; } ) ; $ ( "#" + recording _id ) . click ( function ( ) { var file = prompt ( "Please enter file name" , "" ) ; if ( file ) { confMan . modCommand ( "recording" , null , [ "start" , file ] ) ; } } ) ; $ ( "#" + rec _stop _id ) . click ( function ( ) { confMan . modCommand ( "recording" , null , [ "stop" , "all" ] ) ; } ) ; }
function genControls ( jq , rowid ) { var x = parseInt ( rowid ) ; var kick _id = "kick_" + x ; var canvas _in _next _id = "canvas_in_next_" + x ; var canvas _in _prev _id = "canvas_in_prev_" + x ; var canvas _out _next _id = "canvas_out_next_" + x ; var canvas _out _prev _id = "canvas_out_prev_" + x ; var canvas _in _set _id = "canvas_in_set_" + x ; var canvas _out _set _id = "canvas_out_set_" + x ; var layer _set _id = "layer_set_" + x ; var layer _next _id = "layer_next_" + x ; var layer _prev _id = "layer_prev_" + x ; var tmute _id = "tmute_" + x ; var tvmute _id = "tvmute_" + x ; var vbanner _id = "vbanner_" + x ; var tvpresenter _id = "tvpresenter_" + x ; var tvfloor _id = "tvfloor_" + x ; var box _id = "box_" + x ; var gainup _id = "gain_in_up" + x ; var gaindn _id = "gain_in_dn" + x ; var volup _id = "vol_in_up" + x ; var voldn _id = "vol_in_dn" + x ; var transfer _id = "transfer" + x ; var html = "<div id='" + box _id + "'>" ; html += "<b>General Controls</b><hr noshade>" ; html += "<button class='ctlbtn' id='" + kick _id + "'>Kick</button>" + "<button class='ctlbtn' id='" + tmute _id + "'>Mute</button>" + "<button class='ctlbtn' id='" + gainup _id + "'>Gain -</button>" + "<button class='ctlbtn' id='" + gaindn _id + "'>Gain +</button>" + "<button class='ctlbtn' id='" + voldn _id + "'>Vol -</button>" + "<button class='ctlbtn' id='" + volup _id + "'>Vol +</button>" + "<button class='ctlbtn' id='" + transfer _id + "'>Transfer</button>" ; if ( confMan . params . hasVid ) { html += "<br><br><b>Video Controls</b><hr noshade>" ; html += "<button class='ctlbtn' id='" + tvmute _id + "'>VMute</button>" + "<button class='ctlbtn' id='" + tvpresenter _id + "'>Presenter</button>" + "<button class='ctlbtn' id='" + tvfloor _id + "'>Vid Floor</button>" + "<button class='ctlbtn' id='" + vbanner _id + "'>Banner</button>" ; if ( confMan . canvasCount > 1 ) { html += "<br><br><b>Canvas Controls</b><hr noshade>" + "<button class='ctlbtn' id='" + canvas _in _set _id + "'>Set Input Canvas</button>" + "<button class='ctlbtn' id='" + canvas _in _prev _id + "'>Prev Input Canvas</button>" + "<button class='ctlbtn' id='" + canvas _in _next _id + "'>Next Input Canvas</button>" + "<br>" + "<button class='ctlbtn' id='" + canvas _out _set _id + "'>Set Watching Canvas</button>" + "<button class='ctlbtn' id='" + canvas _out _prev _id + "'>Prev Watching Canvas</button>" + "<button class='ctlbtn' id='" + canvas _out _next _id + "'>Next Watching Canvas</button>" ; }
html += "<br>" + "<button class='ctlbtn' id='" + layer _set _id + "'>Set Layer</button>" + "<button class='ctlbtn' id='" + layer _prev _id + "'>Prev Layer</button>" + "<button class='ctlbtn' id='" + layer _next _id + "'>Next Layer</button>" + "</div>" ; }
jq . html ( html ) ; if ( ! jq . data ( "mouse" ) ) { $ ( "#" + box _id ) . hide ( ) ; }
jq . mouseover ( function ( e ) { jq . data ( { "mouse" : true } ) ; $ ( "#" + box _id ) . show ( ) ; } ) ; jq . mouseout ( function ( e ) { jq . data ( { "mouse" : false } ) ; $ ( "#" + box _id ) . hide ( ) ; } ) ; $ ( "#" + transfer _id ) . click ( function ( ) { var xten = prompt ( "Enter Extension" ) ; if ( xten ) { confMan . modCommand ( "transfer" , x , xten ) ; } } ) ; $ ( "#" + kick _id ) . click ( function ( ) { confMan . modCommand ( "kick" , x ) ; } ) ; $ ( "#" + layer _set _id ) . click ( function ( ) { var cid = prompt ( "Please enter layer ID" , "" ) ; if ( cid ) { confMan . modCommand ( "vid-layer" , x , cid ) ; } } ) ; $ ( "#" + layer _next _id ) . click ( function ( ) { confMan . modCommand ( "vid-layer" , x , "next" ) ; } ) ; $ ( "#" + layer _prev _id ) . click ( function ( ) { confMan . modCommand ( "vid-layer" , x , "prev" ) ; } ) ; $ ( "#" + canvas _in _set _id ) . click ( function ( ) { var cid = prompt ( "Please enter canvas ID" , "" ) ; if ( cid ) { confMan . modCommand ( "vid-canvas" , x , cid ) ; } } ) ; $ ( "#" + canvas _out _set _id ) . click ( function ( ) { var cid = prompt ( "Please enter canvas ID" , "" ) ; if ( cid ) { confMan . modCommand ( "vid-watching-canvas" , x , cid ) ; } } ) ; $ ( "#" + canvas _in _next _id ) . click ( function ( ) { confMan . modCommand ( "vid-canvas" , x , "next" ) ; } ) ; $ ( "#" + canvas _in _prev _id ) . click ( function ( ) { confMan . modCommand ( "vid-canvas" , x , "prev" ) ; } ) ; $ ( "#" + canvas _out _next _id ) . click ( function ( ) { confMan . modCommand ( "vid-watching-canvas" , x , "next" ) ; } ) ; $ ( "#" + canvas _out _prev _id ) . click ( function ( ) { confMan . modCommand ( "vid-watching-canvas" , x , "prev" ) ; } ) ; $ ( "#" + tmute _id ) . click ( function ( ) { confMan . modCommand ( "tmute" , x ) ; } ) ; if ( confMan . params . hasVid ) { $ ( "#" + tvmute _id ) . click ( function ( ) { confMan . modCommand ( "tvmute" , x ) ; } ) ; $ ( "#" + tvpresenter _id ) . click ( function ( ) { confMan . modCommand ( "vid-res-id" , x , "presenter" ) ; } ) ; $ ( "#" + tvfloor _id ) . click ( function ( ) { confMan . modCommand ( "vid-floor" , x , "force" ) ; } ) ; $ ( "#" + vbanner _id ) . click ( function ( ) { var text = prompt ( "Please enter text" , "" ) ; if ( text ) { confMan . modCommand ( "vid-banner" , x , escape ( text ) ) ; } } ) ; }
$ ( "#" + gainup _id ) . click ( function ( ) { confMan . modCommand ( "volume_in" , x , "up" ) ; } ) ; $ ( "#" + gaindn _id ) . click ( function ( ) { confMan . modCommand ( "volume_in" , x , "down" ) ; } ) ; $ ( "#" + volup _id ) . click ( function ( ) { confMan . modCommand ( "volume_out" , x , "up" ) ; } ) ; $ ( "#" + voldn _id ) . click ( function ( ) { confMan . modCommand ( "volume_out" , x , "down" ) ; } ) ; return html ; }
var atitle = "" ; var awidth = 0 ; verto . subscribe ( confMan . params . laData . infoChannel , { handler : function ( v , e ) { if ( typeof ( confMan . params . infoCallback ) === "function" ) { confMan . params . infoCallback ( v , e ) ; } } } ) ; verto . subscribe ( confMan . params . laData . chatChannel , { handler : function ( v , e ) { if ( typeof ( confMan . params . chatCallback ) === "function" ) { confMan . params . chatCallback ( v , e ) ; } } } ) ; if ( confMan . params . laData . role === "moderator" ) { atitle = "Action" ; awidth = 600 ; if ( confMan . params . mainModID ) { genMainMod ( $ ( confMan . params . mainModID ) ) ; $ ( confMan . params . displayID ) . html ( "Moderator Controls Ready<br><br>" ) ; } else { $ ( confMan . params . mainModID ) . html ( "" ) ; }
verto . subscribe ( confMan . params . laData . modChannel , { handler : function ( v , e ) { if ( confMan . params . onBroadcast ) { confMan . params . onBroadcast ( verto , confMan , e . data ) ; }
if ( e . data [ "conf-command" ] === "list-videoLayouts" ) { for ( var j = 0 ; j < confMan . canvasCount ; j ++ ) { var vlselect _id = "#confman_vl_select_" + j + "_" + confMan . serno ; var vlayout _id = "#confman_vid_layout_" + j + "_" + confMan . serno ; var x = 0 ; var options ; $ ( vlselect _id ) . selectmenu ( { } ) ; $ ( vlselect _id ) . selectmenu ( "enable" ) ; $ ( vlselect _id ) . empty ( ) ; $ ( vlselect _id ) . append ( new Option ( "Choose a Layout" , "none" ) ) ; if ( e . data . responseData ) { var rdata = [ ] ; for ( var i in e . data . responseData ) { rdata . push ( e . data . responseData [ i ] . name ) ; }
options = rdata . sort ( function ( a , b ) { var ga = a . substring ( 0 , 6 ) == "group:" ? true : false ; var gb = b . substring ( 0 , 6 ) == "group:" ? true : false ; if ( ( ga || gb ) && ga != gb ) { return ga ? - 1 : 1 ; }
return ( ( a == b ) ? 0 : ( ( a > b ) ? 1 : - 1 ) ) ; } ) ; for ( var i in options ) { $ ( vlselect _id ) . append ( new Option ( options [ i ] , options [ i ] ) ) ; x ++ ; } }
if ( x ) { $ ( vlselect _id ) . selectmenu ( 'refresh' , true ) ; } else { $ ( vlayout _id ) . hide ( ) ; } } } else { if ( ! confMan . destroyed && confMan . params . displayID ) { $ ( confMan . params . displayID ) . html ( e . data . response + "<br><br>" ) ; if ( confMan . lastTimeout ) { clearTimeout ( confMan . lastTimeout ) ; confMan . lastTimeout = 0 ; }
confMan . lastTimeout = setTimeout ( function ( ) { $ ( confMan . params . displayID ) . html ( confMan . destroyed ? "" : "Moderator Controls Ready<br><br>" ) ; } , 4000 ) ; } } } } ) ; if ( confMan . params . hasVid ) { confMan . modCommand ( "list-videoLayouts" , null , null ) ; } }
var row _callback = null ; if ( confMan . params . laData . role === "moderator" ) { row _callback = function ( nRow , aData , iDisplayIndex , iDisplayIndexFull ) { if ( ! aData [ 5 ] ) { var $row = $ ( 'td:eq(5)' , nRow ) ; genControls ( $row , aData ) ; if ( confMan . params . onLaRow ) { confMan . params . onLaRow ( verto , confMan , $row , aData ) ; } } } ; }
confMan . lt = new $ . verto . liveTable ( verto , confMan . params . laData . laChannel , confMan . params . laData . laName , $ ( confMan . params . tableID ) , { subParams : { callID : confMan . params . dialog ? confMan . params . dialog . callID : null } , "onChange" : function ( obj , args ) { $ ( confMan . params . statusID ) . text ( "Conference Members: " + " (" + obj . arrayLen ( ) + " Total)" ) ; if ( confMan . params . onLaChange ) { confMan . params . onLaChange ( verto , confMan , $ . verto . enum . confEvent . laChange , obj , args ) ; } } , "aaData" : [ ] , "aoColumns" : [ { "sTitle" : "ID" , "sWidth" : "50" } , { "sTitle" : "Number" , "sWidth" : "250" } , { "sTitle" : "Name" , "sWidth" : "250" } , { "sTitle" : "Codec" , "sWidth" : "100" } , { "sTitle" : "Status" , "sWidth" : confMan . params . hasVid ? "200px" : "150px" } , { "sTitle" : atitle , "sWidth" : awidth , } ] , "bAutoWidth" : true , "bDestroy" : true , "bSort" : false , "bInfo" : false , "bFilter" : false , "bLengthChange" : false , "bPaginate" : false , "iDisplayLength" : 1400 , "oLanguage" : { "sEmptyTable" : "The Conference is Empty....." } , "fnRowCallback" : row _callback } ) ; } ; $ . verto . confMan . prototype . modCommand = function ( cmd , id , value ) { var confMan = this ; confMan . verto . rpcClient . call ( "verto.broadcast" , { "eventChannel" : confMan . params . laData . modChannel , "data" : { "application" : "conf-control" , "command" : cmd , "id" : id , "value" : value } } ) ; } ; $ . verto . confMan . prototype . sendChat = function ( message , type ) { var confMan = this ; confMan . verto . rpcClient . call ( "verto.broadcast" , { "eventChannel" : confMan . params . laData . chatChannel , "data" : { "action" : "send" , "message" : message , "type" : type } } ) ; } ; $ . verto . confMan . prototype . destroy = function ( ) { var confMan = this ; confMan . destroyed = true ; if ( confMan . lt ) { confMan . lt . destroy ( ) ; }
if ( confMan . params . laData . chatChannel ) { confMan . verto . unsubscribe ( confMan . params . laData . chatChannel ) ; }
if ( confMan . params . laData . modChannel ) { confMan . verto . unsubscribe ( confMan . params . laData . modChannel ) ; }
if ( confMan . params . mainModID ) { $ ( confMan . params . mainModID ) . html ( "" ) ; } } ; $ . verto . dialog = function ( direction , verto , params ) { var dialog = this ; dialog . params = $ . extend ( { useVideo : verto . options . useVideo , useStereo : verto . options . useStereo , screenShare : false , useCamera : false , useMic : verto . options . deviceParams . useMic , useMicLabel : verto . options . deviceParams . useMicLabel , useSpeak : verto . options . deviceParams . useSpeak , tag : verto . options . tag , localTag : verto . options . localTag , login : verto . options . login , videoParams : verto . options . videoParams , useStream : verto . options . useStream , } , params ) ; if ( ! dialog . params . screenShare ) { dialog . params . useCamera = verto . options . deviceParams . useCamera ; dialog . params . useCameraLabel = verto . options . deviceParams . useCameraLabel ; }
dialog . verto = verto ; dialog . direction = direction ; dialog . lastState = null ; dialog . state = dialog . lastState = $ . verto . enum . state . new ; dialog . callbacks = verto . callbacks ; dialog . answered = false ; dialog . attach = params . attach || false ; dialog . screenShare = params . screenShare || false ; dialog . useCamera = dialog . params . useCamera ; dialog . useCameraLabel = dialog . params . useCameraLabel ; dialog . useMic = dialog . params . useMic ; dialog . useMicLabel = dialog . params . useMicLabel ; dialog . useSpeak = dialog . params . useSpeak ; if ( dialog . params . callID ) { dialog . callID = dialog . params . callID ; } else { dialog . callID = dialog . params . callID = generateGUID ( ) ; }
if ( typeof ( dialog . params . tag ) === "function" ) { dialog . params . tag = dialog . params . tag ( ) ; }
if ( dialog . params . tag ) { dialog . audioStream = document . getElementById ( dialog . params . tag ) ; if ( dialog . params . useVideo ) { dialog . videoStream = dialog . audioStream ; } }
if ( dialog . params . localTag ) { dialog . localVideo = document . getElementById ( dialog . params . localTag ) ; }
dialog . verto . dialogs [ dialog . callID ] = dialog ; var RTCcallbacks = { } ; if ( dialog . direction == $ . verto . enum . direction . inbound ) { if ( dialog . params . display _direction === "outbound" ) { dialog . params . remote _caller _id _name = dialog . params . caller _id _name ; dialog . params . remote _caller _id _number = dialog . params . caller _id _number ; } else { dialog . params . remote _caller _id _name = dialog . params . callee _id _name ; dialog . params . remote _caller _id _number = dialog . params . callee _id _number ; }
if ( ! dialog . params . remote _caller _id _name ) { dialog . params . remote _caller _id _name = "Nobody" ; }
if ( ! dialog . params . remote _caller _id _number ) { dialog . params . remote _caller _id _number = "UNKNOWN" ; }
RTCcallbacks . onMessage = function ( rtc , msg ) { console . debug ( msg ) ; } ; RTCcallbacks . onAnswerSDP = function ( rtc , sdp ) { console . error ( "answer sdp" , sdp ) ; } ; } else { dialog . params . remote _caller _id _name = "Outbound Call" ; dialog . params . remote _caller _id _number = dialog . params . destination _number ; }
RTCcallbacks . onICESDP = function ( rtc ) { console . log ( "RECV " + rtc . type + " SDP" , rtc . mediaData . SDP ) ; if ( dialog . state == $ . verto . enum . state . requesting || dialog . state == $ . verto . enum . state . answering || dialog . state == $ . verto . enum . state . active ) { location . reload ( ) ; return ; }
if ( rtc . type == "offer" ) { if ( dialog . state == $ . verto . enum . state . active ) { dialog . setState ( $ . verto . enum . state . requesting ) ; dialog . sendMethod ( "verto.attach" , { sdp : rtc . mediaData . SDP } ) ; } else { dialog . setState ( $ . verto . enum . state . requesting ) ; dialog . sendMethod ( "verto.invite" , { sdp : rtc . mediaData . SDP } ) ; } } else { dialog . setState ( $ . verto . enum . state . answering ) ; dialog . sendMethod ( dialog . attach ? "verto.attach" : "verto.answer" , { sdp : dialog . rtc . mediaData . SDP } ) ; } } ; RTCcallbacks . onICE = function ( rtc ) { if ( rtc . type == "offer" ) { console . log ( "offer" , rtc . mediaData . candidate ) ; return ; } } ; RTCcallbacks . onStream = function ( rtc , stream ) { if ( dialog . callbacks . permissionCallback && typeof dialog . callbacks . permissionCallback . onGranted === 'function' ) { dialog . callbacks . permissionCallback . onGranted ( stream ) ; }
else if ( dialog . verto . options . permissionCallback && typeof dialog . verto . options . permissionCallback . onGranted === 'function' ) { dialog . verto . options . permissionCallback . onGranted ( stream ) ; }
console . log ( "stream started" ) ; } ; RTCcallbacks . onRemoteStream = function ( rtc , stream ) { if ( typeof dialog . callbacks . onRemoteStream === 'function' ) { dialog . callbacks . onRemoteStream ( stream , dialog ) ; }
console . log ( "remote stream started" ) ; } ; RTCcallbacks . onError = function ( e ) { if ( dialog . callbacks . permissionCallback && typeof dialog . callbacks . permissionCallback . onDenied === 'function' ) { dialog . callbacks . permissionCallback . onDenied ( ) ; }
else if ( dialog . verto . options . permissionCallback && typeof dialog . verto . options . permissionCallback . onDenied === 'function' ) { dialog . verto . options . permissionCallback . onDenied ( ) ; }
console . error ( "ERROR:" , e ) ; dialog . hangup ( { cause : "Device or Permission Error" } ) ; } ; dialog . rtc = new $ . FSRTC ( { callbacks : RTCcallbacks , localVideo : dialog . screenShare ? null : dialog . localVideo , useVideo : dialog . params . useVideo ? dialog . videoStream : null , useAudio : dialog . audioStream , useStereo : dialog . params . useStereo , videoParams : dialog . params . videoParams , audioParams : verto . options . audioParams , iceServers : verto . options . iceServers , screenShare : dialog . screenShare , useCamera : dialog . useCamera , useCameraLabel : dialog . useCameraLabel , useMic : dialog . useMic , useMicLabel : dialog . useMicLabel , useSpeak : dialog . useSpeak , turnServer : verto . options . turnServer , useStream : dialog . params . useStream } ) ; dialog . rtc . verto = dialog . verto ; if ( dialog . direction == $ . verto . enum . direction . inbound ) { if ( dialog . attach ) { dialog . answer ( ) ; } else { dialog . ring ( ) ; } } } ; $ . verto . dialog . prototype . invite = function ( ) { var dialog = this ; dialog . rtc . call ( ) ; } ; $ . verto . dialog . prototype . sendMethod = function ( method , obj ) { var dialog = this ; obj . dialogParams = { } ; for ( var i in dialog . params ) { if ( i == "sdp" && method != "verto.invite" && method != "verto.attach" ) { continue ; }
if ( ( obj . noDialogParams && i != "callID" ) ) { continue ; }
obj . dialogParams [ i ] = dialog . params [ i ] ; }
delete obj . noDialogParams ; dialog . verto . rpcClient . call ( method , obj , function ( e ) { dialog . processReply ( method , true , e ) ; } , function ( e ) { dialog . processReply ( method , false , e ) ; } ) ; } ; function checkStateChange ( oldS , newS ) { if ( newS == $ . verto . enum . state . purge || $ . verto . enum . states [ oldS . name ] [ newS . name ] ) { return true ; }
return false ; }
function find _name ( id ) { for ( var i in $ . verto . audioOutDevices ) { var source = $ . verto . audioOutDevices [ i ] ; if ( source . id === id ) { return ( source . label ) ; } }
return id ; }
$ . verto . dialog . prototype . setAudioPlaybackDevice = function ( sinkId , callback , arg ) { var dialog = this ; var element = dialog . audioStream ; if ( typeof element . sinkId !== 'undefined' ) { var devname = find _name ( sinkId ) ; console . info ( "Dialog: " + dialog . callID + " Setting speaker:" , element , devname ) ; element . setSinkId ( sinkId ) . then ( function ( ) { console . log ( "Dialog: " + dialog . callID + ' Success, audio output device attached: ' + sinkId ) ; if ( callback ) { callback ( true , devname , arg ) ; } } ) . catch ( function ( error ) { var errorMessage = error ; if ( error . name === 'SecurityError' ) { errorMessage = "Dialog: " + dialog . callID + ' You need to use HTTPS for selecting audio output ' + 'device: ' + error ; }
if ( callback ) { callback ( false , null , arg ) ; }
console . error ( errorMessage ) ; } ) ; } else { console . warn ( "Dialog: " + dialog . callID + ' Browser does not support output device selection.' ) ; if ( callback ) { callback ( false , null , arg ) ; } } }
$ . verto . dialog . prototype . setState = function ( state ) { var dialog = this ; if ( dialog . state == $ . verto . enum . state . ringing ) { dialog . stopRinging ( ) ; }
if ( dialog . state == state || ! checkStateChange ( dialog . state , state ) ) { console . error ( "Dialog " + dialog . callID + ": INVALID state change from " + dialog . state . name + " to " + state . name ) ; dialog . hangup ( ) ; return false ; }
console . log ( "Dialog " + dialog . callID + ": state change from " + dialog . state . name + " to " + state . name ) ; dialog . lastState = dialog . state ; dialog . state = state ; if ( dialog . callbacks . onDialogState ) { dialog . callbacks . onDialogState ( this ) ; }
switch ( dialog . state ) { case $ . verto . enum . state . early : case $ . verto . enum . state . active : var speaker = dialog . useSpeak ; console . info ( "Using Speaker: " , speaker ) ; if ( speaker && speaker !== "any" && speaker !== "none" ) { setTimeout ( function ( ) { dialog . setAudioPlaybackDevice ( speaker ) ; } , 500 ) ; }
break ; case $ . verto . enum . state . trying : setTimeout ( function ( ) { if ( dialog . state == $ . verto . enum . state . trying ) { dialog . setState ( $ . verto . enum . state . hangup ) ; } } , 30000 ) ; break ; case $ . verto . enum . state . purge : dialog . setState ( $ . verto . enum . state . destroy ) ; break ; case $ . verto . enum . state . hangup : if ( dialog . lastState . val > $ . verto . enum . state . requesting . val && dialog . lastState . val < $ . verto . enum . state . hangup . val ) { dialog . sendMethod ( "verto.bye" , { } ) ; }
dialog . setState ( $ . verto . enum . state . destroy ) ; break ; case $ . verto . enum . state . destroy : if ( typeof ( dialog . verto . options . tag ) === "function" ) { $ ( '#' + dialog . params . tag ) . remove ( ) ; }
delete dialog . verto . dialogs [ dialog . callID ] ; if ( dialog . params . screenShare ) { dialog . rtc . stopPeer ( ) ; } else { dialog . rtc . stop ( ) ; }
break ; }
return true ; } ; $ . verto . dialog . prototype . processReply = function ( method , success , e ) { var dialog = this ; switch ( method ) { case "verto.answer" : case "verto.attach" : if ( success ) { dialog . setState ( $ . verto . enum . state . active ) ; } else { dialog . hangup ( ) ; }
break ; case "verto.invite" : if ( success ) { dialog . setState ( $ . verto . enum . state . trying ) ; } else { dialog . setState ( $ . verto . enum . state . destroy ) ; }
break ; case "verto.bye" : dialog . hangup ( ) ; break ; case "verto.modify" : if ( e . holdState ) { if ( e . holdState == "held" ) { if ( dialog . state != $ . verto . enum . state . held ) { dialog . setState ( $ . verto . enum . state . held ) ; } } else if ( e . holdState == "active" ) { if ( dialog . state != $ . verto . enum . state . active ) { dialog . setState ( $ . verto . enum . state . active ) ; } } }
if ( success ) { }
break ; default : break ; } } ; $ . verto . dialog . prototype . hangup = function ( params ) { var dialog = this ; if ( params ) { if ( params . causeCode ) { dialog . causeCode = params . causeCode ; }
if ( params . cause ) { dialog . cause = params . cause ; } }
if ( ! dialog . cause && ! dialog . causeCode ) { dialog . cause = "NORMAL_CLEARING" ; }
if ( dialog . state . val >= $ . verto . enum . state . new . val && dialog . state . val < $ . verto . enum . state . hangup . val ) { dialog . setState ( $ . verto . enum . state . hangup ) ; } else if ( dialog . state . val < $ . verto . enum . state . destroy ) { dialog . setState ( $ . verto . enum . state . destroy ) ; } } ; $ . verto . dialog . prototype . stopRinging = function ( ) { var dialog = this ; if ( dialog . verto . ringer ) { dialog . verto . ringer . stop ( ) ; } } ; $ . verto . dialog . prototype . indicateRing = function ( ) { var dialog = this ; if ( dialog . verto . ringer ) { dialog . verto . ringer . attr ( "src" , dialog . verto . options . ringFile ) [ 0 ] . play ( ) ; setTimeout ( function ( ) { dialog . stopRinging ( ) ; if ( dialog . state == $ . verto . enum . state . ringing ) { dialog . indicateRing ( ) ; } } , dialog . verto . options . ringSleep ) ; } } ; $ . verto . dialog . prototype . ring = function ( ) { var dialog = this ; dialog . setState ( $ . verto . enum . state . ringing ) ; dialog . indicateRing ( ) ; } ; $ . verto . dialog . prototype . useVideo = function ( on ) { var dialog = this ; dialog . params . useVideo = on ; if ( on ) { dialog . videoStream = dialog . audioStream ; } else { dialog . videoStream = null ; }
dialog . rtc . useVideo ( dialog . videoStream , dialog . localVideo ) ; } ; $ . verto . dialog . prototype . setMute = function ( what ) { var dialog = this ; return dialog . rtc . setMute ( what ) ; } ; $ . verto . dialog . prototype . getMute = function ( ) { var dialog = this ; return dialog . rtc . getMute ( ) ; } ; $ . verto . dialog . prototype . setVideoMute = function ( what ) { var dialog = this ; return dialog . rtc . setVideoMute ( what ) ; } ; $ . verto . dialog . prototype . getVideoMute = function ( ) { var dialog = this ; return dialog . rtc . getVideoMute ( ) ; } ; $ . verto . dialog . prototype . useStereo = function ( on ) { var dialog = this ; dialog . params . useStereo = on ; dialog . rtc . useStereo ( on ) ; } ; $ . verto . dialog . prototype . dtmf = function ( digits ) { var dialog = this ; if ( digits ) { dialog . sendMethod ( "verto.info" , { dtmf : digits } ) ; } } ; $ . verto . dialog . prototype . rtt = function ( obj ) { var dialog = this ; var pobj = { } ; if ( ! obj ) { return false ; }
pobj . code = obj . code ; pobj . chars = obj . chars ; if ( pobj . chars || pobj . code ) { dialog . sendMethod ( "verto.info" , { txt : obj , noDialogParams : true } ) ; } } ; $ . verto . dialog . prototype . transfer = function ( dest , params ) { var dialog = this ; if ( dest ) { dialog . sendMethod ( "verto.modify" , { action : "transfer" , destination : dest , params : params } ) ; } } ; $ . verto . dialog . prototype . replace = function ( replaceCallID , params ) { var dialog = this ; if ( replaceCallID ) { dialog . sendMethod ( "verto.modify" , { action : "replace" , replaceCallID : replaceCallID , params : params } ) ; } } ; $ . verto . dialog . prototype . hold = function ( params ) { var dialog = this ; dialog . sendMethod ( "verto.modify" , { action : "hold" , params : params } ) ; } ; $ . verto . dialog . prototype . unhold = function ( params ) { var dialog = this ; dialog . sendMethod ( "verto.modify" , { action : "unhold" , params : params } ) ; } ; $ . verto . dialog . prototype . toggleHold = function ( params ) { var dialog = this ; dialog . sendMethod ( "verto.modify" , { action : "toggleHold" , params : params } ) ; } ; $ . verto . dialog . prototype . message = function ( msg ) { var dialog = this ; var err = 0 ; msg . from = dialog . params . login ; if ( ! msg . to ) { console . error ( "Missing To" ) ; err ++ ; }
if ( ! msg . body ) { console . error ( "Missing Body" ) ; err ++ ; }
if ( err ) { return false ; }
dialog . sendMethod ( "verto.info" , { msg : msg } ) ; return true ; } ; $ . verto . dialog . prototype . answer = function ( params ) { var dialog = this ; if ( ! dialog . answered ) { if ( ! params ) { params = { } ; }
params . sdp = dialog . params . sdp ; if ( params ) { if ( params . useVideo ) { dialog . useVideo ( true ) ; }
dialog . params . callee _id _name = params . callee _id _name ; dialog . params . callee _id _number = params . callee _id _number ; if ( params . useCamera ) { dialog . useCamera = params . useCamera ; dialog . useCameraLabel = params . useCameraLabel ; }
if ( params . useMic ) { dialog . useMic = params . useMic ; dialog . useMic = params . useMicLabel ; }
if ( params . useSpeak ) { dialog . useSpeak = params . useSpeak ; } }
dialog . rtc . createAnswer ( params ) ; dialog . answered = true ; } } ; $ . verto . dialog . prototype . handleAnswer = function ( params ) { var dialog = this ; dialog . gotAnswer = true ; if ( dialog . state . val >= $ . verto . enum . state . active . val ) { return ; }
if ( dialog . state . val >= $ . verto . enum . state . early . val ) { dialog . setState ( $ . verto . enum . state . active ) ; } else { if ( dialog . gotEarly ) { console . log ( "Dialog " + dialog . callID + " Got answer while still establishing early media, delaying..." ) ; } else { console . log ( "Dialog " + dialog . callID + " Answering Channel" ) ; dialog . rtc . answer ( params . sdp , function ( ) { dialog . setState ( $ . verto . enum . state . active ) ; } , function ( e ) { console . error ( e ) ; dialog . hangup ( ) ; } ) ; console . log ( "Dialog " + dialog . callID + "ANSWER SDP" , params . sdp ) ; } } } ; $ . verto . dialog . prototype . cidString = function ( enc ) { var dialog = this ; var party = dialog . params . remote _caller _id _name + ( enc ? " <" : " <" ) + dialog . params . remote _caller _id _number + ( enc ? ">" : ">" ) ; return party ; } ; $ . verto . dialog . prototype . sendMessage = function ( msg , params ) { var dialog = this ; if ( dialog . callbacks . onMessage ) { dialog . callbacks . onMessage ( dialog . verto , dialog , msg , params ) ; } } ; $ . verto . dialog . prototype . handleInfo = function ( params ) { var dialog = this ; dialog . sendMessage ( $ . verto . enum . message . info , params ) ; } ; $ . verto . dialog . prototype . handleDisplay = function ( params ) { var dialog = this ; if ( params . display _name ) { dialog . params . remote _caller _id _name = params . display _name ; }
if ( params . display _number ) { dialog . params . remote _caller _id _number = params . display _number ; }
dialog . sendMessage ( $ . verto . enum . message . display , { } ) ; } ; $ . verto . dialog . prototype . handleMedia = function ( params ) { var dialog = this ; if ( dialog . state . val >= $ . verto . enum . state . early . val ) { return ; }
dialog . gotEarly = true ; dialog . rtc . answer ( params . sdp , function ( ) { console . log ( "Dialog " + dialog . callID + "Establishing early media" ) ; dialog . setState ( $ . verto . enum . state . early ) ; if ( dialog . gotAnswer ) { console . log ( "Dialog " + dialog . callID + "Answering Channel" ) ; dialog . setState ( $ . verto . enum . state . active ) ; } } , function ( e ) { console . error ( e ) ; dialog . hangup ( ) ; } ) ; console . log ( "Dialog " + dialog . callID + "EARLY SDP" , params . sdp ) ; } ; $ . verto . ENUM = function ( s ) { var i = 0 , o = { } ; s . split ( " " ) . map ( function ( x ) { o [ x ] = { name : x , val : i ++ } ; } ) ; return Object . freeze ( o ) ; } ; $ . verto . enum = { } ; $ . verto . enum . states = Object . freeze ( { new : { requesting : 1 , recovering : 1 , ringing : 1 , destroy : 1 , answering : 1 , hangup : 1 } , requesting : { trying : 1 , hangup : 1 , active : 1 } , recovering : { answering : 1 , hangup : 1 } , trying : { active : 1 , early : 1 , hangup : 1 } , ringing : { answering : 1 , hangup : 1 } , answering : { active : 1 , hangup : 1 } , active : { answering : 1 , requesting : 1 , hangup : 1 , held : 1 } , held : { hangup : 1 , active : 1 } , early : { hangup : 1 , active : 1 } , hangup : { destroy : 1 } , destroy : { } , purge : { destroy : 1 } } ) ; $ . verto . enum . state = $ . verto . ENUM ( "new requesting trying recovering ringing answering early active held hangup destroy purge" ) ; $ . verto . enum . direction = $ . verto . ENUM ( "inbound outbound" ) ; $ . verto . enum . message = $ . verto . ENUM ( "display info pvtEvent clientReady" ) ; $ . verto . enum = Object . freeze ( $ . verto . enum ) ; $ . verto . saved = [ ] ; $ . verto . unloadJobs = [ ] ; var unloadEventName = 'beforeunload' ; var iOS = [ 'iPad' , 'iPhone' , 'iPod' ] . indexOf ( navigator . platform ) >= 0 ; if ( iOS ) { unloadEventName = 'pagehide' ; }
$ ( window ) . bind ( unloadEventName , function ( ) { for ( var f in $ . verto . unloadJobs ) { $ . verto . unloadJobs [ f ] ( ) ; }
if ( $ . verto . haltClosure )
return $ . verto . haltClosure ( ) ; for ( var i in $ . verto . saved ) { var verto = $ . verto . saved [ i ] ; if ( verto ) { verto . purge ( ) ; verto . logout ( ) ; } }
return $ . verto . warnOnUnload ; } ) ; $ . verto . videoDevices = [ ] ; $ . verto . audioInDevices = [ ] ; $ . verto . audioOutDevices = [ ] ; var checkDevices = function ( runtime ) { console . info ( "enumerating devices" ) ; var aud _in = [ ] , aud _out = [ ] , vid = [ ] ; var has _video = 0 , has _audio = 0 ; var Xstream ; function gotDevices ( deviceInfos ) { for ( var i = 0 ; i !== deviceInfos . length ; ++ i ) { var deviceInfo = deviceInfos [ i ] ; var text = "" ; console . log ( deviceInfo ) ; console . log ( deviceInfo . kind + ": " + deviceInfo . label + " id = " + deviceInfo . deviceId ) ; if ( deviceInfo . kind === 'audioinput' ) { text = deviceInfo . label || 'microphone ' + ( aud _in . length + 1 ) ; aud _in . push ( { id : deviceInfo . deviceId , kind : "audio_in" , label : text } ) ; } else if ( deviceInfo . kind === 'audiooutput' ) { text = deviceInfo . label || 'speaker ' + ( aud _out . length + 1 ) ; aud _out . push ( { id : deviceInfo . deviceId , kind : "audio_out" , label : text } ) ; } else if ( deviceInfo . kind === 'videoinput' ) { text = deviceInfo . label || 'camera ' + ( vid . length + 1 ) ; vid . push ( { id : deviceInfo . deviceId , kind : "video" , label : text } ) ; } else { console . log ( 'Some other kind of source/device: ' , deviceInfo ) ; } }
$ . verto . videoDevices = vid ; $ . verto . audioInDevices = aud _in ; $ . verto . audioOutDevices = aud _out ; console . info ( "Audio IN Devices" , $ . verto . audioInDevices ) ; console . info ( "Audio Out Devices" , $ . verto . audioOutDevices ) ; console . info ( "Video Devices" , $ . verto . videoDevices ) ; if ( Xstream ) { Xstream . getTracks ( ) . forEach ( function ( track ) { track . stop ( ) ; } ) ; }
if ( runtime ) { runtime ( true ) ; } }
function handleError ( error ) { console . log ( 'device enumeration error: ' , error ) ; if ( runtime ) runtime ( false ) ; }
function checkTypes ( devs ) { for ( var i = 0 ; i !== devs . length ; ++ i ) { if ( devs [ i ] . kind === 'audioinput' ) { has _audio ++ ; } else if ( devs [ i ] . kind === 'videoinput' ) { has _video ++ ; } }
2019-07-25 19:48:25 +00:00
navigator . mediaDevices . getUserMedia ( { audio : ( has _audio > 0 ? true : false ) , video : ( has _video > 0 ? true : false ) } ) . then ( function ( stream ) { Xstream = stream ; navigator . mediaDevices . enumerateDevices ( ) . then ( gotDevices ) . catch ( handleError ) ; } ) . catch ( function ( err ) { console . log ( "The following error occurred: " + err . name ) ; } ) ; }
2019-06-03 17:00:33 +00:00
navigator . mediaDevices . enumerateDevices ( ) . then ( checkTypes ) . catch ( handleError ) ; } ; $ . verto . refreshDevices = function ( runtime ) { checkDevices ( runtime ) ; }
$ . verto . init = function ( obj , runtime ) { if ( ! obj ) { obj = { } ; }
if ( ! obj . skipPermCheck && ! obj . skipDeviceCheck ) { $ . FSRTC . checkPerms ( function ( status ) { checkDevices ( runtime ) ; } , true , true ) ; } else if ( obj . skipPermCheck && ! obj . skipDeviceCheck ) { checkDevices ( runtime ) ; } else if ( ! obj . skipPermCheck && obj . skipDeviceCheck ) { $ . FSRTC . checkPerms ( function ( status ) { runtime ( status ) ; } , true , true ) ; } else { runtime ( null ) ; } }
$ . verto . genUUID = function ( ) { return generateGUID ( ) ; } } ) ( jQuery ) ; ( function ( f ) { if ( typeof exports === "object" && typeof module !== "undefined" ) { module . exports = f ( ) } else if ( typeof define === "function" && define . amd ) { define ( [ ] , f ) } else { var g ; if ( typeof window !== "undefined" ) { g = window } else if ( typeof global !== "undefined" ) { g = global } else if ( typeof self !== "undefined" ) { g = self } else { g = this } g . adapter = f ( ) } } ) ( function ( ) { var define , module , exports ; return ( 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 < t . length ; i ++ ) o ( t [ i ] ) ; return o } return r } ) ( ) ( { 1 : [ function ( require , module , exports ) { 'use strict' ; var _adapter _factory = require ( './adapter_factory.js' ) ; var adapter = ( 0 , _adapter _factory . adapterFactory ) ( { window : window } ) ; module . exports = adapter ; } , { "./adapter_factory.js" : 2 } ] , 2 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; exports . adapterFactory = adapterFactory ; var _utils = require ( './utils' ) ; var utils = _interopRequireWildcard ( _utils ) ; var _chrome _shim = require ( './chrome/chrome_shim' ) ; var chromeShim = _interopRequireWildcard ( _chrome _shim ) ; var _edge _shim = require ( './edge/edge_shim' ) ; var edgeShim = _interopRequireWildcard ( _edge _shim ) ; var _firefox _shim = require ( './firefox/firefox_shim' ) ; var firefoxShim = _interopRequireWildcard ( _firefox _shim ) ; var _safari _shim = require ( './safari/safari_shim' ) ; var safariShim = _interopRequireWildcard ( _safari _shim ) ; var _common _shim = require ( './common_shim' ) ; var commonShim = _interopRequireWildcard ( _common _shim ) ; function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } else { var newObj = { } ; if ( obj != null ) { for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) newObj [ key ] = obj [ key ] ; } } newObj . default = obj ; return newObj ; } }
function adapterFactory ( ) { var _ref = arguments . length > 0 && arguments [ 0 ] !== undefined ? arguments [ 0 ] : { } , window = _ref . window ; var options = arguments . length > 1 && arguments [ 1 ] !== undefined ? arguments [ 1 ] : { shimChrome : true , shimFirefox : true , shimEdge : true , shimSafari : true } ; var logging = utils . log ; var browserDetails = utils . detectBrowser ( window ) ; var adapter = { browserDetails : browserDetails , commonShim : commonShim , extractVersion : utils . extractVersion , disableLog : utils . disableLog , disableWarnings : utils . disableWarnings } ; switch ( browserDetails . browser ) { case 'chrome' : if ( ! chromeShim || ! chromeShim . shimPeerConnection || ! options . shimChrome ) { logging ( 'Chrome shim is not included in this adapter release.' ) ; return adapter ; }
logging ( 'adapter.js shimming chrome.' ) ; adapter . browserShim = chromeShim ; chromeShim . shimGetUserMedia ( window ) ; chromeShim . shimMediaStream ( window ) ; chromeShim . shimPeerConnection ( window ) ; chromeShim . shimOnTrack ( window ) ; chromeShim . shimAddTrackRemoveTrack ( window ) ; chromeShim . shimGetSendersWithDtmf ( window ) ; chromeShim . shimSenderReceiverGetStats ( window ) ; chromeShim . fixNegotiationNeeded ( window ) ; commonShim . shimRTCIceCandidate ( window ) ; commonShim . shimConnectionState ( window ) ; commonShim . shimMaxMessageSize ( window ) ; commonShim . shimSendThrowTypeError ( window ) ; commonShim . removeAllowExtmapMixed ( window ) ; break ; case 'firefox' : if ( ! firefoxShim || ! firefoxShim . shimPeerConnection || ! options . shimFirefox ) { logging ( 'Firefox shim is not included in this adapter release.' ) ; return adapter ; }
logging ( 'adapter.js shimming firefox.' ) ; adapter . browserShim = firefoxShim ; firefoxShim . shimGetUserMedia ( window ) ; firefoxShim . shimPeerConnection ( window ) ; firefoxShim . shimOnTrack ( window ) ; firefoxShim . shimRemoveStream ( window ) ; firefoxShim . shimSenderGetStats ( window ) ; firefoxShim . shimReceiverGetStats ( window ) ; firefoxShim . shimRTCDataChannel ( window ) ; commonShim . shimRTCIceCandidate ( window ) ; commonShim . shimConnectionState ( window ) ; commonShim . shimMaxMessageSize ( window ) ; commonShim . shimSendThrowTypeError ( window ) ; break ; case 'edge' : if ( ! edgeShim || ! edgeShim . shimPeerConnection || ! options . shimEdge ) { logging ( 'MS edge shim is not included in this adapter release.' ) ; return adapter ; }
logging ( 'adapter.js shimming edge.' ) ; adapter . browserShim = edgeShim ; edgeShim . shimGetUserMedia ( window ) ; edgeShim . shimGetDisplayMedia ( window ) ; edgeShim . shimPeerConnection ( window ) ; edgeShim . shimReplaceTrack ( window ) ; commonShim . shimMaxMessageSize ( window ) ; commonShim . shimSendThrowTypeError ( window ) ; break ; case 'safari' : if ( ! safariShim || ! options . shimSafari ) { logging ( 'Safari shim is not included in this adapter release.' ) ; return adapter ; }
logging ( 'adapter.js shimming safari.' ) ; adapter . browserShim = safariShim ; safariShim . shimRTCIceServerUrls ( window ) ; safariShim . shimCreateOfferLegacy ( window ) ; safariShim . shimCallbacksAPI ( window ) ; safariShim . shimLocalStreamsAPI ( window ) ; safariShim . shimRemoteStreamsAPI ( window ) ; safariShim . shimTrackEventTransceiver ( window ) ; safariShim . shimGetUserMedia ( window ) ; commonShim . shimRTCIceCandidate ( window ) ; commonShim . shimMaxMessageSize ( window ) ; commonShim . shimSendThrowTypeError ( window ) ; commonShim . removeAllowExtmapMixed ( window ) ; break ; default : logging ( 'Unsupported browser!' ) ; break ; }
return adapter ; } } , { "./chrome/chrome_shim" : 3 , "./common_shim" : 6 , "./edge/edge_shim" : 7 , "./firefox/firefox_shim" : 11 , "./safari/safari_shim" : 14 , "./utils" : 15 } ] , 3 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; exports . shimGetDisplayMedia = exports . shimGetUserMedia = undefined ; var _typeof = typeof Symbol === "function" && typeof Symbol . iterator === "symbol" ? function ( obj ) { return typeof obj ; } : function ( obj ) { return obj && typeof Symbol === "function" && obj . constructor === Symbol && obj !== Symbol . prototype ? "symbol" : typeof obj ; } ; var _getusermedia = require ( './getusermedia' ) ; Object . defineProperty ( exports , 'shimGetUserMedia' , { enumerable : true , get : function get ( ) { return _getusermedia . shimGetUserMedia ; } } ) ; var _getdisplaymedia = require ( './getdisplaymedia' ) ; Object . defineProperty ( exports , 'shimGetDisplayMedia' , { enumerable : true , get : function get ( ) { return _getdisplaymedia . shimGetDisplayMedia ; } } ) ; exports . shimMediaStream = shimMediaStream ; exports . shimOnTrack = shimOnTrack ; exports . shimGetSendersWithDtmf = shimGetSendersWithDtmf ; exports . shimSenderReceiverGetStats = shimSenderReceiverGetStats ; exports . shimAddTrackRemoveTrackWithNative = shimAddTrackRemoveTrackWithNative ; exports . shimAddTrackRemoveTrack = shimAddTrackRemoveTrack ; exports . shimPeerConnection = shimPeerConnection ; exports . fixNegotiationNeeded = fixNegotiationNeeded ; var _utils = require ( '../utils.js' ) ; var utils = _interopRequireWildcard ( _utils ) ; function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } else { var newObj = { } ; if ( obj != null ) { for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) newObj [ key ] = obj [ key ] ; } } newObj . default = obj ; return newObj ; } }
function walkStats ( stats , base , resultSet ) { if ( ! base || resultSet . has ( base . id ) ) { return ; }
resultSet . set ( base . id , base ) ; Object . keys ( base ) . forEach ( function ( name ) { if ( name . endsWith ( 'Id' ) ) { walkStats ( stats , stats . get ( base [ name ] ) , resultSet ) ; } else if ( name . endsWith ( 'Ids' ) ) { base [ name ] . forEach ( function ( id ) { walkStats ( stats , stats . get ( id ) , resultSet ) ; } ) ; } } ) ; }
function filterStats ( result , track , outbound ) { var streamStatsType = outbound ? 'outbound-rtp' : 'inbound-rtp' ; var filteredResult = new Map ( ) ; if ( track === null ) { return filteredResult ; }
var trackStats = [ ] ; result . forEach ( function ( value ) { if ( value . type === 'track' && value . trackIdentifier === track . id ) { trackStats . push ( value ) ; } } ) ; trackStats . forEach ( function ( trackStat ) { result . forEach ( function ( stats ) { if ( stats . type === streamStatsType && stats . trackId === trackStat . id ) { walkStats ( result , stats , filteredResult ) ; } } ) ; } ) ; return filteredResult ; }
function shimMediaStream ( window ) { window . MediaStream = window . MediaStream || window . webkitMediaStream ; }
function shimOnTrack ( window ) { if ( ( typeof window === 'undefined' ? 'undefined' : _typeof ( window ) ) === 'object' && window . RTCPeerConnection && ! ( 'ontrack' in window . RTCPeerConnection . prototype ) ) { Object . defineProperty ( window . RTCPeerConnection . prototype , 'ontrack' , { get : function get ( ) { return this . _ontrack ; } , set : function set ( f ) { if ( this . _ontrack ) { this . removeEventListener ( 'track' , this . _ontrack ) ; }
this . addEventListener ( 'track' , this . _ontrack = f ) ; } , enumerable : true , configurable : true } ) ; var origSetRemoteDescription = window . RTCPeerConnection . prototype . setRemoteDescription ; window . RTCPeerConnection . prototype . setRemoteDescription = function ( ) { var _this = this ; if ( ! this . _ontrackpoly ) { this . _ontrackpoly = function ( e ) { e . stream . addEventListener ( 'addtrack' , function ( te ) { var receiver = void 0 ; if ( window . RTCPeerConnection . prototype . getReceivers ) { receiver = _this . getReceivers ( ) . find ( function ( r ) { return r . track && r . track . id === te . track . id ; } ) ; } else { receiver = { track : te . track } ; }
var event = new Event ( 'track' ) ; event . track = te . track ; event . receiver = receiver ; event . transceiver = { receiver : receiver } ; event . streams = [ e . stream ] ; _this . dispatchEvent ( event ) ; } ) ; e . stream . getTracks ( ) . forEach ( function ( track ) { var receiver = void 0 ; if ( window . RTCPeerConnection . prototype . getReceivers ) { receiver = _this . getReceivers ( ) . find ( function ( r ) { return r . track && r . track . id === track . id ; } ) ; } else { receiver = { track : track } ; }
var event = new Event ( 'track' ) ; event . track = track ; event . receiver = receiver ; event . transceiver = { receiver : receiver } ; event . streams = [ e . stream ] ; _this . dispatchEvent ( event ) ; } ) ; } ; this . addEventListener ( 'addstream' , this . _ontrackpoly ) ; }
return origSetRemoteDescription . apply ( this , arguments ) ; } ; } else { utils . wrapPeerConnectionEvent ( window , 'track' , function ( e ) { if ( ! e . transceiver ) { Object . defineProperty ( e , 'transceiver' , { value : { receiver : e . receiver } } ) ; }
return e ; } ) ; } }
function shimGetSendersWithDtmf ( window ) { if ( ( typeof window === 'undefined' ? 'undefined' : _typeof ( window ) ) === 'object' && window . RTCPeerConnection && ! ( 'getSenders' in window . RTCPeerConnection . prototype ) && 'createDTMFSender' in window . RTCPeerConnection . prototype ) { var shimSenderWithDtmf = function shimSenderWithDtmf ( pc , track ) { return { track : track , get dtmf ( ) { if ( this . _dtmf === undefined ) { if ( track . kind === 'audio' ) { this . _dtmf = pc . createDTMFSender ( track ) ; } else { this . _dtmf = null ; } }
return this . _dtmf ; } , _pc : pc } ; } ; if ( ! window . RTCPeerConnection . prototype . getSenders ) { window . RTCPeerConnection . prototype . getSenders = function ( ) { this . _senders = this . _senders || [ ] ; return this . _senders . slice ( ) ; } ; var origAddTrack = window . RTCPeerConnection . prototype . addTrack ; window . RTCPeerConnection . prototype . addTrack = function ( track , stream ) { var sender = origAddTrack . apply ( this , arguments ) ; if ( ! sender ) { sender = shimSenderWithDtmf ( this , track ) ; this . _senders . push ( sender ) ; }
return sender ; } ; var origRemoveTrack = window . RTCPeerConnection . prototype . removeTrack ; window . RTCPeerConnection . prototype . removeTrack = function ( sender ) { origRemoveTrack . apply ( this , arguments ) ; var idx = this . _senders . indexOf ( sender ) ; if ( idx !== - 1 ) { this . _senders . splice ( idx , 1 ) ; } } ; }
var origAddStream = window . RTCPeerConnection . prototype . addStream ; window . RTCPeerConnection . prototype . addStream = function ( stream ) { var _this2 = this ; this . _senders = this . _senders || [ ] ; origAddStream . apply ( this , [ stream ] ) ; stream . getTracks ( ) . forEach ( function ( track ) { _this2 . _senders . push ( shimSenderWithDtmf ( _this2 , track ) ) ; } ) ; } ; var origRemoveStream = window . RTCPeerConnection . prototype . removeStream ; window . RTCPeerConnection . prototype . removeStream = function ( stream ) { var _this3 = this ; this . _senders = this . _senders || [ ] ; origRemoveStream . apply ( this , [ stream ] ) ; stream . getTracks ( ) . forEach ( function ( track ) { var sender = _this3 . _senders . find ( function ( s ) { return s . track === track ; } ) ; if ( sender ) { _this3 . _senders . splice ( _this3 . _senders . indexOf ( sender ) , 1 ) ; } } ) ; } ; } else if ( ( typeof window === 'undefined' ? 'undefined' : _typeof ( window ) ) === 'object' && window . RTCPeerConnection && 'getSenders' in window . RTCPeerConnection . prototype && 'createDTMFSender' in window . RTCPeerConnection . prototype && window . RTCRtpSender && ! ( 'dtmf' in window . RTCRtpSender . prototype ) ) { var origGetSenders = window . RTCPeerConnection . prototype . getSenders ; window . RTCPeerConnection . prototype . getSenders = function ( ) { var _this4 = this ; var senders = origGetSenders . apply ( this , [ ] ) ; senders . forEach ( function ( sender ) { return sender . _pc = _this4 ; } ) ; return senders ; } ; Object . defineProperty ( window . RTCRtpSender . prototype , 'dtmf' , { get : function get ( ) { if ( this . _dtmf === undefined ) { if ( this . track . kind === 'audio' ) { this . _dtmf = this . _pc . createDTMFSender ( this . track ) ; } else { this . _dtmf = null ; } }
return this . _dtmf ; } } ) ; } }
function shimSenderReceiverGetStats ( window ) { if ( ! ( ( typeof window === 'undefined' ? 'undefined' : _typeof ( window ) ) === 'object' && window . RTCPeerConnection && window . RTCRtpSender && window . RTCRtpReceiver ) ) { return ; }
if ( ! ( 'getStats' in window . RTCRtpSender . prototype ) ) { var origGetSenders = window . RTCPeerConnection . prototype . getSenders ; if ( origGetSenders ) { window . RTCPeerConnection . prototype . getSenders = function ( ) { var _this5 = this ; var senders = origGetSenders . apply ( this , [ ] ) ; senders . forEach ( function ( sender ) { return sender . _pc = _this5 ; } ) ; return senders ; } ; }
var origAddTrack = window . RTCPeerConnection . prototype . addTrack ; if ( origAddTrack ) { window . RTCPeerConnection . prototype . addTrack = function ( ) { var sender = origAddTrack . apply ( this , arguments ) ; sender . _pc = this ; return sender ; } ; }
window . RTCRtpSender . prototype . getStats = function ( ) { var sender = this ; return this . _pc . getStats ( ) . then ( function ( result ) { return ( filterStats ( result , sender . track , true ) ) ; } ) ; } ; }
if ( ! ( 'getStats' in window . RTCRtpReceiver . prototype ) ) { var origGetReceivers = window . RTCPeerConnection . prototype . getReceivers ; if ( origGetReceivers ) { window . RTCPeerConnection . prototype . getReceivers = function ( ) { var _this6 = this ; var receivers = origGetReceivers . apply ( this , [ ] ) ; receivers . forEach ( function ( receiver ) { return receiver . _pc = _this6 ; } ) ; return receivers ; } ; }
utils . wrapPeerConnectionEvent ( window , 'track' , function ( e ) { e . receiver . _pc = e . srcElement ; return e ; } ) ; window . RTCRtpReceiver . prototype . getStats = function ( ) { var receiver = this ; return this . _pc . getStats ( ) . then ( function ( result ) { return filterStats ( result , receiver . track , false ) ; } ) ; } ; }
if ( ! ( 'getStats' in window . RTCRtpSender . prototype && 'getStats' in window . RTCRtpReceiver . prototype ) ) { return ; }
var origGetStats = window . RTCPeerConnection . prototype . getStats ; window . RTCPeerConnection . prototype . getStats = function ( ) { if ( arguments . length > 0 && arguments [ 0 ] instanceof window . MediaStreamTrack ) { var track = arguments [ 0 ] ; var sender = void 0 ; var receiver = void 0 ; var err = void 0 ; this . getSenders ( ) . forEach ( function ( s ) { if ( s . track === track ) { if ( sender ) { err = true ; } else { sender = s ; } } } ) ; this . getReceivers ( ) . forEach ( function ( r ) { if ( r . track === track ) { if ( receiver ) { err = true ; } else { receiver = r ; } }
return r . track === track ; } ) ; if ( err || sender && receiver ) { return Promise . reject ( new DOMException ( 'There are more than one sender or receiver for the track.' , 'InvalidAccessError' ) ) ; } else if ( sender ) { return sender . getStats ( ) ; } else if ( receiver ) { return receiver . getStats ( ) ; }
return Promise . reject ( new DOMException ( 'There is no sender or receiver for the track.' , 'InvalidAccessError' ) ) ; }
return origGetStats . apply ( this , arguments ) ; } ; }
function shimAddTrackRemoveTrackWithNative ( window ) { window . RTCPeerConnection . prototype . getLocalStreams = function ( ) { var _this7 = this ; this . _shimmedLocalStreams = this . _shimmedLocalStreams || { } ; return Object . keys ( this . _shimmedLocalStreams ) . map ( function ( streamId ) { return _this7 . _shimmedLocalStreams [ streamId ] [ 0 ] ; } ) ; } ; var origAddTrack = window . RTCPeerConnection . prototype . addTrack ; window . RTCPeerConnection . prototype . addTrack = function ( track , stream ) { if ( ! stream ) { return origAddTrack . apply ( this , arguments ) ; }
this . _shimmedLocalStreams = this . _shimmedLocalStreams || { } ; var sender = origAddTrack . apply ( this , arguments ) ; if ( ! this . _shimmedLocalStreams [ stream . id ] ) { this . _shimmedLocalStreams [ stream . id ] = [ stream , sender ] ; } else if ( this . _shimmedLocalStreams [ stream . id ] . indexOf ( sender ) === - 1 ) { this . _shimmedLocalStreams [ stream . id ] . push ( sender ) ; }
return sender ; } ; var origAddStream = window . RTCPeerConnection . prototype . addStream ; window . RTCPeerConnection . prototype . addStream = function ( stream ) { var _this8 = this ; this . _shimmedLocalStreams = this . _shimmedLocalStreams || { } ; stream . getTracks ( ) . forEach ( function ( track ) { var alreadyExists = _this8 . getSenders ( ) . find ( function ( s ) { return s . track === track ; } ) ; if ( alreadyExists ) { throw new DOMException ( 'Track already exists.' , 'InvalidAccessError' ) ; } } ) ; var existingSenders = this . getSenders ( ) ; origAddStream . apply ( this , arguments ) ; var newSenders = this . getSenders ( ) . filter ( function ( newSender ) { return existingSenders . indexOf ( newSender ) === - 1 ; } ) ; this . _shimmedLocalStreams [ stream . id ] = [ stream ] . concat ( newSenders ) ; } ; var origRemoveStream = window . RTCPeerConnection . prototype . removeStream ; window . RTCPeerConnection . prototype . removeStream = function ( stream ) { this . _shimmedLocalStreams = this . _shimmedLocalStreams || { } ; delete this . _shimmedLocalStreams [ stream . id ] ; return origRemoveStream . apply ( this , arguments ) ; } ; var origRemoveTrack = window . RTCPeerConnection . prototype . removeTrack ; window . RTCPeerConnection . prototype . removeTrack = function ( sender ) { var _this9 = this ; this . _shimmedLocalStreams = this . _shimmedLocalStreams || { } ; if ( sender ) { Object . keys ( this . _shimmedLocalStreams ) . forEach ( function ( streamId ) { var idx = _this9 . _shimmedLocalStreams [ streamId ] . indexOf ( sender ) ; if ( idx !== - 1 ) { _this9 . _shimmedLocalStreams [ streamId ] . splice ( idx , 1 ) ; }
if ( _this9 . _shimmedLocalStreams [ streamId ] . length === 1 ) { delete _this9 . _shimmedLocalStreams [ streamId ] ; } } ) ; }
return origRemoveTrack . apply ( this , arguments ) ; } ; }
function shimAddTrackRemoveTrack ( window ) { if ( ! window . RTCPeerConnection ) { return ; }
var browserDetails = utils . detectBrowser ( window ) ; if ( window . RTCPeerConnection . prototype . addTrack && browserDetails . version >= 65 ) { return shimAddTrackRemoveTrackWithNative ( window ) ; }
var origGetLocalStreams = window . RTCPeerConnection . prototype . getLocalStreams ; window . RTCPeerConnection . prototype . getLocalStreams = function ( ) { var _this10 = this ; var nativeStreams = origGetLocalStreams . apply ( this ) ; this . _reverseStreams = this . _reverseStreams || { } ; return nativeStreams . map ( function ( stream ) { return _this10 . _reverseStreams [ stream . id ] ; } ) ; } ; var origAddStream = window . RTCPeerConnection . prototype . addStream ; window . RTCPeerConnection . prototype . addStream = function ( stream ) { var _this11 = this ; this . _streams = this . _streams || { } ; this . _reverseStreams = this . _reverseStreams || { } ; stream . getTracks ( ) . forEach ( function ( track ) { var alreadyExists = _this11 . getSenders ( ) . find ( function ( s ) { return s . track === track ; } ) ; if ( alreadyExists ) { throw new DOMException ( 'Track already exists.' , 'InvalidAccessError' ) ; } } ) ; if ( ! this . _reverseStreams [ stream . id ] ) { var newStream = new window . MediaStream ( stream . getTracks ( ) ) ; this . _streams [ stream . id ] = newStream ; this . _reverseStreams [ newStream . id ] = stream ; stream = newStream ; }
origAddStream . apply ( this , [ stream ] ) ; } ; var origRemoveStream = window . RTCPeerConnection . prototype . removeStream ; window . RTCPeerConnection . prototype . removeStream = function ( stream ) { this . _streams = this . _streams || { } ; this . _reverseStreams = this . _reverseStreams || { } ; origRemoveStream . apply ( this , [ this . _streams [ stream . id ] || stream ] ) ; delete this . _reverseStreams [ this . _streams [ stream . id ] ? this . _streams [ stream . id ] . id : stream . id ] ; delete this . _streams [ stream . id ] ; } ; window . RTCPeerConnection . prototype . addTrack = function ( track , stream ) { var _this12 = this ; if ( this . signalingState === 'closed' ) { throw new DOMException ( 'The RTCPeerConnection\'s signalingState is \'closed\'.' , 'InvalidStateError' ) ; }
var streams = [ ] . slice . call ( arguments , 1 ) ; if ( streams . length !== 1 || ! streams [ 0 ] . getTracks ( ) . find ( function ( t ) { return t === track ; } ) ) { throw new DOMException ( 'The adapter.js addTrack polyfill only supports a single ' + ' stream which is associated with the specified track.' , 'NotSupportedError' ) ; }
var alreadyExists = this . getSenders ( ) . find ( function ( s ) { return s . track === track ; } ) ; if ( alreadyExists ) { throw new DOMException ( 'Track already exists.' , 'InvalidAccessError' ) ; }
this . _streams = this . _streams || { } ; this . _reverseStreams = this . _reverseStreams || { } ; var oldStream = this . _streams [ stream . id ] ; if ( oldStream ) { oldStream . addTrack ( track ) ; Promise . resolve ( ) . then ( function ( ) { _this12 . dispatchEvent ( new Event ( 'negotiationneeded' ) ) ; } ) ; } else { var newStream = new window . MediaStream ( [ track ] ) ; this . _streams [ stream . id ] = newStream ; this . _reverseStreams [ newStream . id ] = stream ; this . addStream ( newStream ) ; }
return this . getSenders ( ) . find ( function ( s ) { return s . track === track ; } ) ; } ; function replaceInternalStreamId ( pc , description ) { var sdp = description . sdp ; Object . keys ( pc . _reverseStreams || [ ] ) . forEach ( function ( internalId ) { var externalStream = pc . _reverseStreams [ internalId ] ; var internalStream = pc . _streams [ externalStream . id ] ; sdp = sdp . replace ( new RegExp ( internalStream . id , 'g' ) , externalStream . id ) ; } ) ; return new RTCSessionDescription ( { type : description . type , sdp : sdp } ) ; }
function replaceExternalStreamId ( pc , description ) { var sdp = description . sdp ; Object . keys ( pc . _reverseStreams || [ ] ) . forEach ( function ( internalId ) { var externalStream = pc . _reverseStreams [ internalId ] ; var internalStream = pc . _streams [ externalStream . id ] ; sdp = sdp . replace ( new RegExp ( externalStream . id , 'g' ) , internalStream . id ) ; } ) ; return new RTCSessionDescription ( { type : description . type , sdp : sdp } ) ; }
[ 'createOffer' , 'createAnswer' ] . forEach ( function ( method ) { var nativeMethod = window . RTCPeerConnection . prototype [ method ] ; window . RTCPeerConnection . prototype [ method ] = function ( ) { var _this13 = this ; var args = arguments ; var isLegacyCall = arguments . length && typeof arguments [ 0 ] === 'function' ; if ( isLegacyCall ) { return nativeMethod . apply ( this , [ function ( description ) { var desc = replaceInternalStreamId ( _this13 , description ) ; args [ 0 ] . apply ( null , [ desc ] ) ; } , function ( err ) { if ( args [ 1 ] ) { args [ 1 ] . apply ( null , err ) ; } } , arguments [ 2 ] ] ) ; }
return nativeMethod . apply ( this , arguments ) . then ( function ( description ) { return replaceInternalStreamId ( _this13 , description ) ; } ) ; } ; } ) ; var origSetLocalDescription = window . RTCPeerConnection . prototype . setLocalDescription ; window . RTCPeerConnection . prototype . setLocalDescription = function ( ) { if ( ! arguments . length || ! arguments [ 0 ] . type ) { return origSetLocalDescription . apply ( this , arguments ) ; }
arguments [ 0 ] = replaceExternalStreamId ( this , arguments [ 0 ] ) ; return origSetLocalDescription . apply ( this , arguments ) ; } ; var origLocalDescription = Object . getOwnPropertyDescriptor ( window . RTCPeerConnection . prototype , 'localDescription' ) ; Object . defineProperty ( window . RTCPeerConnection . prototype , 'localDescription' , { get : function get ( ) { var description = origLocalDescription . get . apply ( this ) ; if ( description . type === '' ) { return description ; }
return replaceInternalStreamId ( this , description ) ; } } ) ; window . RTCPeerConnection . prototype . removeTrack = function ( sender ) { var _this14 = this ; if ( this . signalingState === 'closed' ) { throw new DOMException ( 'The RTCPeerConnection\'s signalingState is \'closed\'.' , 'InvalidStateError' ) ; }
if ( ! sender . _pc ) { throw new DOMException ( 'Argument 1 of RTCPeerConnection.removeTrack ' + 'does not implement interface RTCRtpSender.' , 'TypeError' ) ; }
var isLocal = sender . _pc === this ; if ( ! isLocal ) { throw new DOMException ( 'Sender was not created by this connection.' , 'InvalidAccessError' ) ; }
this . _streams = this . _streams || { } ; var stream = void 0 ; Object . keys ( this . _streams ) . forEach ( function ( streamid ) { var hasTrack = _this14 . _streams [ streamid ] . getTracks ( ) . find ( function ( track ) { return sender . track === track ; } ) ; if ( hasTrack ) { stream = _this14 . _streams [ streamid ] ; } } ) ; if ( stream ) { if ( stream . getTracks ( ) . length === 1 ) { this . removeStream ( this . _reverseStreams [ stream . id ] ) ; } else { stream . removeTrack ( sender . track ) ; }
this . dispatchEvent ( new Event ( 'negotiationneeded' ) ) ; } } ; }
function shimPeerConnection ( window ) { if ( ! window . RTCPeerConnection && window . webkitRTCPeerConnection ) { window . RTCPeerConnection = window . webkitRTCPeerConnection ; }
if ( ! window . RTCPeerConnection ) { return ; }
var origGetStats = window . RTCPeerConnection . prototype . getStats ; window . RTCPeerConnection . prototype . getStats = function ( selector , successCallback , errorCallback ) { var _this15 = this ; var args = arguments ; if ( arguments . length > 0 && typeof selector === 'function' ) { return origGetStats . apply ( this , arguments ) ; }
if ( origGetStats . length === 0 && ( arguments . length === 0 || typeof arguments [ 0 ] !== 'function' ) ) { return origGetStats . apply ( this , [ ] ) ; }
var fixChromeStats _ = function fixChromeStats _ ( response ) { var standardReport = { } ; var reports = response . result ( ) ; reports . forEach ( function ( report ) { var standardStats = { id : report . id , timestamp : report . timestamp , type : { localcandidate : 'local-candidate' , remotecandidate : 'remote-candidate' } [ report . type ] || report . type } ; report . names ( ) . forEach ( function ( name ) { standardStats [ name ] = report . stat ( name ) ; } ) ; standardReport [ standardStats . id ] = standardStats ; } ) ; return standardReport ; } ; var makeMapStats = function makeMapStats ( stats ) { return new Map ( Object . keys ( stats ) . map ( function ( key ) { return [ key , stats [ key ] ] ; } ) ) ; } ; if ( arguments . length >= 2 ) { var successCallbackWrapper _ = function successCallbackWrapper _ ( response ) { args [ 1 ] ( makeMapStats ( fixChromeStats _ ( response ) ) ) ; } ; return origGetStats . apply ( this , [ successCallbackWrapper _ , arguments [ 0 ] ] ) ; }
return new Promise ( function ( resolve , reject ) { origGetStats . apply ( _this15 , [ function ( response ) { resolve ( makeMapStats ( fixChromeStats _ ( response ) ) ) ; } , reject ] ) ; } ) . then ( successCallback , errorCallback ) ; } ; [ 'setLocalDescription' , 'setRemoteDescription' , 'addIceCandidate' ] . forEach ( function ( method ) { var nativeMethod = window . RTCPeerConnection . prototype [ method ] ; window . RTCPeerConnection . prototype [ method ] = function ( ) { arguments [ 0 ] = new ( method === 'addIceCandidate' ? window . RTCIceCandidate : window . RTCSessionDescription ) ( arguments [ 0 ] ) ; return nativeMethod . apply ( this , arguments ) ; } ; } ) ; var nativeAddIceCandidate = window . RTCPeerConnection . prototype . addIceCandidate ; window . RTCPeerConnection . prototype . addIceCandidate = function ( ) { if ( ! arguments [ 0 ] ) { if ( arguments [ 1 ] ) { arguments [ 1 ] . apply ( null ) ; }
return Promise . resolve ( ) ; }
return nativeAddIceCandidate . apply ( this , arguments ) ; } ; }
function fixNegotiationNeeded ( window ) { utils . wrapPeerConnectionEvent ( window , 'negotiationneeded' , function ( e ) { var pc = e . target ; if ( pc . signalingState !== 'stable' ) { return ; }
return e ; } ) ; } } , { "../utils.js" : 15 , "./getdisplaymedia" : 4 , "./getusermedia" : 5 } ] , 4 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; exports . shimGetDisplayMedia = shimGetDisplayMedia ; function shimGetDisplayMedia ( window , getSourceId ) { if ( window . navigator . mediaDevices && 'getDisplayMedia' in window . navigator . mediaDevices ) { return ; }
if ( ! window . navigator . mediaDevices ) { return ; }
if ( typeof getSourceId !== 'function' ) { console . error ( 'shimGetDisplayMedia: getSourceId argument is not ' + 'a function' ) ; return ; }
window . navigator . mediaDevices . getDisplayMedia = function ( constraints ) { return getSourceId ( constraints ) . then ( function ( sourceId ) { var widthSpecified = constraints . video && constraints . video . width ; var heightSpecified = constraints . video && constraints . video . height ; var frameRateSpecified = constraints . video && constraints . video . frameRate ; constraints . video = { mandatory : { chromeMediaSource : 'desktop' , chromeMediaSourceId : sourceId , maxFrameRate : frameRateSpecified || 3 } } ; if ( widthSpecified ) { constraints . video . mandatory . maxWidth = widthSpecified ; }
if ( heightSpecified ) { constraints . video . mandatory . maxHeight = heightSpecified ; }
return window . navigator . mediaDevices . getUserMedia ( constraints ) ; } ) ; } ; } } , { } ] , 5 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; var _typeof = typeof Symbol === "function" && typeof Symbol . iterator === "symbol" ? function ( obj ) { return typeof obj ; } : function ( obj ) { return obj && typeof Symbol === "function" && obj . constructor === Symbol && obj !== Symbol . prototype ? "symbol" : typeof obj ; } ; exports . shimGetUserMedia = shimGetUserMedia ; var _utils = require ( '../utils.js' ) ; var utils = _interopRequireWildcard ( _utils ) ; function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } else { var newObj = { } ; if ( obj != null ) { for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) newObj [ key ] = obj [ key ] ; } } newObj . default = obj ; return newObj ; } }
var logging = utils . log ; function shimGetUserMedia ( window ) { var navigator = window && window . navigator ; if ( ! navigator . mediaDevices ) { return ; }
var browserDetails = utils . detectBrowser ( window ) ; var constraintsToChrome _ = function constraintsToChrome _ ( c ) { if ( ( typeof c === 'undefined' ? 'undefined' : _typeof ( c ) ) !== 'object' || c . mandatory || c . optional ) { return c ; }
var cc = { } ; Object . keys ( c ) . forEach ( function ( key ) { if ( key === 'require' || key === 'advanced' || key === 'mediaSource' ) { return ; }
var r = _typeof ( c [ key ] ) === 'object' ? c [ key ] : { ideal : c [ key ] } ; if ( r . exact !== undefined && typeof r . exact === 'number' ) { r . min = r . max = r . exact ; }
var oldname _ = function oldname _ ( prefix , name ) { if ( prefix ) { return prefix + name . charAt ( 0 ) . toUpperCase ( ) + name . slice ( 1 ) ; }
return name === 'deviceId' ? 'sourceId' : name ; } ; if ( r . ideal !== undefined ) { cc . optional = cc . optional || [ ] ; var oc = { } ; if ( typeof r . ideal === 'number' ) { oc [ oldname _ ( 'min' , key ) ] = r . ideal ; cc . optional . push ( oc ) ; oc = { } ; oc [ oldname _ ( 'max' , key ) ] = r . ideal ; cc . optional . push ( oc ) ; } else { oc [ oldname _ ( '' , key ) ] = r . ideal ; cc . optional . push ( oc ) ; } }
if ( r . exact !== undefined && typeof r . exact !== 'number' ) { cc . mandatory = cc . mandatory || { } ; cc . mandatory [ oldname _ ( '' , key ) ] = r . exact ; } else { [ 'min' , 'max' ] . forEach ( function ( mix ) { if ( r [ mix ] !== undefined ) { cc . mandatory = cc . mandatory || { } ; cc . mandatory [ oldname _ ( mix , key ) ] = r [ mix ] ; } } ) ; } } ) ; if ( c . advanced ) { cc . optional = ( cc . optional || [ ] ) . concat ( c . advanced ) ; }
return cc ; } ; var shimConstraints _ = function shimConstraints _ ( constraints , func ) { if ( browserDetails . version >= 61 ) { return func ( constraints ) ; }
constraints = JSON . parse ( JSON . stringify ( constraints ) ) ; if ( constraints && _typeof ( constraints . audio ) === 'object' ) { var remap = function remap ( obj , a , b ) { if ( a in obj && ! ( b in obj ) ) { obj [ b ] = obj [ a ] ; delete obj [ a ] ; } } ; constraints = JSON . parse ( JSON . stringify ( constraints ) ) ; remap ( constraints . audio , 'autoGainControl' , 'googAutoGainControl' ) ; remap ( constraints . audio , 'noiseSuppression' , 'googNoiseSuppression' ) ; constraints . audio = constraintsToChrome _ ( constraints . audio ) ; }
if ( constraints && _typeof ( constraints . video ) === 'object' ) { var face = constraints . video . facingMode ; face = face && ( ( typeof face === 'undefined' ? 'undefined' : _typeof ( face ) ) === 'object' ? face : { ideal : face } ) ; var getSupportedFacingModeLies = browserDetails . version < 66 ; if ( face && ( face . exact === 'user' || face . exact === 'environment' || face . ideal === 'user' || face . ideal === 'environment' ) && ! ( navigator . mediaDevices . getSupportedConstraints && navigator . mediaDevices . getSupportedConstraints ( ) . facingMode && ! getSupportedFacingModeLies ) ) { delete constraints . video . facingMode ; var matches = void 0 ; if ( face . exact === 'environment' || face . ideal === 'environment' ) { matches = [ 'back' , 'rear' ] ; } else if ( face . exact === 'user' || face . ideal === 'user' ) { matches = [ 'front' ] ; }
if ( matches ) { return navigator . mediaDevices . enumerateDevices ( ) . then ( function ( devices ) { devices = devices . filter ( function ( d ) { return d . kind === 'videoinput' ; } ) ; var dev = devices . find ( function ( d ) { return matches . some ( function ( match ) { return d . label . toLowerCase ( ) . includes ( match ) ; } ) ; } ) ; if ( ! dev && devices . length && matches . includes ( 'back' ) ) { dev = devices [ devices . length - 1 ] ; }
if ( dev ) { constraints . video . deviceId = face . exact ? { exact : dev . deviceId } : { ideal : dev . deviceId } ; }
constraints . video = constraintsToChrome _ ( constraints . video ) ; logging ( 'chrome: ' + JSON . stringify ( constraints ) ) ; return func ( constraints ) ; } ) ; } }
constraints . video = constraintsToChrome _ ( constraints . video ) ; }
logging ( 'chrome: ' + JSON . stringify ( constraints ) ) ; return func ( constraints ) ; } ; var shimError _ = function shimError _ ( e ) { if ( browserDetails . version >= 64 ) { return e ; }
return { name : { PermissionDeniedError : 'NotAllowedError' , PermissionDismissedError : 'NotAllowedError' , InvalidStateError : 'NotAllowedError' , DevicesNotFoundError : 'NotFoundError' , ConstraintNotSatisfiedError : 'OverconstrainedError' , TrackStartError : 'NotReadableError' , MediaDeviceFailedDueToShutdown : 'NotAllowedError' , MediaDeviceKillSwitchOn : 'NotAllowedError' , TabCaptureError : 'AbortError' , ScreenCaptureError : 'AbortError' , DeviceCaptureError : 'AbortError' } [ e . name ] || e . name , message : e . message , constraint : e . constraint || e . constraintName , toString : function toString ( ) { return this . name + ( this . message && ': ' ) + this . message ; } } ; } ; var getUserMedia _ = function getUserMedia _ ( constraints , onSuccess , onError ) { shimConstraints _ ( constraints , function ( c ) { navigator . webkitGetUserMedia ( c , onSuccess , function ( e ) { if ( onError ) { onError ( shimError _ ( e ) ) ; } } ) ; } ) ; } ; navigator . getUserMedia = getUserMedia _ . bind ( navigator ) ; var origGetUserMedia = navigator . mediaDevices . getUserMedia . bind ( navigator . mediaDevices ) ; navigator . mediaDevices . getUserMedia = function ( cs ) { return shimConstraints _ ( cs , function ( c ) { return origGetUserMedia ( c ) . then ( function ( stream ) { if ( c . audio && ! stream . getAudioTracks ( ) . length || c . video && ! stream . getVideoTracks ( ) . length ) { stream . getTracks ( ) . forEach ( function ( track ) { track . stop ( ) ; } ) ; throw new DOMException ( '' , 'NotFoundError' ) ; }
return stream ; } , function ( e ) { return Promise . reject ( shimError _ ( e ) ) ; } ) ; } ) ; } ; } } , { "../utils.js" : 15 } ] , 6 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; var _typeof = typeof Symbol === "function" && typeof Symbol . iterator === "symbol" ? function ( obj ) { return typeof obj ; } : function ( obj ) { return obj && typeof Symbol === "function" && obj . constructor === Symbol && obj !== Symbol . prototype ? "symbol" : typeof obj ; } ; exports . shimRTCIceCandidate = shimRTCIceCandidate ; exports . shimMaxMessageSize = shimMaxMessageSize ; exports . shimSendThrowTypeError = shimSendThrowTypeError ; exports . shimConnectionState = shimConnectionState ; exports . removeAllowExtmapMixed = removeAllowExtmapMixed ; var _sdp = require ( 'sdp' ) ; var _sdp2 = _interopRequireDefault ( _sdp ) ; var _utils = require ( './utils' ) ; var utils = _interopRequireWildcard ( _utils ) ; function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } else { var newObj = { } ; if ( obj != null ) { for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) newObj [ key ] = obj [ key ] ; } } newObj . default = obj ; return newObj ; } }
function _interopRequireDefault ( obj ) { return obj && obj . _ _esModule ? obj : { default : obj } ; }
function shimRTCIceCandidate ( window ) { if ( ! window . RTCIceCandidate || window . RTCIceCandidate && 'foundation' in window . RTCIceCandidate . prototype ) { return ; }
var NativeRTCIceCandidate = window . RTCIceCandidate ; window . RTCIceCandidate = function ( args ) { if ( ( typeof args === 'undefined' ? 'undefined' : _typeof ( args ) ) === 'object' && args . candidate && args . candidate . indexOf ( 'a=' ) === 0 ) { args = JSON . parse ( JSON . stringify ( args ) ) ; args . candidate = args . candidate . substr ( 2 ) ; }
if ( args . candidate && args . candidate . length ) { var nativeCandidate = new NativeRTCIceCandidate ( args ) ; var parsedCandidate = _sdp2 . default . parseCandidate ( args . candidate ) ; var augmentedCandidate = Object . assign ( nativeCandidate , parsedCandidate ) ; augmentedCandidate . toJSON = function ( ) { return { candidate : augmentedCandidate . candidate , sdpMid : augmentedCandidate . sdpMid , sdpMLineIndex : augmentedCandidate . sdpMLineIndex , usernameFragment : augmentedCandidate . usernameFragment } ; } ; return augmentedCandidate ; }
return new NativeRTCIceCandidate ( args ) ; } ; window . RTCIceCandidate . prototype = NativeRTCIceCandidate . prototype ; utils . wrapPeerConnectionEvent ( window , 'icecandidate' , function ( e ) { if ( e . candidate ) { Object . defineProperty ( e , 'candidate' , { value : new window . RTCIceCandidate ( e . candidate ) , writable : 'false' } ) ; }
return e ; } ) ; }
function shimMaxMessageSize ( window ) { if ( window . RTCSctpTransport || ! window . RTCPeerConnection ) { return ; }
var browserDetails = utils . detectBrowser ( window ) ; if ( ! ( 'sctp' in window . RTCPeerConnection . prototype ) ) { Object . defineProperty ( window . RTCPeerConnection . prototype , 'sctp' , { get : function get ( ) { return typeof this . _sctp === 'undefined' ? null : this . _sctp ; } } ) ; }
var sctpInDescription = function sctpInDescription ( description ) { var sections = _sdp2 . default . splitSections ( description . sdp ) ; sections . shift ( ) ; return sections . some ( function ( mediaSection ) { var mLine = _sdp2 . default . parseMLine ( mediaSection ) ; return mLine && mLine . kind === 'application' && mLine . protocol . indexOf ( 'SCTP' ) !== - 1 ; } ) ; } ; var getRemoteFirefoxVersion = function getRemoteFirefoxVersion ( description ) { var match = description . sdp . match ( /mozilla...THIS_IS_SDPARTA-(\d+)/ ) ; if ( match === null || match . length < 2 ) { return - 1 ; }
var version = parseInt ( match [ 1 ] , 10 ) ; return version !== version ? - 1 : version ; } ; var getCanSendMaxMessageSize = function getCanSendMaxMessageSize ( remoteIsFirefox ) { var canSendMaxMessageSize = 65536 ; if ( browserDetails . browser === 'firefox' ) { if ( browserDetails . version < 57 ) { if ( remoteIsFirefox === - 1 ) { canSendMaxMessageSize = 16384 ; } else { canSendMaxMessageSize = 2147483637 ; } } else if ( browserDetails . version < 60 ) { canSendMaxMessageSize = browserDetails . version === 57 ? 65535 : 65536 ; } else { canSendMaxMessageSize = 2147483637 ; } }
return canSendMaxMessageSize ; } ; var getMaxMessageSize = function getMaxMessageSize ( description , remoteIsFirefox ) { var maxMessageSize = 65536 ; if ( browserDetails . browser === 'firefox' && browserDetails . version === 57 ) { maxMessageSize = 65535 ; }
var match = _sdp2 . default . matchPrefix ( description . sdp , 'a=max-message-size:' ) ; if ( match . length > 0 ) { maxMessageSize = parseInt ( match [ 0 ] . substr ( 19 ) , 10 ) ; } else if ( browserDetails . browser === 'firefox' && remoteIsFirefox !== - 1 ) { maxMessageSize = 2147483637 ; }
return maxMessageSize ; } ; var origSetRemoteDescription = window . RTCPeerConnection . prototype . setRemoteDescription ; window . RTCPeerConnection . prototype . setRemoteDescription = function ( ) { this . _sctp = null ; if ( sctpInDescription ( arguments [ 0 ] ) ) { var isFirefox = getRemoteFirefoxVersion ( arguments [ 0 ] ) ; var canSendMMS = getCanSendMaxMessageSize ( isFirefox ) ; var remoteMMS = getMaxMessageSize ( arguments [ 0 ] , isFirefox ) ; var maxMessageSize = void 0 ; if ( canSendMMS === 0 && remoteMMS === 0 ) { maxMessageSize = Number . POSITIVE _INFINITY ; } else if ( canSendMMS === 0 || remoteMMS === 0 ) { maxMessageSize = Math . max ( canSendMMS , remoteMMS ) ; } else { maxMessageSize = Math . min ( canSendMMS , remoteMMS ) ; }
var sctp = { } ; Object . defineProperty ( sctp , 'maxMessageSize' , { get : function get ( ) { return maxMessageSize ; } } ) ; this . _sctp = sctp ; }
return origSetRemoteDescription . apply ( this , arguments ) ; } ; }
function shimSendThrowTypeError ( window ) { if ( ! ( window . RTCPeerConnection && 'createDataChannel' in window . RTCPeerConnection . prototype ) ) { return ; }
function wrapDcSend ( dc , pc ) { var origDataChannelSend = dc . send ; dc . send = function ( ) { var data = arguments [ 0 ] ; var length = data . length || data . size || data . byteLength ; if ( dc . readyState === 'open' && pc . sctp && length > pc . sctp . maxMessageSize ) { throw new TypeError ( 'Message too large (can send a maximum of ' + pc . sctp . maxMessageSize + ' bytes)' ) ; }
return origDataChannelSend . apply ( dc , arguments ) ; } ; }
var origCreateDataChannel = window . RTCPeerConnection . prototype . createDataChannel ; window . RTCPeerConnection . prototype . createDataChannel = function ( ) { var dataChannel = origCreateDataChannel . apply ( this , arguments ) ; wrapDcSend ( dataChannel , this ) ; return dataChannel ; } ; utils . wrapPeerConnectionEvent ( window , 'datachannel' , function ( e ) { wrapDcSend ( e . channel , e . target ) ; return e ; } ) ; }
function shimConnectionState ( window ) { if ( ! window . RTCPeerConnection || 'connectionState' in window . RTCPeerConnection . prototype ) { return ; }
var proto = window . RTCPeerConnection . prototype ; Object . defineProperty ( proto , 'connectionState' , { get : function get ( ) { return { completed : 'connected' , checking : 'connecting' } [ this . iceConnectionState ] || this . iceConnectionState ; } , enumerable : true , configurable : true } ) ; Object . defineProperty ( proto , 'onconnectionstatechange' , { get : function get ( ) { return this . _onconnectionstatechange || null ; } , set : function set ( cb ) { if ( this . _onconnectionstatechange ) { this . removeEventListener ( 'connectionstatechange' , this . _onconnectionstatechange ) ; delete this . _onconnectionstatechange ; }
if ( cb ) { this . addEventListener ( 'connectionstatechange' , this . _onconnectionstatechange = cb ) ; } } , enumerable : true , configurable : true } ) ; [ 'setLocalDescription' , 'setRemoteDescription' ] . forEach ( function ( method ) { var origMethod = proto [ method ] ; proto [ method ] = function ( ) { if ( ! this . _connectionstatechangepoly ) { this . _connectionstatechangepoly = function ( e ) { var pc = e . target ; if ( pc . _lastConnectionState !== pc . connectionState ) { pc . _lastConnectionState = pc . connectionState ; var newEvent = new Event ( 'connectionstatechange' , e ) ; pc . dispatchEvent ( newEvent ) ; }
return e ; } ; this . addEventListener ( 'iceconnectionstatechange' , this . _connectionstatechangepoly ) ; }
return origMethod . apply ( this , arguments ) ; } ; } ) ; }
function removeAllowExtmapMixed ( window ) { if ( ! window . RTCPeerConnection ) { return ; }
var browserDetails = utils . detectBrowser ( window ) ; if ( browserDetails . browser === 'chrome' && browserDetails . version >= 71 ) { return ; }
var nativeSRD = window . RTCPeerConnection . prototype . setRemoteDescription ; window . RTCPeerConnection . prototype . setRemoteDescription = function ( desc ) { if ( desc && desc . sdp && desc . sdp . indexOf ( '\na=extmap-allow-mixed' ) !== - 1 ) { desc . sdp = desc . sdp . split ( '\n' ) . filter ( function ( line ) { return line . trim ( ) !== 'a=extmap-allow-mixed' ; } ) . join ( '\n' ) ; }
return nativeSRD . apply ( this , arguments ) ; } ; } } , { "./utils" : 15 , "sdp" : 17 } ] , 7 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; exports . shimGetDisplayMedia = exports . shimGetUserMedia = undefined ; var _getusermedia = require ( './getusermedia' ) ; Object . defineProperty ( exports , 'shimGetUserMedia' , { enumerable : true , get : function get ( ) { return _getusermedia . shimGetUserMedia ; } } ) ; var _getdisplaymedia = require ( './getdisplaymedia' ) ; Object . defineProperty ( exports , 'shimGetDisplayMedia' , { enumerable : true , get : function get ( ) { return _getdisplaymedia . shimGetDisplayMedia ; } } ) ; exports . shimPeerConnection = shimPeerConnection ; exports . shimReplaceTrack = shimReplaceTrack ; var _utils = require ( '../utils' ) ; var utils = _interopRequireWildcard ( _utils ) ; var _filtericeservers = require ( './filtericeservers' ) ; var _rtcpeerconnectionShim = require ( 'rtcpeerconnection-shim' ) ; var _rtcpeerconnectionShim2 = _interopRequireDefault ( _rtcpeerconnectionShim ) ; function _interopRequireDefault ( obj ) { return obj && obj . _ _esModule ? obj : { default : obj } ; }
function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } else { var newObj = { } ; if ( obj != null ) { for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) newObj [ key ] = obj [ key ] ; } } newObj . default = obj ; return newObj ; } }
function shimPeerConnection ( window ) { var browserDetails = utils . detectBrowser ( window ) ; if ( window . RTCIceGatherer ) { if ( ! window . RTCIceCandidate ) { window . RTCIceCandidate = function ( args ) { return args ; } ; }
if ( ! window . RTCSessionDescription ) { window . RTCSessionDescription = function ( args ) { return args ; } ; }
if ( browserDetails . version < 15025 ) { var origMSTEnabled = Object . getOwnPropertyDescriptor ( window . MediaStreamTrack . prototype , 'enabled' ) ; Object . defineProperty ( window . MediaStreamTrack . prototype , 'enabled' , { set : function set ( value ) { origMSTEnabled . set . call ( this , value ) ; var ev = new Event ( 'enabled' ) ; ev . enabled = value ; this . dispatchEvent ( ev ) ; } } ) ; } }
if ( window . RTCRtpSender && ! ( 'dtmf' in window . RTCRtpSender . prototype ) ) { Object . defineProperty ( window . RTCRtpSender . prototype , 'dtmf' , { get : function get ( ) { if ( this . _dtmf === undefined ) { if ( this . track . kind === 'audio' ) { this . _dtmf = new window . RTCDtmfSender ( this ) ; } else if ( this . track . kind === 'video' ) { this . _dtmf = null ; } }
return this . _dtmf ; } } ) ; }
if ( window . RTCDtmfSender && ! window . RTCDTMFSender ) { window . RTCDTMFSender = window . RTCDtmfSender ; }
var RTCPeerConnectionShim = ( 0 , _rtcpeerconnectionShim2 . default ) ( window , browserDetails . version ) ; window . RTCPeerConnection = function ( config ) { if ( config && config . iceServers ) { config . iceServers = ( 0 , _filtericeservers . filterIceServers ) ( config . iceServers , browserDetails . version ) ; utils . log ( 'ICE servers after filtering:' , config . iceServers ) ; }
return new RTCPeerConnectionShim ( config ) ; } ; window . RTCPeerConnection . prototype = RTCPeerConnectionShim . prototype ; }
function shimReplaceTrack ( window ) { if ( window . RTCRtpSender && ! ( 'replaceTrack' in window . RTCRtpSender . prototype ) ) { window . RTCRtpSender . prototype . replaceTrack = window . RTCRtpSender . prototype . setTrack ; } } } , { "../utils" : 15 , "./filtericeservers" : 8 , "./getdisplaymedia" : 9 , "./getusermedia" : 10 , "rtcpeerconnection-shim" : 16 } ] , 8 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; exports . filterIceServers = filterIceServers ; var _utils = require ( '../utils' ) ; var utils = _interopRequireWildcard ( _utils ) ; function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } else { var newObj = { } ; if ( obj != null ) { for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) newObj [ key ] = obj [ key ] ; } } newObj . default = obj ; return newObj ; } }
function filterIceServers ( iceServers , edgeVersion ) { var hasTurn = false ; iceServers = JSON . parse ( JSON . stringify ( iceServers ) ) ; return iceServers . filter ( function ( server ) { if ( server && ( server . urls || server . url ) ) { var urls = server . urls || server . url ; if ( server . url && ! server . urls ) { utils . deprecated ( 'RTCIceServer.url' , 'RTCIceServer.urls' ) ; }
var isString = typeof urls === 'string' ; if ( isString ) { urls = [ urls ] ; }
urls = urls . filter ( function ( url ) { if ( url . indexOf ( 'stun:' ) === 0 ) { return false ; }
var validTurn = url . startsWith ( 'turn' ) && ! url . startsWith ( 'turn:[' ) && url . includes ( 'transport=udp' ) ; if ( validTurn && ! hasTurn ) { hasTurn = true ; return true ; }
return validTurn && ! hasTurn ; } ) ; delete server . url ; server . urls = isString ? urls [ 0 ] : urls ; return ! ! urls . length ; } } ) ; } } , { "../utils" : 15 } ] , 9 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; exports . shimGetDisplayMedia = shimGetDisplayMedia ; function shimGetDisplayMedia ( window ) { if ( ! ( 'getDisplayMedia' in window . navigator ) ) { return ; }
if ( ! window . navigator . mediaDevices ) { return ; }
if ( window . navigator . mediaDevices && 'getDisplayMedia' in window . navigator . mediaDevices ) { return ; }
window . navigator . mediaDevices . getDisplayMedia = window . navigator . getDisplayMedia . bind ( window . navigator . mediaDevices ) ; } } , { } ] , 10 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; exports . shimGetUserMedia = shimGetUserMedia ; function shimGetUserMedia ( window ) { var navigator = window && window . navigator ; var shimError _ = function shimError _ ( e ) { return { name : { PermissionDeniedError : 'NotAllowedError' } [ e . name ] || e . name , message : e . message , constraint : e . constraint , toString : function toString ( ) { return this . name ; } } ; } ; var origGetUserMedia = navigator . mediaDevices . getUserMedia . bind ( navigator . mediaDevices ) ; navigator . mediaDevices . getUserMedia = function ( c ) { return origGetUserMedia ( c ) . catch ( function ( e ) { return Promise . reject ( shimError _ ( e ) ) ; } ) ; } ; } } , { } ] , 11 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; exports . shimGetDisplayMedia = exports . shimGetUserMedia = undefined ; var _typeof = typeof Symbol === "function" && typeof Symbol . iterator === "symbol" ? function ( obj ) { return typeof obj ; } : function ( obj ) { return obj && typeof Symbol === "function" && obj . constructor === Symbol && obj !== Symbol . prototype ? "symbol" : typeof obj ; } ; var _getusermedia = require ( './getusermedia' ) ; Object . defineProperty ( exports , 'shimGetUserMedia' , { enumerable : true , get : function get ( ) { return _getusermedia . shimGetUserMedia ; } } ) ; var _getdisplaymedia = require ( './getdisplaymedia' ) ; Object . defineProperty ( exports , 'shimGetDisplayMedia' , { enumerable : true , get : function get ( ) { return _getdisplaymedia . shimGetDisplayMedia ; } } ) ; exports . shimOnTrack = shimOnTrack ; exports . shimPeerConnection = shimPeerConnection ; exports . shimSenderGetStats = shimSenderGetStats ; exports . shimReceiverGetStats = shimReceiverGetStats ; exports . shimRemoveStream = shimRemoveStream ; exports . shimRTCDataChannel = shimRTCDataChannel ; var _utils = require ( '../utils' ) ; var utils = _interopRequireWildcard ( _utils ) ; function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } else { var newObj = { } ; if ( obj != null ) { for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) newObj [ key ] = obj [ key ] ; } } newObj . default = obj ; return newObj ; } }
function shimOnTrack ( window ) { if ( ( typeof window === 'undefined' ? 'undefined' : _typeof ( window ) ) === 'object' && window . RTCTrackEvent && 'receiver' in window . RTCTrackEvent . prototype && ! ( 'transceiver' in window . RTCTrackEvent . prototype ) ) { Object . defineProperty ( window . RTCTrackEvent . prototype , 'transceiver' , { get : function get ( ) { return { receiver : this . receiver } ; } } ) ; } }
function shimPeerConnection ( window ) { var browserDetails = utils . detectBrowser ( window ) ; if ( ( typeof window === 'undefined' ? 'undefined' : _typeof ( window ) ) !== 'object' || ! ( window . RTCPeerConnection || window . mozRTCPeerConnection ) ) { return ; }
if ( ! window . RTCPeerConnection && window . mozRTCPeerConnection ) { window . RTCPeerConnection = window . mozRTCPeerConnection ; }
[ 'setLocalDescription' , 'setRemoteDescription' , 'addIceCandidate' ] . forEach ( function ( method ) { var nativeMethod = window . RTCPeerConnection . prototype [ method ] ; window . RTCPeerConnection . prototype [ method ] = function ( ) { arguments [ 0 ] = new ( method === 'addIceCandidate' ? window . RTCIceCandidate : window . RTCSessionDescription ) ( arguments [ 0 ] ) ; return nativeMethod . apply ( this , arguments ) ; } ; } ) ; var nativeAddIceCandidate = window . RTCPeerConnection . prototype . addIceCandidate ; window . RTCPeerConnection . prototype . addIceCandidate = function ( ) { if ( ! arguments [ 0 ] ) { if ( arguments [ 1 ] ) { arguments [ 1 ] . apply ( null ) ; }
return Promise . resolve ( ) ; }
return nativeAddIceCandidate . apply ( this , arguments ) ; } ; var modernStatsTypes = { inboundrtp : 'inbound-rtp' , outboundrtp : 'outbound-rtp' , candidatepair : 'candidate-pair' , localcandidate : 'local-candidate' , remotecandidate : 'remote-candidate' } ; var nativeGetStats = window . RTCPeerConnection . prototype . getStats ; window . RTCPeerConnection . prototype . getStats = function ( selector , onSucc , onErr ) { return nativeGetStats . apply ( this , [ selector || null ] ) . then ( function ( stats ) { if ( browserDetails . version < 53 && ! onSucc ) { try { stats . forEach ( function ( stat ) { stat . type = modernStatsTypes [ stat . type ] || stat . type ; } ) ; } catch ( e ) { if ( e . name !== 'TypeError' ) { throw e ; }
stats . forEach ( function ( stat , i ) { stats . set ( i , Object . assign ( { } , stat , { type : modernStatsTypes [ stat . type ] || stat . type } ) ) ; } ) ; } }
return stats ; } ) . then ( onSucc , onErr ) ; } ; }
function shimSenderGetStats ( window ) { if ( ! ( ( typeof window === 'undefined' ? 'undefined' : _typeof ( window ) ) === 'object' && window . RTCPeerConnection && window . RTCRtpSender ) ) { return ; }
if ( window . RTCRtpSender && 'getStats' in window . RTCRtpSender . prototype ) { return ; }
var origGetSenders = window . RTCPeerConnection . prototype . getSenders ; if ( origGetSenders ) { window . RTCPeerConnection . prototype . getSenders = function ( ) { var _this = this ; var senders = origGetSenders . apply ( this , [ ] ) ; senders . forEach ( function ( sender ) { return sender . _pc = _this ; } ) ; return senders ; } ; }
var origAddTrack = window . RTCPeerConnection . prototype . addTrack ; if ( origAddTrack ) { window . RTCPeerConnection . prototype . addTrack = function ( ) { var sender = origAddTrack . apply ( this , arguments ) ; sender . _pc = this ; return sender ; } ; }
window . RTCRtpSender . prototype . getStats = function ( ) { return this . track ? this . _pc . getStats ( this . track ) : Promise . resolve ( new Map ( ) ) ; } ; }
function shimReceiverGetStats ( window ) { if ( ! ( ( typeof window === 'undefined' ? 'undefined' : _typeof ( window ) ) === 'object' && window . RTCPeerConnection && window . RTCRtpSender ) ) { return ; }
if ( window . RTCRtpSender && 'getStats' in window . RTCRtpReceiver . prototype ) { return ; }
var origGetReceivers = window . RTCPeerConnection . prototype . getReceivers ; if ( origGetReceivers ) { window . RTCPeerConnection . prototype . getReceivers = function ( ) { var _this2 = this ; var receivers = origGetReceivers . apply ( this , [ ] ) ; receivers . forEach ( function ( receiver ) { return receiver . _pc = _this2 ; } ) ; return receivers ; } ; }
utils . wrapPeerConnectionEvent ( window , 'track' , function ( e ) { e . receiver . _pc = e . srcElement ; return e ; } ) ; window . RTCRtpReceiver . prototype . getStats = function ( ) { return this . _pc . getStats ( this . track ) ; } ; }
function shimRemoveStream ( window ) { if ( ! window . RTCPeerConnection || 'removeStream' in window . RTCPeerConnection . prototype ) { return ; }
window . RTCPeerConnection . prototype . removeStream = function ( stream ) { var _this3 = this ; utils . deprecated ( 'removeStream' , 'removeTrack' ) ; this . getSenders ( ) . forEach ( function ( sender ) { if ( sender . track && stream . getTracks ( ) . includes ( sender . track ) ) { _this3 . removeTrack ( sender ) ; } } ) ; } ; }
function shimRTCDataChannel ( window ) { if ( window . DataChannel && ! window . RTCDataChannel ) { window . RTCDataChannel = window . DataChannel ; } } } , { "../utils" : 15 , "./getdisplaymedia" : 12 , "./getusermedia" : 13 } ] , 12 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; exports . shimGetDisplayMedia = shimGetDisplayMedia ; function shimGetDisplayMedia ( window , preferredMediaSource ) { if ( window . navigator . mediaDevices && 'getDisplayMedia' in window . navigator . mediaDevices ) { return ; }
if ( ! window . navigator . mediaDevices ) { return ; }
window . navigator . mediaDevices . getDisplayMedia = function ( constraints ) { if ( ! ( constraints && constraints . video ) ) { var err = new DOMException ( 'getDisplayMedia without video ' + 'constraints is undefined' ) ; err . name = 'NotFoundError' ; err . code = 8 ; return Promise . reject ( err ) ; }
if ( constraints . video === true ) { constraints . video = { mediaSource : preferredMediaSource } ; } else { constraints . video . mediaSource = preferredMediaSource ; }
return window . navigator . mediaDevices . getUserMedia ( constraints ) ; } ; } } , { } ] , 13 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; var _typeof = typeof Symbol === "function" && typeof Symbol . iterator === "symbol" ? function ( obj ) { return typeof obj ; } : function ( obj ) { return obj && typeof Symbol === "function" && obj . constructor === Symbol && obj !== Symbol . prototype ? "symbol" : typeof obj ; } ; exports . shimGetUserMedia = shimGetUserMedia ; var _utils = require ( '../utils' ) ; var utils = _interopRequireWildcard ( _utils ) ; function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } else { var newObj = { } ; if ( obj != null ) { for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) newObj [ key ] = obj [ key ] ; } } newObj . default = obj ; return newObj ; } }
function shimGetUserMedia ( window ) { var browserDetails = utils . detectBrowser ( window ) ; var navigator = window && window . navigator ; var MediaStreamTrack = window && window . MediaStreamTrack ; navigator . getUserMedia = function ( constraints , onSuccess , onError ) { utils . deprecated ( 'navigator.getUserMedia' , 'navigator.mediaDevices.getUserMedia' ) ; navigator . mediaDevices . getUserMedia ( constraints ) . then ( onSuccess , onError ) ; } ; if ( ! ( browserDetails . version > 55 && 'autoGainControl' in navigator . mediaDevices . getSupportedConstraints ( ) ) ) { var remap = function remap ( obj , a , b ) { if ( a in obj && ! ( b in obj ) ) { obj [ b ] = obj [ a ] ; delete obj [ a ] ; } } ; var nativeGetUserMedia = navigator . mediaDevices . getUserMedia . bind ( navigator . mediaDevices ) ; navigator . mediaDevices . getUserMedia = function ( c ) { if ( ( typeof c === 'undefined' ? 'undefined' : _typeof ( c ) ) === 'object' && _typeof ( c . audio ) === 'object' ) { c = JSON . parse ( JSON . stringify ( c ) ) ; remap ( c . audio , 'autoGainControl' , 'mozAutoGainControl' ) ; remap ( c . audio , 'noiseSuppression' , 'mozNoiseSuppression' ) ; }
return nativeGetUserMedia ( c ) ; } ; if ( MediaStreamTrack && MediaStreamTrack . prototype . getSettings ) { var nativeGetSettings = MediaStreamTrack . prototype . getSettings ; MediaStreamTrack . prototype . getSettings = function ( ) { var obj = nativeGetSettings . apply ( this , arguments ) ; remap ( obj , 'mozAutoGainControl' , 'autoGainControl' ) ; remap ( obj , 'mozNoiseSuppression' , 'noiseSuppression' ) ; return obj ; } ; }
if ( MediaStreamTrack && MediaStreamTrack . prototype . applyConstraints ) { var nativeApplyConstraints = MediaStreamTrack . prototype . applyConstraints ; MediaStreamTrack . prototype . applyConstraints = function ( c ) { if ( this . kind === 'audio' && ( typeof c === 'undefined' ? 'undefined' : _typeof ( c ) ) === 'object' ) { c = JSON . parse ( JSON . stringify ( c ) ) ; remap ( c , 'autoGainControl' , 'mozAutoGainControl' ) ; remap ( c , 'noiseSuppression' , 'mozNoiseSuppression' ) ; }
return nativeApplyConstraints . apply ( this , [ c ] ) ; } ; } } } } , { "../utils" : 15 } ] , 14 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; var _typeof = typeof Symbol === "function" && typeof Symbol . iterator === "symbol" ? function ( obj ) { return typeof obj ; } : function ( obj ) { return obj && typeof Symbol === "function" && obj . constructor === Symbol && obj !== Symbol . prototype ? "symbol" : typeof obj ; } ; exports . shimLocalStreamsAPI = shimLocalStreamsAPI ; exports . shimRemoteStreamsAPI = shimRemoteStreamsAPI ; exports . shimCallbacksAPI = shimCallbacksAPI ; exports . shimGetUserMedia = shimGetUserMedia ; exports . shimConstraints = shimConstraints ; exports . shimRTCIceServerUrls = shimRTCIceServerUrls ; exports . shimTrackEventTransceiver = shimTrackEventTransceiver ; exports . shimCreateOfferLegacy = shimCreateOfferLegacy ; var _utils = require ( '../utils' ) ; var utils = _interopRequireWildcard ( _utils ) ; function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } else { var newObj = { } ; if ( obj != null ) { for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) newObj [ key ] = obj [ key ] ; } } newObj . default = obj ; return newObj ; } }
function shimLocalStreamsAPI ( window ) { if ( ( typeof window === 'undefined' ? 'undefined' : _typeof ( window ) ) !== 'object' || ! window . RTCPeerConnection ) { return ; }
if ( ! ( 'getLocalStreams' in window . RTCPeerConnection . prototype ) ) { window . RTCPeerConnection . prototype . getLocalStreams = function ( ) { if ( ! this . _localStreams ) { this . _localStreams = [ ] ; }
return this . _localStreams ; } ; }
if ( ! ( 'addStream' in window . RTCPeerConnection . prototype ) ) { var _addTrack = window . RTCPeerConnection . prototype . addTrack ; window . RTCPeerConnection . prototype . addStream = function ( stream ) { var _this = this ; if ( ! this . _localStreams ) { this . _localStreams = [ ] ; }
if ( ! this . _localStreams . includes ( stream ) ) { this . _localStreams . push ( stream ) ; }
stream . getTracks ( ) . forEach ( function ( track ) { return _addTrack . call ( _this , track , stream ) ; } ) ; } ; window . RTCPeerConnection . prototype . addTrack = function ( track , stream ) { if ( stream ) { if ( ! this . _localStreams ) { this . _localStreams = [ stream ] ; } else if ( ! this . _localStreams . includes ( stream ) ) { this . _localStreams . push ( stream ) ; } }
return _addTrack . call ( this , track , stream ) ; } ; }
if ( ! ( 'removeStream' in window . RTCPeerConnection . prototype ) ) { window . RTCPeerConnection . prototype . removeStream = function ( stream ) { var _this2 = this ; if ( ! this . _localStreams ) { this . _localStreams = [ ] ; }
var index = this . _localStreams . indexOf ( stream ) ; if ( index === - 1 ) { return ; }
this . _localStreams . splice ( index , 1 ) ; var tracks = stream . getTracks ( ) ; this . getSenders ( ) . forEach ( function ( sender ) { if ( tracks . includes ( sender . track ) ) { _this2 . removeTrack ( sender ) ; } } ) ; } ; } }
function shimRemoteStreamsAPI ( window ) { if ( ( typeof window === 'undefined' ? 'undefined' : _typeof ( window ) ) !== 'object' || ! window . RTCPeerConnection ) { return ; }
if ( ! ( 'getRemoteStreams' in window . RTCPeerConnection . prototype ) ) { window . RTCPeerConnection . prototype . getRemoteStreams = function ( ) { return this . _remoteStreams ? this . _remoteStreams : [ ] ; } ; }
if ( ! ( 'onaddstream' in window . RTCPeerConnection . prototype ) ) { Object . defineProperty ( window . RTCPeerConnection . prototype , 'onaddstream' , { get : function get ( ) { return this . _onaddstream ; } , set : function set ( f ) { var _this3 = this ; if ( this . _onaddstream ) { this . removeEventListener ( 'addstream' , this . _onaddstream ) ; this . removeEventListener ( 'track' , this . _onaddstreampoly ) ; }
this . addEventListener ( 'addstream' , this . _onaddstream = f ) ; this . addEventListener ( 'track' , this . _onaddstreampoly = function ( e ) { e . streams . forEach ( function ( stream ) { if ( ! _this3 . _remoteStreams ) { _this3 . _remoteStreams = [ ] ; }
if ( _this3 . _remoteStreams . includes ( stream ) ) { return ; }
_this3 . _remoteStreams . push ( stream ) ; var event = new Event ( 'addstream' ) ; event . stream = stream ; _this3 . dispatchEvent ( event ) ; } ) ; } ) ; } } ) ; var origSetRemoteDescription = window . RTCPeerConnection . prototype . setRemoteDescription ; window . RTCPeerConnection . prototype . setRemoteDescription = function ( ) { var pc = this ; if ( ! this . _onaddstreampoly ) { this . addEventListener ( 'track' , this . _onaddstreampoly = function ( e ) { e . streams . forEach ( function ( stream ) { if ( ! pc . _remoteStreams ) { pc . _remoteStreams = [ ] ; }
if ( pc . _remoteStreams . indexOf ( stream ) >= 0 ) { return ; }
pc . _remoteStreams . push ( stream ) ; var event = new Event ( 'addstream' ) ; event . stream = stream ; pc . dispatchEvent ( event ) ; } ) ; } ) ; }
return origSetRemoteDescription . apply ( pc , arguments ) ; } ; } }
function shimCallbacksAPI ( window ) { if ( ( typeof window === 'undefined' ? 'undefined' : _typeof ( window ) ) !== 'object' || ! window . RTCPeerConnection ) { return ; }
var prototype = window . RTCPeerConnection . prototype ; var createOffer = prototype . createOffer ; var createAnswer = prototype . createAnswer ; var setLocalDescription = prototype . setLocalDescription ; var setRemoteDescription = prototype . setRemoteDescription ; var addIceCandidate = prototype . addIceCandidate ; prototype . createOffer = function ( successCallback , failureCallback ) { var options = arguments . length >= 2 ? arguments [ 2 ] : arguments [ 0 ] ; var promise = createOffer . apply ( this , [ options ] ) ; if ( ! failureCallback ) { return promise ; }
promise . then ( successCallback , failureCallback ) ; return Promise . resolve ( ) ; } ; prototype . createAnswer = function ( successCallback , failureCallback ) { var options = arguments . length >= 2 ? arguments [ 2 ] : arguments [ 0 ] ; var promise = createAnswer . apply ( this , [ options ] ) ; if ( ! failureCallback ) { return promise ; }
promise . then ( successCallback , failureCallback ) ; return Promise . resolve ( ) ; } ; var withCallback = function withCallback ( description , successCallback , failureCallback ) { var promise = setLocalDescription . apply ( this , [ description ] ) ; if ( ! failureCallback ) { return promise ; }
promise . then ( successCallback , failureCallback ) ; return Promise . resolve ( ) ; } ; prototype . setLocalDescription = withCallback ; withCallback = function withCallback ( description , successCallback , failureCallback ) { var promise = setRemoteDescription . apply ( this , [ description ] ) ; if ( ! failureCallback ) { return promise ; }
promise . then ( successCallback , failureCallback ) ; return Promise . resolve ( ) ; } ; prototype . setRemoteDescription = withCallback ; withCallback = function withCallback ( candidate , successCallback , failureCallback ) { var promise = addIceCandidate . apply ( this , [ candidate ] ) ; if ( ! failureCallback ) { return promise ; }
promise . then ( successCallback , failureCallback ) ; return Promise . resolve ( ) ; } ; prototype . addIceCandidate = withCallback ; }
function shimGetUserMedia ( window ) { var navigator = window && window . navigator ; if ( navigator . mediaDevices && navigator . mediaDevices . getUserMedia ) { var mediaDevices = navigator . mediaDevices ; var _getUserMedia = mediaDevices . getUserMedia . bind ( mediaDevices ) ; navigator . mediaDevices . getUserMedia = function ( constraints ) { return _getUserMedia ( shimConstraints ( constraints ) ) ; } ; }
if ( ! navigator . getUserMedia && navigator . mediaDevices && navigator . mediaDevices . getUserMedia ) { navigator . getUserMedia = function ( constraints , cb , errcb ) { navigator . mediaDevices . getUserMedia ( constraints ) . then ( cb , errcb ) ; } . bind ( navigator ) ; } }
function shimConstraints ( constraints ) { if ( constraints && constraints . video !== undefined ) { return Object . assign ( { } , constraints , { video : utils . compactObject ( constraints . video ) } ) ; }
return constraints ; }
function shimRTCIceServerUrls ( window ) { var OrigPeerConnection = window . RTCPeerConnection ; window . RTCPeerConnection = function ( pcConfig , pcConstraints ) { if ( pcConfig && pcConfig . iceServers ) { var newIceServers = [ ] ; for ( var i = 0 ; i < pcConfig . iceServers . length ; i ++ ) { var server = pcConfig . iceServers [ i ] ; if ( ! server . hasOwnProperty ( 'urls' ) && server . hasOwnProperty ( 'url' ) ) { utils . deprecated ( 'RTCIceServer.url' , 'RTCIceServer.urls' ) ; server = JSON . parse ( JSON . stringify ( server ) ) ; server . urls = server . url ; delete server . url ; newIceServers . push ( server ) ; } else { newIceServers . push ( pcConfig . iceServers [ i ] ) ; } }
pcConfig . iceServers = newIceServers ; }
return new OrigPeerConnection ( pcConfig , pcConstraints ) ; } ; window . RTCPeerConnection . prototype = OrigPeerConnection . prototype ; if ( 'generateCertificate' in window . RTCPeerConnection ) { Object . defineProperty ( window . RTCPeerConnection , 'generateCertificate' , { get : function get ( ) { return OrigPeerConnection . generateCertificate ; } } ) ; } }
function shimTrackEventTransceiver ( window ) { if ( ( typeof window === 'undefined' ? 'undefined' : _typeof ( window ) ) === 'object' && window . RTCPeerConnection && 'receiver' in window . RTCTrackEvent . prototype && ! window . RTCTransceiver ) { Object . defineProperty ( window . RTCTrackEvent . prototype , 'transceiver' , { get : function get ( ) { return { receiver : this . receiver } ; } } ) ; } }
function shimCreateOfferLegacy ( window ) { var origCreateOffer = window . RTCPeerConnection . prototype . createOffer ; window . RTCPeerConnection . prototype . createOffer = function ( offerOptions ) { if ( offerOptions ) { if ( typeof offerOptions . offerToReceiveAudio !== 'undefined' ) { offerOptions . offerToReceiveAudio = ! ! offerOptions . offerToReceiveAudio ; }
var audioTransceiver = this . getTransceivers ( ) . find ( function ( transceiver ) { return transceiver . sender . track && transceiver . sender . track . kind === 'audio' ; } ) ; if ( offerOptions . offerToReceiveAudio === false && audioTransceiver ) { if ( audioTransceiver . direction === 'sendrecv' ) { if ( audioTransceiver . setDirection ) { audioTransceiver . setDirection ( 'sendonly' ) ; } else { audioTransceiver . direction = 'sendonly' ; } } else if ( audioTransceiver . direction === 'recvonly' ) { if ( audioTransceiver . setDirection ) { audioTransceiver . setDirection ( 'inactive' ) ; } else { audioTransceiver . direction = 'inactive' ; } } } else if ( offerOptions . offerToReceiveAudio === true && ! audioTransceiver ) { this . addTransceiver ( 'audio' ) ; }
if ( typeof offerOptions . offerToReceiveVideo !== 'undefined' ) { offerOptions . offerToReceiveVideo = ! ! offerOptions . offerToReceiveVideo ; }
var videoTransceiver = this . getTransceivers ( ) . find ( function ( transceiver ) { return transceiver . sender . track && transceiver . sender . track . kind === 'video' ; } ) ; if ( offerOptions . offerToReceiveVideo === false && videoTransceiver ) { if ( videoTransceiver . direction === 'sendrecv' ) { if ( videoTransceiver . setDirection ) { videoTransceiver . setDirection ( 'sendonly' ) ; } else { videoTransceiver . direction = 'sendonly' ; } } else if ( videoTransceiver . direction === 'recvonly' ) { if ( videoTransceiver . setDirection ) { videoTransceiver . setDirection ( 'inactive' ) ; } else { videoTransceiver . direction = 'inactive' ; } } } else if ( offerOptions . offerToReceiveVideo === true && ! videoTransceiver ) { this . addTransceiver ( 'video' ) ; } }
return origCreateOffer . apply ( this , arguments ) ; } ; } } , { "../utils" : 15 } ] , 15 : [ function ( require , module , exports ) { 'use strict' ; Object . defineProperty ( exports , "__esModule" , { value : true } ) ; var _typeof = typeof Symbol === "function" && typeof Symbol . iterator === "symbol" ? function ( obj ) { return typeof obj ; } : function ( obj ) { return obj && typeof Symbol === "function" && obj . constructor === Symbol && obj !== Symbol . prototype ? "symbol" : typeof obj ; } ; exports . extractVersion = extractVersion ; exports . wrapPeerConnectionEvent = wrapPeerConnectionEvent ; exports . disableLog = disableLog ; exports . disableWarnings = disableWarnings ; exports . log = log ; exports . deprecated = deprecated ; exports . detectBrowser = detectBrowser ; exports . compactObject = compactObject ; function _defineProperty ( obj , key , value ) { if ( key in obj ) { Object . defineProperty ( obj , key , { value : value , enumerable : true , configurable : true , writable : true } ) ; } else { obj [ key ] = value ; } return obj ; }
var logDisabled _ = true ; var deprecationWarnings _ = true ; function extractVersion ( uastring , expr , pos ) { var match = uastring . match ( expr ) ; return match && match . length >= pos && parseInt ( match [ pos ] , 10 ) ; }
function wrapPeerConnectionEvent ( window , eventNameToWrap , wrapper ) { if ( ! window . RTCPeerConnection ) { return ; }
var proto = window . RTCPeerConnection . prototype ; var nativeAddEventListener = proto . addEventListener ; proto . addEventListener = function ( nativeEventName , cb ) { if ( nativeEventName !== eventNameToWrap ) { return nativeAddEventListener . apply ( this , arguments ) ; }
var wrappedCallback = function wrappedCallback ( e ) { var modifiedEvent = wrapper ( e ) ; if ( modifiedEvent ) { cb ( modifiedEvent ) ; } } ; this . _eventMap = this . _eventMap || { } ; this . _eventMap [ cb ] = wrappedCallback ; return nativeAddEventListener . apply ( this , [ nativeEventName , wrappedCallback ] ) ; } ; var nativeRemoveEventListener = proto . removeEventListener ; proto . removeEventListener = function ( nativeEventName , cb ) { if ( nativeEventName !== eventNameToWrap || ! this . _eventMap || ! this . _eventMap [ cb ] ) { return nativeRemoveEventListener . apply ( this , arguments ) ; }
var unwrappedCb = this . _eventMap [ cb ] ; delete this . _eventMap [ cb ] ; return nativeRemoveEventListener . apply ( this , [ nativeEventName , unwrappedCb ] ) ; } ; Object . defineProperty ( proto , 'on' + eventNameToWrap , { get : function get ( ) { return this [ '_on' + eventNameToWrap ] ; } , set : function set ( cb ) { if ( this [ '_on' + eventNameToWrap ] ) { this . removeEventListener ( eventNameToWrap , this [ '_on' + eventNameToWrap ] ) ; delete this [ '_on' + eventNameToWrap ] ; }
if ( cb ) { this . addEventListener ( eventNameToWrap , this [ '_on' + eventNameToWrap ] = cb ) ; } } , enumerable : true , configurable : true } ) ; }
function disableLog ( bool ) { if ( typeof bool !== 'boolean' ) { return new Error ( 'Argument type: ' + ( typeof bool === 'undefined' ? 'undefined' : _typeof ( bool ) ) + '. Please use a boolean.' ) ; }
logDisabled _ = bool ; return bool ? 'adapter.js logging disabled' : 'adapter.js logging enabled' ; }
function disableWarnings ( bool ) { if ( typeof bool !== 'boolean' ) { return new Error ( 'Argument type: ' + ( typeof bool === 'undefined' ? 'undefined' : _typeof ( bool ) ) + '. Please use a boolean.' ) ; }
deprecationWarnings _ = ! bool ; return 'adapter.js deprecation warnings ' + ( bool ? 'disabled' : 'enabled' ) ; }
function log ( ) { if ( ( typeof window === 'undefined' ? 'undefined' : _typeof ( window ) ) === 'object' ) { if ( logDisabled _ ) { return ; }
if ( typeof console !== 'undefined' && typeof console . log === 'function' ) { console . log . apply ( console , arguments ) ; } } }
function deprecated ( oldMethod , newMethod ) { if ( ! deprecationWarnings _ ) { return ; }
console . warn ( oldMethod + ' is deprecated, please use ' + newMethod + ' instead.' ) ; }
function detectBrowser ( window ) { var navigator = window . navigator ; var result = { browser : null , version : null } ; if ( typeof window === 'undefined' || ! window . navigator ) { result . browser = 'Not a browser.' ; return result ; }
if ( navigator . mozGetUserMedia ) { result . browser = 'firefox' ; result . version = extractVersion ( navigator . userAgent , /Firefox\/(\d+)\./ , 1 ) ; } else if ( navigator . webkitGetUserMedia ) { result . browser = 'chrome' ; result . version = extractVersion ( navigator . userAgent , /Chrom(e|ium)\/(\d+)\./ , 2 ) ; } else if ( navigator . mediaDevices && navigator . userAgent . match ( /Edge\/(\d+).(\d+)$/ ) ) { result . browser = 'edge' ; result . version = extractVersion ( navigator . userAgent , /Edge\/(\d+).(\d+)$/ , 2 ) ; } else if ( window . RTCPeerConnection && navigator . userAgent . match ( /AppleWebKit\/(\d+)\./ ) ) { result . browser = 'safari' ; result . version = extractVersion ( navigator . userAgent , /AppleWebKit\/(\d+)\./ , 1 ) ; } else { result . browser = 'Not a supported browser.' ; return result ; }
return result ; }
function compactObject ( data ) { if ( ( typeof data === 'undefined' ? 'undefined' : _typeof ( data ) ) !== 'object' ) { return data ; }
return Object . keys ( data ) . reduce ( function ( accumulator , key ) { var isObject = _typeof ( data [ key ] ) === 'object' ; var value = isObject ? compactObject ( data [ key ] ) : data [ key ] ; var isEmptyObject = isObject && ! Object . keys ( value ) . length ; if ( value === undefined || isEmptyObject ) { return accumulator ; }
return Object . assign ( accumulator , _defineProperty ( { } , key , value ) ) ; } , { } ) ; } } , { } ] , 16 : [ function ( require , module , exports ) { 'use strict' ; var SDPUtils = require ( 'sdp' ) ; function fixStatsType ( stat ) { return { inboundrtp : 'inbound-rtp' , outboundrtp : 'outbound-rtp' , candidatepair : 'candidate-pair' , localcandidate : 'local-candidate' , remotecandidate : 'remote-candidate' } [ stat . type ] || stat . type ; }
function writeMediaSection ( transceiver , caps , type , stream , dtlsRole ) { var sdp = SDPUtils . writeRtpDescription ( transceiver . kind , caps ) ; sdp += SDPUtils . writeIceParameters ( transceiver . iceGatherer . getLocalParameters ( ) ) ; sdp += SDPUtils . writeDtlsParameters ( transceiver . dtlsTransport . getLocalParameters ( ) , type === 'offer' ? 'actpass' : dtlsRole || 'active' ) ; sdp += 'a=mid:' + transceiver . mid + '\r\n' ; if ( transceiver . rtpSender && transceiver . rtpReceiver ) { sdp += 'a=sendrecv\r\n' ; } else if ( transceiver . rtpSender ) { sdp += 'a=sendonly\r\n' ; } else if ( transceiver . rtpReceiver ) { sdp += 'a=recvonly\r\n' ; } else { sdp += 'a=inactive\r\n' ; }
if ( transceiver . rtpSender ) { var trackId = transceiver . rtpSender . _initialTrackId || transceiver . rtpSender . track . id ; transceiver . rtpSender . _initialTrackId = trackId ; var msid = 'msid:' + ( stream ? stream . id : '-' ) + ' ' +
trackId + '\r\n' ; sdp += 'a=' + msid ; sdp += 'a=ssrc:' + transceiver . sendEncodingParameters [ 0 ] . ssrc + ' ' + msid ; if ( transceiver . sendEncodingParameters [ 0 ] . rtx ) { sdp += 'a=ssrc:' + transceiver . sendEncodingParameters [ 0 ] . rtx . ssrc + ' ' + msid ; sdp += 'a=ssrc-group:FID ' +
transceiver . sendEncodingParameters [ 0 ] . ssrc + ' ' +
transceiver . sendEncodingParameters [ 0 ] . rtx . ssrc + '\r\n' ; } }
sdp += 'a=ssrc:' + transceiver . sendEncodingParameters [ 0 ] . ssrc + ' cname:' + SDPUtils . localCName + '\r\n' ; if ( transceiver . rtpSender && transceiver . sendEncodingParameters [ 0 ] . rtx ) { sdp += 'a=ssrc:' + transceiver . sendEncodingParameters [ 0 ] . rtx . ssrc + ' cname:' + SDPUtils . localCName + '\r\n' ; }
return sdp ; }
function filterIceServers ( iceServers , edgeVersion ) { var hasTurn = false ; iceServers = JSON . parse ( JSON . stringify ( iceServers ) ) ; return iceServers . filter ( function ( server ) { if ( server && ( server . urls || server . url ) ) { var urls = server . urls || server . url ; if ( server . url && ! server . urls ) { console . warn ( 'RTCIceServer.url is deprecated! Use urls instead.' ) ; }
var isString = typeof urls === 'string' ; if ( isString ) { urls = [ urls ] ; }
urls = urls . filter ( function ( url ) { var validTurn = url . indexOf ( 'turn:' ) === 0 && url . indexOf ( 'transport=udp' ) !== - 1 && url . indexOf ( 'turn:[' ) === - 1 && ! hasTurn ; if ( validTurn ) { hasTurn = true ; return true ; }
return url . indexOf ( 'stun:' ) === 0 && edgeVersion >= 14393 && url . indexOf ( '?transport=udp' ) === - 1 ; } ) ; delete server . url ; server . urls = isString ? urls [ 0 ] : urls ; return ! ! urls . length ; } } ) ; }
function getCommonCapabilities ( localCapabilities , remoteCapabilities ) { var commonCapabilities = { codecs : [ ] , headerExtensions : [ ] , fecMechanisms : [ ] } ; var findCodecByPayloadType = function ( pt , codecs ) { pt = parseInt ( pt , 10 ) ; for ( var i = 0 ; i < codecs . length ; i ++ ) { if ( codecs [ i ] . payloadType === pt || codecs [ i ] . preferredPayloadType === pt ) { return codecs [ i ] ; } } } ; var rtxCapabilityMatches = function ( lRtx , rRtx , lCodecs , rCodecs ) { var lCodec = findCodecByPayloadType ( lRtx . parameters . apt , lCodecs ) ; var rCodec = findCodecByPayloadType ( rRtx . parameters . apt , rCodecs ) ; return lCodec && rCodec && lCodec . name . toLowerCase ( ) === rCodec . name . toLowerCase ( ) ; } ; localCapabilities . codecs . forEach ( function ( lCodec ) { for ( var i = 0 ; i < remoteCapabilities . codecs . length ; i ++ ) { var rCodec = remoteCapabilities . codecs [ i ] ; if ( lCodec . name . toLowerCase ( ) === rCodec . name . toLowerCase ( ) && lCodec . clockRate === rCodec . clockRate ) { if ( lCodec . name . toLowerCase ( ) === 'rtx' && lCodec . parameters && rCodec . parameters . apt ) { if ( ! rtxCapabilityMatches ( lCodec , rCodec , localCapabilities . codecs , remoteCapabilities . codecs ) ) { continue ; } }
rCodec = JSON . parse ( JSON . stringify ( rCodec ) ) ; rCodec . numChannels = Math . min ( lCodec . numChannels , rCodec . numChannels ) ; commonCapabilities . codecs . push ( rCodec ) ; rCodec . rtcpFeedback = rCodec . rtcpFeedback . filter ( function ( fb ) { for ( var j = 0 ; j < lCodec . rtcpFeedback . length ; j ++ ) { if ( lCodec . rtcpFeedback [ j ] . type === fb . type && lCodec . rtcpFeedback [ j ] . parameter === fb . parameter ) { return true ; } }
return false ; } ) ; break ; } } } ) ; localCapabilities . headerExtensions . forEach ( function ( lHeaderExtension ) { for ( var i = 0 ; i < remoteCapabilities . headerExtensions . length ; i ++ ) { var rHeaderExtension = remoteCapabilities . headerExtensions [ i ] ; if ( lHeaderExtension . uri === rHeaderExtension . uri ) { commonCapabilities . headerExtensions . push ( rHeaderExtension ) ; break ; } } } ) ; return commonCapabilities ; }
function isActionAllowedInSignalingState ( action , type , signalingState ) { return { offer : { setLocalDescription : [ 'stable' , 'have-local-offer' ] , setRemoteDescription : [ 'stable' , 'have-remote-offer' ] } , answer : { setLocalDescription : [ 'have-remote-offer' , 'have-local-pranswer' ] , setRemoteDescription : [ 'have-local-offer' , 'have-remote-pranswer' ] } } [ type ] [ action ] . indexOf ( signalingState ) !== - 1 ; }
function maybeAddCandidate ( iceTransport , candidate ) { var alreadyAdded = iceTransport . getRemoteCandidates ( ) . find ( function ( remoteCandidate ) { return candidate . foundation === remoteCandidate . foundation && candidate . ip === remoteCandidate . ip && candidate . port === remoteCandidate . port && candidate . priority === remoteCandidate . priority && candidate . protocol === remoteCandidate . protocol && candidate . type === remoteCandidate . type ; } ) ; if ( ! alreadyAdded ) { iceTransport . addRemoteCandidate ( candidate ) ; }
return ! alreadyAdded ; }
function makeError ( name , description ) { var e = new Error ( description ) ; e . name = name ; e . code = { NotSupportedError : 9 , InvalidStateError : 11 , InvalidAccessError : 15 , TypeError : undefined , OperationError : undefined } [ name ] ; return e ; }
module . exports = function ( window , edgeVersion ) { function addTrackToStreamAndFireEvent ( track , stream ) { stream . addTrack ( track ) ; stream . dispatchEvent ( new window . MediaStreamTrackEvent ( 'addtrack' , { track : track } ) ) ; }
function removeTrackFromStreamAndFireEvent ( track , stream ) { stream . removeTrack ( track ) ; stream . dispatchEvent ( new window . MediaStreamTrackEvent ( 'removetrack' , { track : track } ) ) ; }
function fireAddTrack ( pc , track , receiver , streams ) { var trackEvent = new Event ( 'track' ) ; trackEvent . track = track ; trackEvent . receiver = receiver ; trackEvent . transceiver = { receiver : receiver } ; trackEvent . streams = streams ; window . setTimeout ( function ( ) { pc . _dispatchEvent ( 'track' , trackEvent ) ; } ) ; }
var RTCPeerConnection = function ( config ) { var pc = this ; var _eventTarget = document . createDocumentFragment ( ) ; [ 'addEventListener' , 'removeEventListener' , 'dispatchEvent' ] . forEach ( function ( method ) { pc [ method ] = _eventTarget [ method ] . bind ( _eventTarget ) ; } ) ; this . canTrickleIceCandidates = null ; this . needNegotiation = false ; this . localStreams = [ ] ; this . remoteStreams = [ ] ; this . _localDescription = null ; this . _remoteDescription = null ; this . signalingState = 'stable' ; this . iceConnectionState = 'new' ; this . connectionState = 'new' ; this . iceGatheringState = 'new' ; config = JSON . parse ( JSON . stringify ( config || { } ) ) ; this . usingBundle = config . bundlePolicy === 'max-bundle' ; if ( config . rtcpMuxPolicy === 'negotiate' ) { throw ( makeError ( 'NotSupportedError' , 'rtcpMuxPolicy \'negotiate\' is not supported' ) ) ; } else if ( ! config . rtcpMuxPolicy ) { config . rtcpMuxPolicy = 'require' ; }
switch ( config . iceTransportPolicy ) { case 'all' : case 'relay' : break ; default : config . iceTransportPolicy = 'all' ; break ; }
switch ( config . bundlePolicy ) { case 'balanced' : case 'max-compat' : case 'max-bundle' : break ; default : config . bundlePolicy = 'balanced' ; break ; }
config . iceServers = filterIceServers ( config . iceServers || [ ] , edgeVersion ) ; this . _iceGatherers = [ ] ; if ( config . iceCandidatePoolSize ) { for ( var i = config . iceCandidatePoolSize ; i > 0 ; i -- ) { this . _iceGatherers . push ( new window . RTCIceGatherer ( { iceServers : config . iceServers , gatherPolicy : config . iceTransportPolicy } ) ) ; } } else { config . iceCandidatePoolSize = 0 ; }
this . _config = config ; this . transceivers = [ ] ; this . _sdpSessionId = SDPUtils . generateSessionId ( ) ; this . _sdpSessionVersion = 0 ; this . _dtlsRole = undefined ; this . _isClosed = false ; } ; Object . defineProperty ( RTCPeerConnection . prototype , 'localDescription' , { configurable : true , get : function ( ) { return this . _localDescription ; } } ) ; Object . defineProperty ( RTCPeerConnection . prototype , 'remoteDescription' , { configurable : true , get : function ( ) { return this . _remoteDescription ; } } ) ; RTCPeerConnection . prototype . onicecandidate = null ; RTCPeerConnection . prototype . onaddstream = null ; RTCPeerConnection . prototype . ontrack = null ; RTCPeerConnection . prototype . onremovestream = null ; RTCPeerConnection . prototype . onsignalingstatechange = null ; RTCPeerConnection . prototype . oniceconnectionstatechange = null ; RTCPeerConnection . prototype . onconnectionstatechange = null ; RTCPeerConnection . prototype . onicegatheringstatechange = null ; RTCPeerConnection . prototype . onnegotiationneeded = null ; RTCPeerConnection . prototype . ondatachannel = null ; RTCPeerConnection . prototype . _dispatchEvent = function ( name , event ) { if ( this . _isClosed ) { return ; }
this . dispatchEvent ( event ) ; if ( typeof this [ 'on' + name ] === 'function' ) { this [ 'on' + name ] ( event ) ; } } ; RTCPeerConnection . prototype . _emitGatheringStateChange = function ( ) { var event = new Event ( 'icegatheringstatechange' ) ; this . _dispatchEvent ( 'icegatheringstatechange' , event ) ; } ; RTCPeerConnection . prototype . getConfiguration = function ( ) { return this . _config ; } ; RTCPeerConnection . prototype . getLocalStreams = function ( ) { return this . localStreams ; } ; RTCPeerConnection . prototype . getRemoteStreams = function ( ) { return this . remoteStreams ; } ; RTCPeerConnection . prototype . _createTransceiver = function ( kind , doNotAdd ) { var hasBundleTransport = this . transceivers . length > 0 ; var transceiver = { track : null , iceGatherer : null , iceTransport : null , dtlsTransport : null , localCapabilities : null , remoteCapabilities : null , rtpSender : null , rtpReceiver : null , kind : kind , mid : null , sendEncodingParameters : null , recvEncodingParameters : null , stream : null , associatedRemoteMediaStreams : [ ] , wantReceive : true } ; if ( this . usingBundle && hasBundleTransport ) { transceiver . iceTransport = this . transceivers [ 0 ] . iceTransport ; transceiver . dtlsTransport = this . transceivers [ 0 ] . dtlsTransport ; } else { var transports = this . _createIceAndDtlsTransports ( ) ; transceiver . iceTransport = transports . iceTransport ; transceiver . dtlsTransport = transports . dtlsTransport ; }
if ( ! doNotAdd ) { this . transceivers . push ( transceiver ) ; }
return transceiver ; } ; RTCPeerConnection . prototype . addTrack = function ( track , stream ) { if ( this . _isClosed ) { throw makeError ( 'InvalidStateError' , 'Attempted to call addTrack on a closed peerconnection.' ) ; }
var alreadyExists = this . transceivers . find ( function ( s ) { return s . track === track ; } ) ; if ( alreadyExists ) { throw makeError ( 'InvalidAccessError' , 'Track already exists.' ) ; }
var transceiver ; for ( var i = 0 ; i < this . transceivers . length ; i ++ ) { if ( ! this . transceivers [ i ] . track && this . transceivers [ i ] . kind === track . kind ) { transceiver = this . transceivers [ i ] ; } }
if ( ! transceiver ) { transceiver = this . _createTransceiver ( track . kind ) ; }
this . _maybeFireNegotiationNeeded ( ) ; if ( this . localStreams . indexOf ( stream ) === - 1 ) { this . localStreams . push ( stream ) ; }
transceiver . track = track ; transceiver . stream = stream ; transceiver . rtpSender = new window . RTCRtpSender ( track , transceiver . dtlsTransport ) ; return transceiver . rtpSender ; } ; RTCPeerConnection . prototype . addStream = function ( stream ) { var pc = this ; if ( edgeVersion >= 15025 ) { stream . getTracks ( ) . forEach ( function ( track ) { pc . addTrack ( track , stream ) ; } ) ; } else { var clonedStream = stream . clone ( ) ; stream . getTracks ( ) . forEach ( function ( track , idx ) { var clonedTrack = clonedStream . getTracks ( ) [ idx ] ; track . addEventListener ( 'enabled' , function ( event ) { clonedTrack . enabled = event . enabled ; } ) ; } ) ; clonedStream . getTracks ( ) . forEach ( function ( track ) { pc . addTrack ( track , clonedStream ) ; } ) ; } } ; RTCPeerConnection . prototype . removeTrack = function ( sender ) { if ( this . _isClosed ) { throw makeError ( 'InvalidStateError' , 'Attempted to call removeTrack on a closed peerconnection.' ) ; }
if ( ! ( sender instanceof window . RTCRtpSender ) ) { throw new TypeError ( 'Argument 1 of RTCPeerConnection.removeTrack ' + 'does not implement interface RTCRtpSender.' ) ; }
var transceiver = this . transceivers . find ( function ( t ) { return t . rtpSender === sender ; } ) ; if ( ! transceiver ) { throw makeError ( 'InvalidAccessError' , 'Sender was not created by this connection.' ) ; }
var stream = transceiver . stream ; transceiver . rtpSender . stop ( ) ; transceiver . rtpSender = null ; transceiver . track = null ; transceiver . stream = null ; var localStreams = this . transceivers . map ( function ( t ) { return t . stream ; } ) ; if ( localStreams . indexOf ( stream ) === - 1 && this . localStreams . indexOf ( stream ) > - 1 ) { this . localStreams . splice ( this . localStreams . indexOf ( stream ) , 1 ) ; }
this . _maybeFireNegotiationNeeded ( ) ; } ; RTCPeerConnection . prototype . removeStream = function ( stream ) { var pc = this ; stream . getTracks ( ) . forEach ( function ( track ) { var sender = pc . getSenders ( ) . find ( function ( s ) { return s . track === track ; } ) ; if ( sender ) { pc . removeTrack ( sender ) ; } } ) ; } ; RTCPeerConnection . prototype . getSenders = function ( ) { return this . transceivers . filter ( function ( transceiver ) { return ! ! transceiver . rtpSender ; } ) . map ( function ( transceiver ) { return transceiver . rtpSender ; } ) ; } ; RTCPeerConnection . prototype . getReceivers = function ( ) { return this . transceivers . filter ( function ( transceiver ) { return ! ! transceiver . rtpReceiver ; } ) . map ( function ( transceiver ) { return transceiver . rtpReceiver ; } ) ; } ; RTCPeerConnection . prototype . _createIceGatherer = function ( sdpMLineIndex , usingBundle ) { var pc = this ; if ( usingBundle && sdpMLineIndex > 0 ) { return this . transceivers [ 0 ] . iceGatherer ; } else if ( this . _iceGatherers . length ) { return this . _iceGatherers . shift ( ) ; }
var iceGatherer = new window . RTCIceGatherer ( { iceServers : this . _config . iceServers , gatherPolicy : this . _config . iceTransportPolicy } ) ; Object . defineProperty ( iceGatherer , 'state' , { value : 'new' , writable : true } ) ; this . transceivers [ sdpMLineIndex ] . bufferedCandidateEvents = [ ] ; this . transceivers [ sdpMLineIndex ] . bufferCandidates = function ( event ) { var end = ! event . candidate || Object . keys ( event . candidate ) . length === 0 ; iceGatherer . state = end ? 'completed' : 'gathering' ; if ( pc . transceivers [ sdpMLineIndex ] . bufferedCandidateEvents !== null ) { pc . transceivers [ sdpMLineIndex ] . bufferedCandidateEvents . push ( event ) ; } } ; iceGatherer . addEventListener ( 'localcandidate' , this . transceivers [ sdpMLineIndex ] . bufferCandidates ) ; return iceGatherer ; } ; RTCPeerConnection . prototype . _gather = function ( mid , sdpMLineIndex ) { var pc = this ; var iceGatherer = this . transceivers [ sdpMLineIndex ] . iceGatherer ; if ( iceGatherer . onlocalcandidate ) { return ; }
var bufferedCandidateEvents = this . transceivers [ sdpMLineIndex ] . bufferedCandidateEvents ; this . transceivers [ sdpMLineIndex ] . bufferedCandidateEvents = null ; iceGatherer . removeEventListener ( 'localcandidate' , this . transceivers [ sdpMLineIndex ] . bufferCandidates ) ; iceGatherer . onlocalcandidate = function ( evt ) { if ( pc . usingBundle && sdpMLineIndex > 0 ) { return ; }
var event = new Event ( 'icecandidate' ) ; event . candidate = { sdpMid : mid , sdpMLineIndex : sdpMLineIndex } ; var cand = evt . candidate ; var end = ! cand || Object . keys ( cand ) . length === 0 ; if ( end ) { if ( iceGatherer . state === 'new' || iceGatherer . state === 'gathering' ) { iceGatherer . state = 'completed' ; } } else { if ( iceGatherer . state === 'new' ) { iceGatherer . state = 'gathering' ; }
cand . component = 1 ; cand . ufrag = iceGatherer . getLocalParameters ( ) . usernameFragment ; var serializedCandidate = SDPUtils . writeCandidate ( cand ) ; event . candidate = Object . assign ( event . candidate , SDPUtils . parseCandidate ( serializedCandidate ) ) ; event . candidate . candidate = serializedCandidate ; event . candidate . toJSON = function ( ) { return { candidate : event . candidate . candidate , sdpMid : event . candidate . sdpMid , sdpMLineIndex : event . candidate . sdpMLineIndex , usernameFragment : event . candidate . usernameFragment } ; } ; }
var sections = SDPUtils . getMediaSections ( pc . _localDescription . sdp ) ; if ( ! end ) { sections [ event . candidate . sdpMLineIndex ] += 'a=' + event . candidate . candidate + '\r\n' ; } else { sections [ event . candidate . sdpMLineIndex ] += 'a=end-of-candidates\r\n' ; }
pc . _localDescription . sdp = SDPUtils . getDescription ( pc . _localDescription . sdp ) +
sections . join ( '' ) ; var complete = pc . transceivers . every ( function ( transceiver ) { return transceiver . iceGatherer && transceiver . iceGatherer . state === 'completed' ; } ) ; if ( pc . iceGatheringState !== 'gathering' ) { pc . iceGatheringState = 'gathering' ; pc . _emitGatheringStateChange ( ) ; }
if ( ! end ) { pc . _dispatchEvent ( 'icecandidate' , event ) ; }
if ( complete ) { pc . _dispatchEvent ( 'icecandidate' , new Event ( 'icecandidate' ) ) ; pc . iceGatheringState = 'complete' ; pc . _emitGatheringStateChange ( ) ; } } ; window . setTimeout ( function ( ) { bufferedCandidateEvents . forEach ( function ( e ) { iceGatherer . onlocalcandidate ( e ) ; } ) ; } , 0 ) ; } ; RTCPeerConnection . prototype . _createIceAndDtlsTransports = function ( ) { var pc = this ; var iceTransport = new window . RTCIceTransport ( null ) ; iceTransport . onicestatechange = function ( ) { pc . _updateIceConnectionState ( ) ; pc . _updateConnectionState ( ) ; } ; var dtlsTransport = new window . RTCDtlsTransport ( iceTransport ) ; dtlsTransport . ondtlsstatechange = function ( ) { pc . _updateConnectionState ( ) ; } ; dtlsTransport . onerror = function ( ) { Object . defineProperty ( dtlsTransport , 'state' , { value : 'failed' , writable : true } ) ; pc . _updateConnectionState ( ) ; } ; return { iceTransport : iceTransport , dtlsTransport : dtlsTransport } ; } ; RTCPeerConnection . prototype . _disposeIceAndDtlsTransports = function ( sdpMLineIndex ) { var iceGatherer = this . transceivers [ sdpMLineIndex ] . iceGatherer ; if ( iceGatherer ) { delete iceGatherer . onlocalcandidate ; delete this . transceivers [ sdpMLineIndex ] . iceGatherer ; }
var iceTransport = this . transceivers [ sdpMLineIndex ] . iceTransport ; if ( iceTransport ) { delete iceTransport . onicestatechange ; delete this . transceivers [ sdpMLineIndex ] . iceTransport ; }
var dtlsTransport = this . transceivers [ sdpMLineIndex ] . dtlsTransport ; if ( dtlsTransport ) { delete dtlsTransport . ondtlsstatechange ; delete dtlsTransport . onerror ; delete this . transceivers [ sdpMLineIndex ] . dtlsTransport ; } } ; RTCPeerConnection . prototype . _transceive = function ( transceiver , send , recv ) { var params = getCommonCapabilities ( transceiver . localCapabilities , transceiver . remoteCapabilities ) ; if ( send && transceiver . rtpSender ) { params . encodings = transceiver . sendEncodingParameters ; params . rtcp = { cname : SDPUtils . localCName , compound : transceiver . rtcpParameters . compound } ; if ( transceiver . recvEncodingParameters . length ) { params . rtcp . ssrc = transceiver . recvEncodingParameters [ 0 ] . ssrc ; }
transceiver . rtpSender . send ( params ) ; }
if ( recv && transceiver . rtpReceiver && params . codecs . length > 0 ) { if ( transceiver . kind === 'video' && transceiver . recvEncodingParameters && edgeVersion < 15019 ) { transceiver . recvEncodingParameters . forEach ( function ( p ) { delete p . rtx ; } ) ; }
if ( transceiver . recvEncodingParameters . length ) { params . encodings = transceiver . recvEncodingParameters ; } else { params . encodings = [ { } ] ; }
params . rtcp = { compound : transceiver . rtcpParameters . compound } ; if ( transceiver . rtcpParameters . cname ) { params . rtcp . cname = transceiver . rtcpParameters . cname ; }
if ( transceiver . sendEncodingParameters . length ) { params . rtcp . ssrc = transceiver . sendEncodingParameters [ 0 ] . ssrc ; }
transceiver . rtpReceiver . receive ( params ) ; } } ; RTCPeerConnection . prototype . setLocalDescription = function ( description ) { var pc = this ; if ( [ 'offer' , 'answer' ] . indexOf ( description . type ) === - 1 ) { return Promise . reject ( makeError ( 'TypeError' , 'Unsupported type "' + description . type + '"' ) ) ; }
if ( ! isActionAllowedInSignalingState ( 'setLocalDescription' , description . type , pc . signalingState ) || pc . _isClosed ) { return Promise . reject ( makeError ( 'InvalidStateError' , 'Can not set local ' + description . type + ' in state ' + pc . signalingState ) ) ; }
var sections ; var sessionpart ; if ( description . type === 'offer' ) { sections = SDPUtils . splitSections ( description . sdp ) ; sessionpart = sections . shift ( ) ; sections . forEach ( function ( mediaSection , sdpMLineIndex ) { var caps = SDPUtils . parseRtpParameters ( mediaSection ) ; pc . transceivers [ sdpMLineIndex ] . localCapabilities = caps ; } ) ; pc . transceivers . forEach ( function ( transceiver , sdpMLineIndex ) { pc . _gather ( transceiver . mid , sdpMLineIndex ) ; } ) ; } else if ( description . type === 'answer' ) { sections = SDPUtils . splitSections ( pc . _remoteDescription . sdp ) ; sessionpart = sections . shift ( ) ; var isIceLite = SDPUtils . matchPrefix ( sessionpart , 'a=ice-lite' ) . length > 0 ; sections . forEach ( function ( mediaSection , sdpMLineIndex ) { var transceiver = pc . transceivers [ sdpMLineIndex ] ; var iceGatherer = transceiver . iceGatherer ; var iceTransport = transceiver . iceTransport ; var dtlsTransport = transceiver . dtlsTransport ; var localCapabilities = transceiver . localCapabilities ; var remoteCapabilities = transceiver . remoteCapabilities ; var rejected = SDPUtils . isRejected ( mediaSection ) && SDPUtils . matchPrefix ( mediaSection , 'a=bundle-only' ) . length === 0 ; if ( ! rejected && ! transceiver . rejected ) { var remoteIceParameters = SDPUtils . getIceParameters ( mediaSection , sessionpart ) ; var remoteDtlsParameters = SDPUtils . getDtlsParameters ( mediaSection , sessionpart ) ; if ( isIceLite ) { remoteDtlsParameters . role = 'server' ; }
if ( ! pc . usingBundle || sdpMLineIndex === 0 ) { pc . _gather ( transceiver . mid , sdpMLineIndex ) ; if ( iceTransport . state === 'new' ) { iceTransport . start ( iceGatherer , remoteIceParameters , isIceLite ? 'controlling' : 'controlled' ) ; }
if ( dtlsTransport . state === 'new' ) { dtlsTransport . start ( remoteDtlsParameters ) ; } }
var params = getCommonCapabilities ( localCapabilities , remoteCapabilities ) ; pc . _transceive ( transceiver , params . codecs . length > 0 , false ) ; } } ) ; }
pc . _localDescription = { type : description . type , sdp : description . sdp } ; if ( description . type === 'offer' ) { pc . _updateSignalingState ( 'have-local-offer' ) ; } else { pc . _updateSignalingState ( 'stable' ) ; }
return Promise . resolve ( ) ; } ; RTCPeerConnection . prototype . setRemoteDescription = function ( description ) { var pc = this ; if ( [ 'offer' , 'answer' ] . indexOf ( description . type ) === - 1 ) { return Promise . reject ( makeError ( 'TypeError' , 'Unsupported type "' + description . type + '"' ) ) ; }
if ( ! isActionAllowedInSignalingState ( 'setRemoteDescription' , description . type , pc . signalingState ) || pc . _isClosed ) { return Promise . reject ( makeError ( 'InvalidStateError' , 'Can not set remote ' + description . type + ' in state ' + pc . signalingState ) ) ; }
var streams = { } ; pc . remoteStreams . forEach ( function ( stream ) { streams [ stream . id ] = stream ; } ) ; var receiverList = [ ] ; var sections = SDPUtils . splitSections ( description . sdp ) ; var sessionpart = sections . shift ( ) ; var isIceLite = SDPUtils . matchPrefix ( sessionpart , 'a=ice-lite' ) . length > 0 ; var usingBundle = SDPUtils . matchPrefix ( sessionpart , 'a=group:BUNDLE ' ) . length > 0 ; pc . usingBundle = usingBundle ; var iceOptions = SDPUtils . matchPrefix ( sessionpart , 'a=ice-options:' ) [ 0 ] ; if ( iceOptions ) { pc . canTrickleIceCandidates = iceOptions . substr ( 14 ) . split ( ' ' ) . indexOf ( 'trickle' ) >= 0 ; } else { pc . canTrickleIceCandidates = false ; }
sections . forEach ( function ( mediaSection , sdpMLineIndex ) { var lines = SDPUtils . splitLines ( mediaSection ) ; var kind = SDPUtils . getKind ( mediaSection ) ; var rejected = SDPUtils . isRejected ( mediaSection ) && SDPUtils . matchPrefix ( mediaSection , 'a=bundle-only' ) . length === 0 ; var protocol = lines [ 0 ] . substr ( 2 ) . split ( ' ' ) [ 2 ] ; var direction = SDPUtils . getDirection ( mediaSection , sessionpart ) ; var remoteMsid = SDPUtils . parseMsid ( mediaSection ) ; var mid = SDPUtils . getMid ( mediaSection ) || SDPUtils . generateIdentifier ( ) ; if ( rejected || ( kind === 'application' && ( protocol === 'DTLS/SCTP' || protocol === 'UDP/DTLS/SCTP' ) ) ) { pc . transceivers [ sdpMLineIndex ] = { mid : mid , kind : kind , protocol : protocol , rejected : true } ; return ; }
if ( ! rejected && pc . transceivers [ sdpMLineIndex ] && pc . transceivers [ sdpMLineIndex ] . rejected ) { pc . transceivers [ sdpMLineIndex ] = pc . _createTransceiver ( kind , true ) ; }
var transceiver ; var iceGatherer ; var iceTransport ; var dtlsTransport ; var rtpReceiver ; var sendEncodingParameters ; var recvEncodingParameters ; var localCapabilities ; var track ; var remoteCapabilities = SDPUtils . parseRtpParameters ( mediaSection ) ; var remoteIceParameters ; var remoteDtlsParameters ; if ( ! rejected ) { remoteIceParameters = SDPUtils . getIceParameters ( mediaSection , sessionpart ) ; remoteDtlsParameters = SDPUtils . getDtlsParameters ( mediaSection , sessionpart ) ; remoteDtlsParameters . role = 'client' ; }
recvEncodingParameters = SDPUtils . parseRtpEncodingParameters ( mediaSection ) ; var rtcpParameters = SDPUtils . parseRtcpParameters ( mediaSection ) ; var isComplete = SDPUtils . matchPrefix ( mediaSection , 'a=end-of-candidates' , sessionpart ) . length > 0 ; var cands = SDPUtils . matchPrefix ( mediaSection , 'a=candidate:' ) . map ( function ( cand ) { return SDPUtils . parseCandidate ( cand ) ; } ) . filter ( function ( cand ) { return cand . component === 1 ; } ) ; if ( ( description . type === 'offer' || description . type === 'answer' ) && ! rejected && usingBundle && sdpMLineIndex > 0 && pc . transceivers [ sdpMLineIndex ] ) { pc . _disposeIceAndDtlsTransports ( sdpMLineIndex ) ; pc . transceivers [ sdpMLineIndex ] . iceGatherer = pc . transceivers [ 0 ] . iceGatherer ; pc . transceivers [ sdpMLineIndex ] . iceTransport = pc . transceivers [ 0 ] . iceTransport ; pc . transceivers [ sdpMLineIndex ] . dtlsTransport = pc . transceivers [ 0 ] . dtlsTransport ; if ( pc . transceivers [ sdpMLineIndex ] . rtpSender ) { pc . transceivers [ sdpMLineIndex ] . rtpSender . setTransport ( pc . transceivers [ 0 ] . dtlsTransport ) ; }
if ( pc . transceivers [ sdpMLineIndex ] . rtpReceiver ) { pc . transceivers [ sdpMLineIndex ] . rtpReceiver . setTransport ( pc . transceivers [ 0 ] . dtlsTransport ) ; } }
if ( description . type === 'offer' && ! rejected ) { transceiver = pc . transceivers [ sdpMLineIndex ] || pc . _createTransceiver ( kind ) ; transceiver . mid = mid ; if ( ! transceiver . iceGatherer ) { transceiver . iceGatherer = pc . _createIceGatherer ( sdpMLineIndex , usingBundle ) ; }
if ( cands . length && transceiver . iceTransport . state === 'new' ) { if ( isComplete && ( ! usingBundle || sdpMLineIndex === 0 ) ) { transceiver . iceTransport . setRemoteCandidates ( cands ) ; } else { cands . forEach ( function ( candidate ) { maybeAddCandidate ( transceiver . iceTransport , candidate ) ; } ) ; } }
localCapabilities = window . RTCRtpReceiver . getCapabilities ( kind ) ; if ( edgeVersion < 15019 ) { localCapabilities . codecs = localCapabilities . codecs . filter ( function ( codec ) { return codec . name !== 'rtx' ; } ) ; }
sendEncodingParameters = transceiver . sendEncodingParameters || [ { ssrc : ( 2 * sdpMLineIndex + 2 ) * 1001 } ] ; var isNewTrack = false ; if ( direction === 'sendrecv' || direction === 'sendonly' ) { isNewTrack = ! transceiver . rtpReceiver ; rtpReceiver = transceiver . rtpReceiver || new window . RTCRtpReceiver ( transceiver . dtlsTransport , kind ) ; if ( isNewTrack ) { var stream ; track = rtpReceiver . track ; if ( remoteMsid && remoteMsid . stream === '-' ) { } else if ( remoteMsid ) { if ( ! streams [ remoteMsid . stream ] ) { streams [ remoteMsid . stream ] = new window . MediaStream ( ) ; Object . defineProperty ( streams [ remoteMsid . stream ] , 'id' , { get : function ( ) { return remoteMsid . stream ; } } ) ; }
Object . defineProperty ( track , 'id' , { get : function ( ) { return remoteMsid . track ; } } ) ; stream = streams [ remoteMsid . stream ] ; } else { if ( ! streams . default ) { streams . default = new window . MediaStream ( ) ; }
stream = streams . default ; }
if ( stream ) { addTrackToStreamAndFireEvent ( track , stream ) ; transceiver . associatedRemoteMediaStreams . push ( stream ) ; }
receiverList . push ( [ track , rtpReceiver , stream ] ) ; } } else if ( transceiver . rtpReceiver && transceiver . rtpReceiver . track ) { transceiver . associatedRemoteMediaStreams . forEach ( function ( s ) { var nativeTrack = s . getTracks ( ) . find ( function ( t ) { return t . id === transceiver . rtpReceiver . track . id ; } ) ; if ( nativeTrack ) { removeTrackFromStreamAndFireEvent ( nativeTrack , s ) ; } } ) ; transceiver . associatedRemoteMediaStreams = [ ] ; }
transceiver . localCapabilities = localCapabilities ; transceiver . remoteCapabilities = remoteCapabilities ; transceiver . rtpReceiver = rtpReceiver ; transceiver . rtcpParameters = rtcpParameters ; transceiver . sendEncodingParameters = sendEncodingParameters ; transceiver . recvEncodingParameters = recvEncodingParameters ; pc . _transceive ( pc . transceivers [ sdpMLineIndex ] , false , isNewTrack ) ; } else if ( description . type === 'answer' && ! rejected ) { transceiver = pc . transceivers [ sdpMLineIndex ] ; iceGatherer = transceiver . iceGatherer ; iceTransport = transceiver . iceTransport ; dtlsTransport = transceiver . dtlsTransport ; rtpReceiver = transceiver . rtpReceiver ; sendEncodingParameters = transceiver . sendEncodingParameters ; localCapabilities = transceiver . localCapabilities ; pc . transceivers [ sdpMLineIndex ] . recvEncodingParameters = recvEncodingParameters ; pc . transceivers [ sdpMLineIndex ] . remoteCapabilities = remoteCapabilities ; pc . transceivers [ sdpMLineIndex ] . rtcpParameters = rtcpParameters ; if ( cands . length && iceTransport . state === 'new' ) { if ( ( isIceLite || isComplete ) && ( ! usingBundle || sdpMLineIndex === 0 ) ) { iceTransport . setRemoteCandidates ( cands ) ; } else { cands . forEach ( function ( candidate ) { maybeAddCandidate ( transceiver . iceTransport , candidate ) ; } ) ; } }
if ( ! usingBundle || sdpMLineIndex === 0 ) { if ( iceTransport . state === 'new' ) { iceTransport . start ( iceGatherer , remoteIceParameters , 'controlling' ) ; }
if ( dtlsTransport . state === 'new' ) { dtlsTransport . start ( remoteDtlsParameters ) ; } }
var commonCapabilities = getCommonCapabilities ( transceiver . localCapabilities , transceiver . remoteCapabilities ) ; var hasRtx = commonCapabilities . codecs . filter ( function ( c ) { return c . name . toLowerCase ( ) === 'rtx' ; } ) . length ; if ( ! hasRtx && transceiver . sendEncodingParameters [ 0 ] . rtx ) { delete transceiver . sendEncodingParameters [ 0 ] . rtx ; }
pc . _transceive ( transceiver , direction === 'sendrecv' || direction === 'recvonly' , direction === 'sendrecv' || direction === 'sendonly' ) ; if ( rtpReceiver && ( direction === 'sendrecv' || direction === 'sendonly' ) ) { track = rtpReceiver . track ; if ( remoteMsid ) { if ( ! streams [ remoteMsid . stream ] ) { streams [ remoteMsid . stream ] = new window . MediaStream ( ) ; }
addTrackToStreamAndFireEvent ( track , streams [ remoteMsid . stream ] ) ; receiverList . push ( [ track , rtpReceiver , streams [ remoteMsid . stream ] ] ) ; } else { if ( ! streams . default ) { streams . default = new window . MediaStream ( ) ; }
addTrackToStreamAndFireEvent ( track , streams . default ) ; receiverList . push ( [ track , rtpReceiver , streams . default ] ) ; } } else { delete transceiver . rtpReceiver ; } } } ) ; if ( pc . _dtlsRole === undefined ) { pc . _dtlsRole = description . type === 'offer' ? 'active' : 'passive' ; }
pc . _remoteDescription = { type : description . type , sdp : description . sdp } ; if ( description . type === 'offer' ) { pc . _updateSignalingState ( 'have-remote-offer' ) ; } else { pc . _updateSignalingState ( 'stable' ) ; }
Object . keys ( streams ) . forEach ( function ( sid ) { var stream = streams [ sid ] ; if ( stream . getTracks ( ) . length ) { if ( pc . remoteStreams . indexOf ( stream ) === - 1 ) { pc . remoteStreams . push ( stream ) ; var event = new Event ( 'addstream' ) ; event . stream = stream ; window . setTimeout ( function ( ) { pc . _dispatchEvent ( 'addstream' , event ) ; } ) ; }
receiverList . forEach ( function ( item ) { var track = item [ 0 ] ; var receiver = item [ 1 ] ; if ( stream . id !== item [ 2 ] . id ) { return ; }
fireAddTrack ( pc , track , receiver , [ stream ] ) ; } ) ; } } ) ; receiverList . forEach ( function ( item ) { if ( item [ 2 ] ) { return ; }
fireAddTrack ( pc , item [ 0 ] , item [ 1 ] , [ ] ) ; } ) ; window . setTimeout ( function ( ) { if ( ! ( pc && pc . transceivers ) ) { return ; }
pc . transceivers . forEach ( function ( transceiver ) { if ( transceiver . iceTransport && transceiver . iceTransport . state === 'new' && transceiver . iceTransport . getRemoteCandidates ( ) . length > 0 ) { console . warn ( 'Timeout for addRemoteCandidate. Consider sending ' + 'an end-of-candidates notification' ) ; transceiver . iceTransport . addRemoteCandidate ( { } ) ; } } ) ; } , 4000 ) ; return Promise . resolve ( ) ; } ; RTCPeerConnection . prototype . close = function ( ) { this . transceivers . forEach ( function ( transceiver ) { if ( transceiver . iceTransport ) { transceiver . iceTransport . stop ( ) ; }
if ( transceiver . dtlsTransport ) { transceiver . dtlsTransport . stop ( ) ; }
if ( transceiver . rtpSender ) { transceiver . rtpSender . stop ( ) ; }
if ( transceiver . rtpReceiver ) { transceiver . rtpReceiver . stop ( ) ; } } ) ; this . _isClosed = true ; this . _updateSignalingState ( 'closed' ) ; } ; RTCPeerConnection . prototype . _updateSignalingState = function ( newState ) { this . signalingState = newState ; var event = new Event ( 'signalingstatechange' ) ; this . _dispatchEvent ( 'signalingstatechange' , event ) ; } ; RTCPeerConnection . prototype . _maybeFireNegotiationNeeded = function ( ) { var pc = this ; if ( this . signalingState !== 'stable' || this . needNegotiation === true ) { return ; }
this . needNegotiation = true ; window . setTimeout ( function ( ) { if ( pc . needNegotiation ) { pc . needNegotiation = false ; var event = new Event ( 'negotiationneeded' ) ; pc . _dispatchEvent ( 'negotiationneeded' , event ) ; } } , 0 ) ; } ; RTCPeerConnection . prototype . _updateIceConnectionState = function ( ) { var newState ; var states = { 'new' : 0 , closed : 0 , checking : 0 , connected : 0 , completed : 0 , disconnected : 0 , failed : 0 } ; this . transceivers . forEach ( function ( transceiver ) { if ( transceiver . iceTransport && ! transceiver . rejected ) { states [ transceiver . iceTransport . state ] ++ ; } } ) ; newState = 'new' ; if ( states . failed > 0 ) { newState = 'failed' ; } else if ( states . checking > 0 ) { newState = 'checking' ; } else if ( states . disconnected > 0 ) { newState = 'disconnected' ; } else if ( states . new > 0 ) { newState = 'new' ; } else if ( states . connected > 0 ) { newState = 'connected' ; } else if ( states . completed > 0 ) { newState = 'completed' ; }
if ( newState !== this . iceConnectionState ) { this . iceConnectionState = newState ; var event = new Event ( 'iceconnectionstatechange' ) ; this . _dispatchEvent ( 'iceconnectionstatechange' , event ) ; } } ; RTCPeerConnection . prototype . _updateConnectionState = function ( ) { var newState ; var states = { 'new' : 0 , closed : 0 , connecting : 0 , connected : 0 , completed : 0 , disconnected : 0 , failed : 0 } ; this . transceivers . forEach ( function ( transceiver ) { if ( transceiver . iceTransport && transceiver . dtlsTransport && ! transceiver . rejected ) { states [ transceiver . iceTransport . state ] ++ ; states [ transceiver . dtlsTransport . state ] ++ ; } } ) ; states . connected += states . completed ; newState = 'new' ; if ( states . failed > 0 ) { newState = 'failed' ; } else if ( states . connecting > 0 ) { newState = 'connecting' ; } else if ( states . disconnected > 0 ) { newState = 'disconnected' ; } else if ( states . new > 0 ) { newState = 'new' ; } else if ( states . connected > 0 ) { newState = 'connected' ; }
if ( newState !== this . connectionState ) { this . connectionState = newState ; var event = new Event ( 'connectionstatechange' ) ; this . _dispatchEvent ( 'connectionstatechange' , event ) ; } } ; RTCPeerConnection . prototype . createOffer = function ( ) { var pc = this ; if ( pc . _isClosed ) { return Promise . reject ( makeError ( 'InvalidStateError' , 'Can not call createOffer after close' ) ) ; }
var numAudioTracks = pc . transceivers . filter ( function ( t ) { return t . kind === 'audio' ; } ) . length ; var numVideoTracks = pc . transceivers . filter ( function ( t ) { return t . kind === 'video' ; } ) . length ; var offerOptions = arguments [ 0 ] ; if ( offerOptions ) { if ( offerOptions . mandatory || offerOptions . optional ) { throw new TypeError ( 'Legacy mandatory/optional constraints not supported.' ) ; }
if ( offerOptions . offerToReceiveAudio !== undefined ) { if ( offerOptions . offerToReceiveAudio === true ) { numAudioTracks = 1 ; } else if ( offerOptions . offerToReceiveAudio === false ) { numAudioTracks = 0 ; } else { numAudioTracks = offerOptions . offerToReceiveAudio ; } }
if ( offerOptions . offerToReceiveVideo !== undefined ) { if ( offerOptions . offerToReceiveVideo === true ) { numVideoTracks = 1 ; } else if ( offerOptions . offerToReceiveVideo === false ) { numVideoTracks = 0 ; } else { numVideoTracks = offerOptions . offerToReceiveVideo ; } } }
pc . transceivers . forEach ( function ( transceiver ) { if ( transceiver . kind === 'audio' ) { numAudioTracks -- ; if ( numAudioTracks < 0 ) { transceiver . wantReceive = false ; } } else if ( transceiver . kind === 'video' ) { numVideoTracks -- ; if ( numVideoTracks < 0 ) { transceiver . wantReceive = false ; } } } ) ; while ( numAudioTracks > 0 || numVideoTracks > 0 ) { if ( numAudioTracks > 0 ) { pc . _createTransceiver ( 'audio' ) ; numAudioTracks -- ; }
if ( numVideoTracks > 0 ) { pc . _createTransceiver ( 'video' ) ; numVideoTracks -- ; } }
var sdp = SDPUtils . writeSessionBoilerplate ( pc . _sdpSessionId , pc . _sdpSessionVersion ++ ) ; pc . transceivers . forEach ( function ( transceiver , sdpMLineIndex ) { var track = transceiver . track ; var kind = transceiver . kind ; var mid = transceiver . mid || SDPUtils . generateIdentifier ( ) ; transceiver . mid = mid ; if ( ! transceiver . iceGatherer ) { transceiver . iceGatherer = pc . _createIceGatherer ( sdpMLineIndex , pc . usingBundle ) ; }
var localCapabilities = window . RTCRtpSender . getCapabilities ( kind ) ; if ( edgeVersion < 15019 ) { localCapabilities . codecs = localCapabilities . codecs . filter ( function ( codec ) { return codec . name !== 'rtx' ; } ) ; }
localCapabilities . codecs . forEach ( function ( codec ) { if ( codec . name === 'H264' && codec . parameters [ 'level-asymmetry-allowed' ] === undefined ) { codec . parameters [ 'level-asymmetry-allowed' ] = '1' ; }
if ( transceiver . remoteCapabilities && transceiver . remoteCapabilities . codecs ) { transceiver . remoteCapabilities . codecs . forEach ( function ( remoteCodec ) { if ( codec . name . toLowerCase ( ) === remoteCodec . name . toLowerCase ( ) && codec . clockRate === remoteCodec . clockRate ) { codec . preferredPayloadType = remoteCodec . payloadType ; } } ) ; } } ) ; localCapabilities . headerExtensions . forEach ( function ( hdrExt ) { var remoteExtensions = transceiver . remoteCapabilities && transceiver . remoteCapabilities . headerExtensions || [ ] ; remoteExtensions . forEach ( function ( rHdrExt ) { if ( hdrExt . uri === rHdrExt . uri ) { hdrExt . id = rHdrExt . id ; } } ) ; } ) ; var sendEncodingParameters = transceiver . sendEncodingParameters || [ { ssrc : ( 2 * sdpMLineIndex + 1 ) * 1001 } ] ; if ( track ) { if ( edgeVersion >= 15019 && kind === 'video' && ! sendEncodingParameters [ 0 ] . rtx ) { sendEncodingParameters [ 0 ] . rtx = { ssrc : sendEncodingParameters [ 0 ] . ssrc + 1 } ; } }
if ( transceiver . wantReceive ) { transceiver . rtpReceiver = new window . RTCRtpReceiver ( transceiver . dtlsTransport , kind ) ; }
transceiver . localCapabilities = localCapabilities ; transceiver . sendEncodingParameters = sendEncodingParameters ; } ) ; if ( pc . _config . bundlePolicy !== 'max-compat' ) { sdp += 'a=group:BUNDLE ' + pc . transceivers . map ( function ( t ) { return t . mid ; } ) . join ( ' ' ) + '\r\n' ; }
sdp += 'a=ice-options:trickle\r\n' ; pc . transceivers . forEach ( function ( transceiver , sdpMLineIndex ) { sdp += writeMediaSection ( transceiver , transceiver . localCapabilities , 'offer' , transceiver . stream , pc . _dtlsRole ) ; sdp += 'a=rtcp-rsize\r\n' ; if ( transceiver . iceGatherer && pc . iceGatheringState !== 'new' && ( sdpMLineIndex === 0 || ! pc . usingBundle ) ) { transceiver . iceGatherer . getLocalCandidates ( ) . forEach ( function ( cand ) { cand . component = 1 ; sdp += 'a=' + SDPUtils . writeCandidate ( cand ) + '\r\n' ; } ) ; if ( transceiver . iceGatherer . state === 'completed' ) { sdp += 'a=end-of-candidates\r\n' ; } } } ) ; var desc = new window . RTCSessionDescription ( { type : 'offer' , sdp : sdp } ) ; return Promise . resolve ( desc ) ; } ; RTCPeerConnection . prototype . createAnswer = function ( ) { var pc = this ; if ( pc . _isClosed ) { return Promise . reject ( makeError ( 'InvalidStateError' , 'Can not call createAnswer after close' ) ) ; }
if ( ! ( pc . signalingState === 'have-remote-offer' || pc . signalingState === 'have-local-pranswer' ) ) { return Promise . reject ( makeError ( 'InvalidStateError' , 'Can not call createAnswer in signalingState ' + pc . signalingState ) ) ; }
var sdp = SDPUtils . writeSessionBoilerplate ( pc . _sdpSessionId , pc . _sdpSessionVersion ++ ) ; if ( pc . usingBundle ) { sdp += 'a=group:BUNDLE ' + pc . transceivers . map ( function ( t ) { return t . mid ; } ) . join ( ' ' ) + '\r\n' ; }
sdp += 'a=ice-options:trickle\r\n' ; var mediaSectionsInOffer = SDPUtils . getMediaSections ( pc . _remoteDescription . sdp ) . length ; pc . transceivers . forEach ( function ( transceiver , sdpMLineIndex ) { if ( sdpMLineIndex + 1 > mediaSectionsInOffer ) { return ; }
if ( transceiver . rejected ) { if ( transceiver . kind === 'application' ) { if ( transceiver . protocol === 'DTLS/SCTP' ) { sdp += 'm=application 0 DTLS/SCTP 5000\r\n' ; } else { sdp += 'm=application 0 ' + transceiver . protocol + ' webrtc-datachannel\r\n' ; } } else if ( transceiver . kind === 'audio' ) { sdp += 'm=audio 0 UDP/TLS/RTP/SAVPF 0\r\n' + 'a=rtpmap:0 PCMU/8000\r\n' ; } else if ( transceiver . kind === 'video' ) { sdp += 'm=video 0 UDP/TLS/RTP/SAVPF 120\r\n' + 'a=rtpmap:120 VP8/90000\r\n' ; }
sdp += 'c=IN IP4 0.0.0.0\r\n' + 'a=inactive\r\n' + 'a=mid:' + transceiver . mid + '\r\n' ; return ; }
if ( transceiver . stream ) { var localTrack ; if ( transceiver . kind === 'audio' ) { localTrack = transceiver . stream . getAudioTracks ( ) [ 0 ] ; } else if ( transceiver . kind === 'video' ) { localTrack = transceiver . stream . getVideoTracks ( ) [ 0 ] ; }
if ( localTrack ) { if ( edgeVersion >= 15019 && transceiver . kind === 'video' && ! transceiver . sendEncodingParameters [ 0 ] . rtx ) { transceiver . sendEncodingParameters [ 0 ] . rtx = { ssrc : transceiver . sendEncodingParameters [ 0 ] . ssrc + 1 } ; } } }
var commonCapabilities = getCommonCapabilities ( transceiver . localCapabilities , transceiver . remoteCapabilities ) ; var hasRtx = commonCapabilities . codecs . filter ( function ( c ) { return c . name . toLowerCase ( ) === 'rtx' ; } ) . length ; if ( ! hasRtx && transceiver . sendEncodingParameters [ 0 ] . rtx ) { delete transceiver . sendEncodingParameters [ 0 ] . rtx ; }
sdp += writeMediaSection ( transceiver , commonCapabilities , 'answer' , transceiver . stream , pc . _dtlsRole ) ; if ( transceiver . rtcpParameters && transceiver . rtcpParameters . reducedSize ) { sdp += 'a=rtcp-rsize\r\n' ; } } ) ; var desc = new window . RTCSessionDescription ( { type : 'answer' , sdp : sdp } ) ; return Promise . resolve ( desc ) ; } ; RTCPeerConnection . prototype . addIceCandidate = function ( candidate ) { var pc = this ; var sections ; if ( candidate && ! ( candidate . sdpMLineIndex !== undefined || candidate . sdpMid ) ) { return Promise . reject ( new TypeError ( 'sdpMLineIndex or sdpMid required' ) ) ; }
return new Promise ( function ( resolve , reject ) { if ( ! pc . _remoteDescription ) { return reject ( makeError ( 'InvalidStateError' , 'Can not add ICE candidate without a remote description' ) ) ; } else if ( ! candidate || candidate . candidate === '' ) { for ( var j = 0 ; j < pc . transceivers . length ; j ++ ) { if ( pc . transceivers [ j ] . rejected ) { continue ; }
pc . transceivers [ j ] . iceTransport . addRemoteCandidate ( { } ) ; sections = SDPUtils . getMediaSections ( pc . _remoteDescription . sdp ) ; sections [ j ] += 'a=end-of-candidates\r\n' ; pc . _remoteDescription . sdp = SDPUtils . getDescription ( pc . _remoteDescription . sdp ) +
sections . join ( '' ) ; if ( pc . usingBundle ) { break ; } } } else { var sdpMLineIndex = candidate . sdpMLineIndex ; if ( candidate . sdpMid ) { for ( var i = 0 ; i < pc . transceivers . length ; i ++ ) { if ( pc . transceivers [ i ] . mid === candidate . sdpMid ) { sdpMLineIndex = i ; break ; } } }
var transceiver = pc . transceivers [ sdpMLineIndex ] ; if ( transceiver ) { if ( transceiver . rejected ) { return resolve ( ) ; }
var cand = Object . keys ( candidate . candidate ) . length > 0 ? SDPUtils . parseCandidate ( candidate . candidate ) : { } ; if ( cand . protocol === 'tcp' && ( cand . port === 0 || cand . port === 9 ) ) { return resolve ( ) ; }
if ( cand . component && cand . component !== 1 ) { return resolve ( ) ; }
if ( sdpMLineIndex === 0 || ( sdpMLineIndex > 0 && transceiver . iceTransport !== pc . transceivers [ 0 ] . iceTransport ) ) { if ( ! maybeAddCandidate ( transceiver . iceTransport , cand ) ) { return reject ( makeError ( 'OperationError' , 'Can not add ICE candidate' ) ) ; } }
var candidateString = candidate . candidate . trim ( ) ; if ( candidateString . indexOf ( 'a=' ) === 0 ) { candidateString = candidateString . substr ( 2 ) ; }
sections = SDPUtils . getMediaSections ( pc . _remoteDescription . sdp ) ; sections [ sdpMLineIndex ] += 'a=' +
( cand . type ? candidateString : 'end-of-candidates' )
+ '\r\n' ; pc . _remoteDescription . sdp = SDPUtils . getDescription ( pc . _remoteDescription . sdp ) +
sections . join ( '' ) ; } else { return reject ( makeError ( 'OperationError' , 'Can not add ICE candidate' ) ) ; } }
resolve ( ) ; } ) ; } ; RTCPeerConnection . prototype . getStats = function ( selector ) { if ( selector && selector instanceof window . MediaStreamTrack ) { var senderOrReceiver = null ; this . transceivers . forEach ( function ( transceiver ) { if ( transceiver . rtpSender && transceiver . rtpSender . track === selector ) { senderOrReceiver = transceiver . rtpSender ; } else if ( transceiver . rtpReceiver && transceiver . rtpReceiver . track === selector ) { senderOrReceiver = transceiver . rtpReceiver ; } } ) ; if ( ! senderOrReceiver ) { throw makeError ( 'InvalidAccessError' , 'Invalid selector.' ) ; }
return senderOrReceiver . getStats ( ) ; }
var promises = [ ] ; this . transceivers . forEach ( function ( transceiver ) { [ 'rtpSender' , 'rtpReceiver' , 'iceGatherer' , 'iceTransport' , 'dtlsTransport' ] . forEach ( function ( method ) { if ( transceiver [ method ] ) { promises . push ( transceiver [ method ] . getStats ( ) ) ; } } ) ; } ) ; return Promise . all ( promises ) . then ( function ( allStats ) { var results = new Map ( ) ; allStats . forEach ( function ( stats ) { stats . forEach ( function ( stat ) { results . set ( stat . id , stat ) ; } ) ; } ) ; return results ; } ) ; } ; var ortcObjects = [ 'RTCRtpSender' , 'RTCRtpReceiver' , 'RTCIceGatherer' , 'RTCIceTransport' , 'RTCDtlsTransport' ] ; ortcObjects . forEach ( function ( ortcObjectName ) { var obj = window [ ortcObjectName ] ; if ( obj && obj . prototype && obj . prototype . getStats ) { var nativeGetstats = obj . prototype . getStats ; obj . prototype . getStats = function ( ) { return nativeGetstats . apply ( this ) . then ( function ( nativeStats ) { var mapStats = new Map ( ) ; Object . keys ( nativeStats ) . forEach ( function ( id ) { nativeStats [ id ] . type = fixStatsType ( nativeStats [ id ] ) ; mapStats . set ( id , nativeStats [ id ] ) ; } ) ; return mapStats ; } ) ; } ; } } ) ; var methods = [ 'createOffer' , 'createAnswer' ] ; methods . forEach ( function ( method ) { var nativeMethod = RTCPeerConnection . prototype [ method ] ; RTCPeerConnection . prototype [ method ] = function ( ) { var args = arguments ; if ( typeof args [ 0 ] === 'function' || typeof args [ 1 ] === 'function' ) { return nativeMethod . apply ( this , [ arguments [ 2 ] ] ) . then ( function ( description ) { if ( typeof args [ 0 ] === 'function' ) { args [ 0 ] . apply ( null , [ description ] ) ; } } , function ( error ) { if ( typeof args [ 1 ] === 'function' ) { args [ 1 ] . apply ( null , [ error ] ) ; } } ) ; }
return nativeMethod . apply ( this , arguments ) ; } ; } ) ; methods = [ 'setLocalDescription' , 'setRemoteDescription' , 'addIceCandidate' ] ; methods . forEach ( function ( method ) { var nativeMethod = RTCPeerConnection . prototype [ method ] ; RTCPeerConnection . prototype [ method ] = function ( ) { var args = arguments ; if ( typeof args [ 1 ] === 'function' || typeof args [ 2 ] === 'function' ) { return nativeMethod . apply ( this , arguments ) . then ( function ( ) { if ( typeof args [ 1 ] === 'function' ) { args [ 1 ] . apply ( null ) ; } } , function ( error ) { if ( typeof args [ 2 ] === 'function' ) { args [ 2 ] . apply ( null , [ error ] ) ; } } ) ; }
return nativeMethod . apply ( this , arguments ) ; } ; } ) ; [ 'getStats' ] . forEach ( function ( method ) { var nativeMethod = RTCPeerConnection . prototype [ method ] ; RTCPeerConnection . prototype [ method ] = function ( ) { var args = arguments ; if ( typeof args [ 1 ] === 'function' ) { return nativeMethod . apply ( this , arguments ) . then ( function ( ) { if ( typeof args [ 1 ] === 'function' ) { args [ 1 ] . apply ( null ) ; } } ) ; }
return nativeMethod . apply ( this , arguments ) ; } ; } ) ; return RTCPeerConnection ; } ; } , { "sdp" : 17 } ] , 17 : [ function ( require , module , exports ) { 'use strict' ; var SDPUtils = { } ; SDPUtils . generateIdentifier = function ( ) { return Math . random ( ) . toString ( 36 ) . substr ( 2 , 10 ) ; } ; SDPUtils . localCName = SDPUtils . generateIdentifier ( ) ; SDPUtils . splitLines = function ( blob ) { return blob . trim ( ) . split ( '\n' ) . map ( function ( line ) { return line . trim ( ) ; } ) ; } ; SDPUtils . splitSections = function ( blob ) { var parts = blob . split ( '\nm=' ) ; return parts . map ( function ( part , index ) { return ( index > 0 ? 'm=' + part : part ) . trim ( ) + '\r\n' ; } ) ; } ; SDPUtils . getDescription = function ( blob ) { var sections = SDPUtils . splitSections ( blob ) ; return sections && sections [ 0 ] ; } ; SDPUtils . getMediaSections = function ( blob ) { var sections = SDPUtils . splitSections ( blob ) ; sections . shift ( ) ; return sections ; } ; SDPUtils . matchPrefix = function ( blob , prefix ) { return SDPUtils . splitLines ( blob ) . filter ( function ( line ) { return line . indexOf ( prefix ) === 0 ; } ) ; } ; SDPUtils . parseCandidate = function ( line ) { var parts ; if ( line . indexOf ( 'a=candidate:' ) === 0 ) { parts = line . substring ( 12 ) . split ( ' ' ) ; } else { parts = line . substring ( 10 ) . split ( ' ' ) ; }
var candidate = { foundation : parts [ 0 ] , component : parseInt ( parts [ 1 ] , 10 ) , protocol : parts [ 2 ] . toLowerCase ( ) , priority : parseInt ( parts [ 3 ] , 10 ) , ip : parts [ 4 ] , address : parts [ 4 ] , port : parseInt ( parts [ 5 ] , 10 ) , type : parts [ 7 ] } ; for ( var i = 8 ; i < parts . length ; i += 2 ) { switch ( parts [ i ] ) { case 'raddr' : candidate . relatedAddress = parts [ i + 1 ] ; break ; case 'rport' : candidate . relatedPort = parseInt ( parts [ i + 1 ] , 10 ) ; break ; case 'tcptype' : candidate . tcpType = parts [ i + 1 ] ; break ; case 'ufrag' : candidate . ufrag = parts [ i + 1 ] ; candidate . usernameFragment = parts [ i + 1 ] ; break ; default : candidate [ parts [ i ] ] = parts [ i + 1 ] ; break ; } }
return candidate ; } ; SDPUtils . writeCandidate = function ( candidate ) { var sdp = [ ] ; sdp . push ( candidate . foundation ) ; sdp . push ( candidate . component ) ; sdp . push ( candidate . protocol . toUpperCase ( ) ) ; sdp . push ( candidate . priority ) ; sdp . push ( candidate . address || candidate . ip ) ; sdp . push ( candidate . port ) ; var type = candidate . type ; sdp . push ( 'typ' ) ; sdp . push ( type ) ; if ( type !== 'host' && candidate . relatedAddress && candidate . relatedPort ) { sdp . push ( 'raddr' ) ; sdp . push ( candidate . relatedAddress ) ; sdp . push ( 'rport' ) ; sdp . push ( candidate . relatedPort ) ; }
if ( candidate . tcpType && candidate . protocol . toLowerCase ( ) === 'tcp' ) { sdp . push ( 'tcptype' ) ; sdp . push ( candidate . tcpType ) ; }
if ( candidate . usernameFragment || candidate . ufrag ) { sdp . push ( 'ufrag' ) ; sdp . push ( candidate . usernameFragment || candidate . ufrag ) ; }
return 'candidate:' + sdp . join ( ' ' ) ; } ; SDPUtils . parseIceOptions = function ( line ) { return line . substr ( 14 ) . split ( ' ' ) ; } ; SDPUtils . parseRtpMap = function ( line ) { var parts = line . substr ( 9 ) . split ( ' ' ) ; var parsed = { payloadType : parseInt ( parts . shift ( ) , 10 ) } ; parts = parts [ 0 ] . split ( '/' ) ; parsed . name = parts [ 0 ] ; parsed . clockRate = parseInt ( parts [ 1 ] , 10 ) ; parsed . channels = parts . length === 3 ? parseInt ( parts [ 2 ] , 10 ) : 1 ; parsed . numChannels = parsed . channels ; return parsed ; } ; SDPUtils . writeRtpMap = function ( codec ) { var pt = codec . payloadType ; if ( codec . preferredPayloadType !== undefined ) { pt = codec . preferredPayloadType ; }
var channels = codec . channels || codec . numChannels || 1 ; return 'a=rtpmap:' + pt + ' ' + codec . name + '/' + codec . clockRate +
( channels !== 1 ? '/' + channels : '' ) + '\r\n' ; } ; SDPUtils . parseExtmap = function ( line ) { var parts = line . substr ( 9 ) . split ( ' ' ) ; return { id : parseInt ( parts [ 0 ] , 10 ) , direction : parts [ 0 ] . indexOf ( '/' ) > 0 ? parts [ 0 ] . split ( '/' ) [ 1 ] : 'sendrecv' , uri : parts [ 1 ] } ; } ; SDPUtils . writeExtmap = function ( headerExtension ) { return 'a=extmap:' + ( headerExtension . id || headerExtension . preferredId ) +
( headerExtension . direction && headerExtension . direction !== 'sendrecv' ? '/' + headerExtension . direction : '' ) + ' ' + headerExtension . uri + '\r\n' ; } ; SDPUtils . parseFmtp = function ( line ) { var parsed = { } ; var kv ; var parts = line . substr ( line . indexOf ( ' ' ) + 1 ) . split ( ';' ) ; for ( var j = 0 ; j < parts . length ; j ++ ) { kv = parts [ j ] . trim ( ) . split ( '=' ) ; parsed [ kv [ 0 ] . trim ( ) ] = kv [ 1 ] ; }
return parsed ; } ; SDPUtils . writeFmtp = function ( codec ) { var line = '' ; var pt = codec . payloadType ; if ( codec . preferredPayloadType !== undefined ) { pt = codec . preferredPayloadType ; }
if ( codec . parameters && Object . keys ( codec . parameters ) . length ) { var params = [ ] ; Object . keys ( codec . parameters ) . forEach ( function ( param ) { if ( codec . parameters [ param ] ) { params . push ( param + '=' + codec . parameters [ param ] ) ; } else { params . push ( param ) ; } } ) ; line += 'a=fmtp:' + pt + ' ' + params . join ( ';' ) + '\r\n' ; }
return line ; } ; SDPUtils . parseRtcpFb = function ( line ) { var parts = line . substr ( line . indexOf ( ' ' ) + 1 ) . split ( ' ' ) ; return { type : parts . shift ( ) , parameter : parts . join ( ' ' ) } ; } ; SDPUtils . writeRtcpFb = function ( codec ) { var lines = '' ; var pt = codec . payloadType ; if ( codec . preferredPayloadType !== undefined ) { pt = codec . preferredPayloadType ; }
if ( codec . rtcpFeedback && codec . rtcpFeedback . length ) { codec . rtcpFeedback . forEach ( function ( fb ) { lines += 'a=rtcp-fb:' + pt + ' ' + fb . type +
( fb . parameter && fb . parameter . length ? ' ' + fb . parameter : '' ) + '\r\n' ; } ) ; }
return lines ; } ; SDPUtils . parseSsrcMedia = function ( line ) { var sp = line . indexOf ( ' ' ) ; var parts = { ssrc : parseInt ( line . substr ( 7 , sp - 7 ) , 10 ) } ; var colon = line . indexOf ( ':' , sp ) ; if ( colon > - 1 ) { parts . attribute = line . substr ( sp + 1 , colon - sp - 1 ) ; parts . value = line . substr ( colon + 1 ) ; } else { parts . attribute = line . substr ( sp + 1 ) ; }
return parts ; } ; SDPUtils . parseSsrcGroup = function ( line ) { var parts = line . substr ( 13 ) . split ( ' ' ) ; return { semantics : parts . shift ( ) , ssrcs : parts . map ( function ( ssrc ) { return parseInt ( ssrc , 10 ) ; } ) } ; } ; SDPUtils . getMid = function ( mediaSection ) { var mid = SDPUtils . matchPrefix ( mediaSection , 'a=mid:' ) [ 0 ] ; if ( mid ) { return mid . substr ( 6 ) ; } } ; SDPUtils . parseFingerprint = function ( line ) { var parts = line . substr ( 14 ) . split ( ' ' ) ; return { algorithm : parts [ 0 ] . toLowerCase ( ) , value : parts [ 1 ] } ; } ; SDPUtils . getDtlsParameters = function ( mediaSection , sessionpart ) { var lines = SDPUtils . matchPrefix ( mediaSection + sessionpart , 'a=fingerprint:' ) ; return { role : 'auto' , fingerprints : lines . map ( SDPUtils . parseFingerprint ) } ; } ; SDPUtils . writeDtlsParameters = function ( params , setupType ) { var sdp = 'a=setup:' + setupType + '\r\n' ; params . fingerprints . forEach ( function ( fp ) { sdp += 'a=fingerprint:' + fp . algorithm + ' ' + fp . value + '\r\n' ; } ) ; return sdp ; } ; SDPUtils . getIceParameters = function ( mediaSection , sessionpart ) { var lines = SDPUtils . splitLines ( mediaSection ) ; lines = lines . concat ( SDPUtils . splitLines ( sessionpart ) ) ; var iceParameters = { usernameFragment : lines . filter ( function ( line ) { return line . indexOf ( 'a=ice-ufrag:' ) === 0 ; } ) [ 0 ] . substr ( 12 ) , password : lines . filter ( function ( line ) { return line . indexOf ( 'a=ice-pwd:' ) === 0 ; } ) [ 0 ] . substr ( 10 ) } ; return iceParameters ; } ; SDPUtils . writeIceParameters = function ( params ) { return 'a=ice-ufrag:' + params . usernameFragment + '\r\n' + 'a=ice-pwd:' + params . password + '\r\n' ; } ; SDPUtils . parseRtpParameters = function ( mediaSection ) { var description = { codecs : [ ] , headerExtensions : [ ] , fecMechanisms : [ ] , rtcp : [ ] } ; var lines = SDPUtils . splitLines ( mediaSection ) ; var mline = lines [ 0 ] . split ( ' ' ) ; for ( var i = 3 ; i < mline . length ; i ++ ) { var pt = mline [ i ] ; var rtpmapline = SDPUtils . matchPrefix ( mediaSection , 'a=rtpmap:' + pt + ' ' ) [ 0 ] ; if ( rtpmapline ) { var codec = SDPUtils . parseRtpMap ( rtpmapline ) ; var fmtps = SDPUtils . matchPrefix ( mediaSection , 'a=fmtp:' + pt + ' ' ) ; codec . parameters = fmtps . length ? SDPUtils . parseFmtp ( fmtps [ 0 ] ) : { } ; codec . rtcpFeedback = SDPUtils . matchPrefix ( mediaSection , 'a=rtcp-fb:' + pt + ' ' ) . map ( SDPUtils . parseRtcpFb ) ; description . codecs . push ( codec ) ; switch ( codec . name . toUpperCase ( ) ) { case 'RED' : case 'ULPFEC' : description . fecMechanisms . push ( codec . name . toUpperCase ( ) ) ; break ; default : break ; } } }
SDPUtils . matchPrefix ( mediaSection , 'a=extmap:' ) . forEach ( function ( line ) { description . headerExtensions . push ( SDPUtils . parseExtmap ( line ) ) ; } ) ; return description ; } ; SDPUtils . writeRtpDescription = function ( kind , caps ) { var sdp = '' ; sdp += 'm=' + kind + ' ' ; sdp += caps . codecs . length > 0 ? '9' : '0' ; sdp += ' UDP/TLS/RTP/SAVPF ' ; sdp += caps . codecs . map ( function ( codec ) { if ( codec . preferredPayloadType !== undefined ) { return codec . preferredPayloadType ; }
return codec . payloadType ; } ) . join ( ' ' ) + '\r\n' ; sdp += 'c=IN IP4 0.0.0.0\r\n' ; sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n' ; caps . codecs . forEach ( function ( codec ) { sdp += SDPUtils . writeRtpMap ( codec ) ; sdp += SDPUtils . writeFmtp ( codec ) ; sdp += SDPUtils . writeRtcpFb ( codec ) ; } ) ; var maxptime = 0 ; caps . codecs . forEach ( function ( codec ) { if ( codec . maxptime > maxptime ) { maxptime = codec . maxptime ; } } ) ; if ( maxptime > 0 ) { sdp += 'a=maxptime:' + maxptime + '\r\n' ; }
sdp += 'a=rtcp-mux\r\n' ; if ( caps . headerExtensions ) { caps . headerExtensions . forEach ( function ( extension ) { sdp += SDPUtils . writeExtmap ( extension ) ; } ) ; }
return sdp ; } ; SDPUtils . parseRtpEncodingParameters = function ( mediaSection ) { var encodingParameters = [ ] ; var description = SDPUtils . parseRtpParameters ( mediaSection ) ; var hasRed = description . fecMechanisms . indexOf ( 'RED' ) !== - 1 ; var hasUlpfec = description . fecMechanisms . indexOf ( 'ULPFEC' ) !== - 1 ; var ssrcs = SDPUtils . matchPrefix ( mediaSection , 'a=ssrc:' ) . map ( function ( line ) { return SDPUtils . parseSsrcMedia ( line ) ; } ) . filter ( function ( parts ) { return parts . attribute === 'cname' ; } ) ; var primarySsrc = ssrcs . length > 0 && ssrcs [ 0 ] . ssrc ; var secondarySsrc ; var flows = SDPUtils . matchPrefix ( mediaSection , 'a=ssrc-group:FID' ) . map ( function ( line ) { var parts = line . substr ( 17 ) . split ( ' ' ) ; return parts . map ( function ( part ) { return parseInt ( part , 10 ) ; } ) ; } ) ; if ( flows . length > 0 && flows [ 0 ] . length > 1 && flows [ 0 ] [ 0 ] === primarySsrc ) { secondarySsrc = flows [ 0 ] [ 1 ] ; }
description . codecs . forEach ( function ( codec ) { if ( codec . name . toUpperCase ( ) === 'RTX' && codec . parameters . apt ) { var encParam = { ssrc : primarySsrc , codecPayloadType : parseInt ( codec . parameters . apt , 10 ) } ; if ( primarySsrc && secondarySsrc ) { encParam . rtx = { ssrc : secondarySsrc } ; }
encodingParameters . push ( encParam ) ; if ( hasRed ) { encParam = JSON . parse ( JSON . stringify ( encParam ) ) ; encParam . fec = { ssrc : primarySsrc , mechanism : hasUlpfec ? 'red+ulpfec' : 'red' } ; encodingParameters . push ( encParam ) ; } } } ) ; if ( encodingParameters . length === 0 && primarySsrc ) { encodingParameters . push ( { ssrc : primarySsrc } ) ; }
var bandwidth = SDPUtils . matchPrefix ( mediaSection , 'b=' ) ; if ( bandwidth . length ) { if ( bandwidth [ 0 ] . indexOf ( 'b=TIAS:' ) === 0 ) { bandwidth = parseInt ( bandwidth [ 0 ] . substr ( 7 ) , 10 ) ; } else if ( bandwidth [ 0 ] . indexOf ( 'b=AS:' ) === 0 ) { bandwidth = parseInt ( bandwidth [ 0 ] . substr ( 5 ) , 10 ) * 1000 * 0.95
- ( 50 * 40 * 8 ) ; } else { bandwidth = undefined ; }
encodingParameters . forEach ( function ( params ) { params . maxBitrate = bandwidth ; } ) ; }
return encodingParameters ; } ; SDPUtils . parseRtcpParameters = function ( mediaSection ) { var rtcpParameters = { } ; var remoteSsrc = SDPUtils . matchPrefix ( mediaSection , 'a=ssrc:' ) . map ( function ( line ) { return SDPUtils . parseSsrcMedia ( line ) ; } ) . filter ( function ( obj ) { return obj . attribute === 'cname' ; } ) [ 0 ] ; if ( remoteSsrc ) { rtcpParameters . cname = remoteSsrc . value ; rtcpParameters . ssrc = remoteSsrc . ssrc ; }
var rsize = SDPUtils . matchPrefix ( mediaSection , 'a=rtcp-rsize' ) ; rtcpParameters . reducedSize = rsize . length > 0 ; rtcpParameters . compound = rsize . length === 0 ; var mux = SDPUtils . matchPrefix ( mediaSection , 'a=rtcp-mux' ) ; rtcpParameters . mux = mux . length > 0 ; return rtcpParameters ; } ; SDPUtils . parseMsid = function ( mediaSection ) { var parts ; var spec = SDPUtils . matchPrefix ( mediaSection , 'a=msid:' ) ; if ( spec . length === 1 ) { parts = spec [ 0 ] . substr ( 7 ) . split ( ' ' ) ; return { stream : parts [ 0 ] , track : parts [ 1 ] } ; }
var planB = SDPUtils . matchPrefix ( mediaSection , 'a=ssrc:' ) . map ( function ( line ) { return SDPUtils . parseSsrcMedia ( line ) ; } ) . filter ( function ( msidParts ) { return msidParts . attribute === 'msid' ; } ) ; if ( planB . length > 0 ) { parts = planB [ 0 ] . value . split ( ' ' ) ; return { stream : parts [ 0 ] , track : parts [ 1 ] } ; } } ; SDPUtils . generateSessionId = function ( ) { return Math . random ( ) . toString ( ) . substr ( 2 , 21 ) ; } ; SDPUtils . writeSessionBoilerplate = function ( sessId , sessVer , sessUser ) { var sessionId ; var version = sessVer !== undefined ? sessVer : 2 ; if ( sessId ) { sessionId = sessId ; } else { sessionId = SDPUtils . generateSessionId ( ) ; }
var user = sessUser || 'thisisadapterortc' ; return 'v=0\r\n' + 'o=' + user + ' ' + sessionId + ' ' + version + ' IN IP4 127.0.0.1\r\n' + 's=-\r\n' + 't=0 0\r\n' ; } ; SDPUtils . writeMediaSection = function ( transceiver , caps , type , stream ) { var sdp = SDPUtils . writeRtpDescription ( transceiver . kind , caps ) ; sdp += SDPUtils . writeIceParameters ( transceiver . iceGatherer . getLocalParameters ( ) ) ; sdp += SDPUtils . writeDtlsParameters ( transceiver . dtlsTransport . getLocalParameters ( ) , type === 'offer' ? 'actpass' : 'active' ) ; sdp += 'a=mid:' + transceiver . mid + '\r\n' ; if ( transceiver . direction ) { sdp += 'a=' + transceiver . direction + '\r\n' ; } else if ( transceiver . rtpSender && transceiver . rtpReceiver ) { sdp += 'a=sendrecv\r\n' ; } else if ( transceiver . rtpSender ) { sdp += 'a=sendonly\r\n' ; } else if ( transceiver . rtpReceiver ) { sdp += 'a=recvonly\r\n' ; } else { sdp += 'a=inactive\r\n' ; }
if ( transceiver . rtpSender ) { var msid = 'msid:' + stream . id + ' ' +
transceiver . rtpSender . track . id + '\r\n' ; sdp += 'a=' + msid ; sdp += 'a=ssrc:' + transceiver . sendEncodingParameters [ 0 ] . ssrc + ' ' + msid ; if ( transceiver . sendEncodingParameters [ 0 ] . rtx ) { sdp += 'a=ssrc:' + transceiver . sendEncodingParameters [ 0 ] . rtx . ssrc + ' ' + msid ; sdp += 'a=ssrc-group:FID ' +
transceiver . sendEncodingParameters [ 0 ] . ssrc + ' ' +
transceiver . sendEncodingParameters [ 0 ] . rtx . ssrc + '\r\n' ; } }
sdp += 'a=ssrc:' + transceiver . sendEncodingParameters [ 0 ] . ssrc + ' cname:' + SDPUtils . localCName + '\r\n' ; if ( transceiver . rtpSender && transceiver . sendEncodingParameters [ 0 ] . rtx ) { sdp += 'a=ssrc:' + transceiver . sendEncodingParameters [ 0 ] . rtx . ssrc + ' cname:' + SDPUtils . localCName + '\r\n' ; }
return sdp ; } ; SDPUtils . getDirection = function ( mediaSection , sessionpart ) { var lines = SDPUtils . splitLines ( mediaSection ) ; for ( var i = 0 ; i < lines . length ; i ++ ) { switch ( lines [ i ] ) { case 'a=sendrecv' : case 'a=sendonly' : case 'a=recvonly' : case 'a=inactive' : return lines [ i ] . substr ( 2 ) ; default : } }
if ( sessionpart ) { return SDPUtils . getDirection ( sessionpart ) ; }
return 'sendrecv' ; } ; SDPUtils . getKind = function ( mediaSection ) { var lines = SDPUtils . splitLines ( mediaSection ) ; var mline = lines [ 0 ] . split ( ' ' ) ; return mline [ 0 ] . substr ( 2 ) ; } ; SDPUtils . isRejected = function ( mediaSection ) { return mediaSection . split ( ' ' , 2 ) [ 1 ] === '0' ; } ; SDPUtils . parseMLine = function ( mediaSection ) { var lines = SDPUtils . splitLines ( mediaSection ) ; var parts = lines [ 0 ] . substr ( 2 ) . split ( ' ' ) ; return { kind : parts [ 0 ] , port : parseInt ( parts [ 1 ] , 10 ) , protocol : parts [ 2 ] , fmt : parts . slice ( 3 ) . join ( ' ' ) } ; } ; SDPUtils . parseOLine = function ( mediaSection ) { var line = SDPUtils . matchPrefix ( mediaSection , 'o=' ) [ 0 ] ; var parts = line . substr ( 2 ) . split ( ' ' ) ; return { username : parts [ 0 ] , sessionId : parts [ 1 ] , sessionVersion : parseInt ( parts [ 2 ] , 10 ) , netType : parts [ 3 ] , addressType : parts [ 4 ] , address : parts [ 5 ] } ; } ; SDPUtils . isValidSDP = function ( blob ) { if ( typeof blob !== 'string' || blob . length === 0 ) { return false ; }
var lines = SDPUtils . splitLines ( blob ) ; for ( var i = 0 ; i < lines . length ; i ++ ) { if ( lines [ i ] . length < 2 || lines [ i ] . charAt ( 1 ) !== '=' ) { return false ; } }
return true ; } ; if ( typeof module === 'object' ) { module . exports = SDPUtils ; } } , { } ] } , { } , [ 1 ] ) ( 1 ) } ) ;