@ -22,6 +22,11 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
@@ -22,6 +22,11 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
// Create AudioContext singleton, if supported.
var context = AudioContext ? new AudioContext ( ) : null ;
var peerconnections = { } ;
// Disabled for now until browser support matures. If enabled this totally breaks
// Firefox and Chrome with Firefox interop.
var enableRenegotiationSupport = false ;
var UserMedia = function ( options ) {
@ -32,9 +37,14 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
@@ -32,9 +37,14 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
this . started = false ;
this . delay = 0 ;
this . audioMute = false ;
this . videoMute = false ;
this . mediaConstraints = null ;
// Audio level.
this . audioLevel = 0 ;
if ( ! this . options . noaudio && context && context . createScriptProcessor ) {
this . audioSource = null ;
this . audioProcessor = context . createScriptProcessor ( 2048 , 1 , 1 ) ;
this . audioProcessor . onaudioprocess = _ . bind ( function ( event ) {
@ -54,8 +64,34 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
@@ -54,8 +64,34 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
this . audioLevel = rms ;
//console.log("this.audioLevel", this.audioLevel);
} , this ) ;
// Connect stream to audio processor if supported.
if ( context . createMediaStreamSource ) {
this . e . on ( "localstream" , _ . bind ( function ( event , stream ) {
if ( this . audioSource ) {
this . audioSource . disconnect ( ) ;
}
// Connect to audioProcessor.
this . audioSource = context . createMediaStreamSource ( stream ) ;
//console.log("got source", this.audioSource);
this . audioSource . connect ( this . audioProcessor ) ;
this . audioProcessor . connect ( context . destination ) ;
} , this ) ) ;
}
}
this . e . on ( "localstream" , _ . bind ( function ( event , stream , oldstream ) {
// Update stream support.
if ( oldstream ) {
_ . each ( peerconnections , function ( pc ) {
pc . removeStream ( oldstream ) ;
pc . addStream ( stream ) ;
console . log ( "Updated usermedia stream at peer connection" , pc , stream ) ;
} ) ;
}
} , this ) ) ;
} ;
// Static.
@ -112,11 +148,30 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
@@ -112,11 +148,30 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
if ( ! mediaConstraints ) {
mediaConstraints = currentcall . mediaConstraints ;
}
this . mediaConstraints = mediaConstraints ;
return this . doGetUserMediaWithConstraints ( mediaConstraints ) ;
} ;
UserMedia . prototype . doGetUserMediaWithConstraints = function ( mediaConstraints ) {
if ( ! mediaConstraints ) {
mediaConstraints = this . mediaConstraints ;
}
var constraints = $ . extend ( true , { } , mediaConstraints ) ;
if ( this . audioMute ) {
constraints . audio = false ;
}
if ( this . videoMute ) {
constraints . video = false ;
}
try {
console . log ( 'Requesting access to local media with mediaConstraints:\n' +
' \'' + JSON . stringify ( mediaConstraints ) + '\'' , mediaConstraints ) ;
getUserMedia ( mediaConstraints , _ . bind ( this . onUserMediaSuccess , this ) , _ . bind ( this . onUserMediaError , this ) ) ;
' \'' + JSON . stringify ( c onstraints) + '\'' , c onstraints) ;
getUserMedia ( c onstraints, _ . bind ( this . onUserMediaSuccess , this ) , _ . bind ( this . onUserMediaError , this ) ) ;
this . started = true ;
return true ;
} catch ( e ) {
@ -134,27 +189,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
@@ -134,27 +189,7 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
return ;
}
// Get notified of end events.
stream . onended = _ . bind ( function ( event ) {
console . log ( "User media stream ended." ) ;
if ( this . started ) {
this . stop ( ) ;
}
} , this ) ;
if ( this . audioProcessor && context . createMediaStreamSource ) {
// Connect to audioProcessor.
this . audioSource = context . createMediaStreamSource ( stream ) ;
//console.log("got source", this.audioSource);
this . audioSource . connect ( this . audioProcessor ) ;
this . audioProcessor . connect ( context . destination ) ;
}
this . localStream = stream ;
// Let webrtc handle the rest.
setTimeout ( _ . bind ( function ( ) {
this . e . triggerHandler ( "mediasuccess" , [ this ] ) ;
} , this ) , this . delay ) ;
this . onLocalStream ( stream ) ;
} ;
@ -170,6 +205,36 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
@@ -170,6 +205,36 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
} ;
UserMedia . prototype . onLocalStream = function ( stream ) {
var oldStream = this . localStream ;
if ( oldStream ) {
oldStream . onended = function ( ) { } ;
oldStream . stop ( ) ;
setTimeout ( _ . bind ( function ( ) {
this . e . triggerHandler ( "mediachanged" , [ this ] ) ;
} , this ) , 0 ) ;
} else {
// Let webrtc handle the rest.
setTimeout ( _ . bind ( function ( ) {
this . e . triggerHandler ( "mediasuccess" , [ this ] ) ;
} , this ) , this . delay ) ;
}
// Get notified of end events.
stream . onended = _ . bind ( function ( event ) {
console . log ( "User media stream ended." ) ;
if ( this . started ) {
this . stop ( ) ;
}
} , this ) ;
// Set new stream.
this . localStream = stream ;
this . e . triggerHandler ( "localstream" , [ stream , oldStream , this ] ) ;
} ;
UserMedia . prototype . stop = function ( ) {
this . started = false ;
@ -186,6 +251,9 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
@@ -186,6 +251,9 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
this . audioProcessor . disconnect ( )
}
this . audioLevel = 0 ;
this . audioMute = false ;
this . videoMute = false ;
this . mediaConstraints = null ;
console . log ( "Stopped user media." ) ;
this . e . triggerHandler ( "stopped" , [ this ] ) ;
@ -198,53 +266,97 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
@@ -198,53 +266,97 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
UserMedia . prototype . applyAudioMute = function ( mute ) {
if ( this . localStream ) {
var m = ! ! mute ;
var audioTracks = this . localStream . getAudioTracks ( ) ;
if ( audioTracks . length === 0 ) {
//console.log('No local audio available.');
return ;
}
if ( ! enableRenegotiationSupport ) {
// Disable streams only - does not require renegotiation but keeps mic
// active and the stream will transmit silence.
if ( this . localStream ) {
var audioTracks = this . localStream . getAudioTracks ( ) ;
if ( audioTracks . length === 0 ) {
//console.log('No local audio available.');
return ;
}
for ( var i = 0 ; i < audioTracks . length ; i ++ ) {
audioTracks [ i ] . enabled = ! mute ;
}
if ( mute ) {
console . log ( "Local audio muted by disabling audio tracks." ) ;
} else {
console . log ( "Local audio unmuted by enabling audio tracks." ) ;
}
for ( i = 0 ; i < audioTracks . length ; i ++ ) {
audioTracks [ i ] . enabled = ! mute ;
}
if ( mute ) {
console . log ( "Local audio muted." )
} else {
// Remove audio stream, by creating a new stream and doing renegotiation. This
// is the way to go to disable the mic when audio is muted.
if ( this . localStream ) {
if ( this . audioMute !== m ) {
this . audioMute = m ;
this . doGetUserMediaWithConstraints ( ) ;
}
} else {
console . log ( "Local audio unmuted." )
this . audioMute = m ;
}
}
return mute ;
return m ;
} ;
UserMedia . prototype . applyVideoMute = function ( mute ) {
if ( this . localStream ) {
var m = ! ! mute ;
var videoTracks = this . localStream . getVideoTracks ( ) ;
if ( videoTracks . length === 0 ) {
//console.log('No local video available.');
return ;
}
if ( ! enableRenegotiationSupport ) {
// Disable streams only - does not require renegotiation but keeps camera
// active and the stream will transmit black.
if ( this . localStream ) {
var videoTracks = this . localStream . getVideoTracks ( ) ;
if ( videoTracks . length === 0 ) {
//console.log('No local video available.');
return ;
}
for ( var i = 0 ; i < videoTracks . length ; i ++ ) {
videoTracks [ i ] . enabled = ! mute ;
}
if ( mute ) {
console . log ( "Local video muted by disabling video tracks." ) ;
} else {
console . log ( "Local video unmuted by enabling video tracks." ) ;
}
for ( i = 0 ; i < videoTracks . length ; i ++ ) {
videoTracks [ i ] . enabled = ! mute ;
}
} else {
if ( mute ) {
console . log ( "Local video muted." )
// Removevideo stream, by creating a new stream and doing renegotiation. This
// is the way to go to disable the camera when video is muted.
if ( this . localStream ) {
if ( this . videoMute !== m ) {
this . videoMute = m ;
this . doGetUserMediaWithConstraints ( ) ;
}
} else {
console . log ( "Local video unmuted." )
this . videoMute = m ;
}
}
return mute ;
return m ;
} ;
@ -253,6 +365,13 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
@@ -253,6 +365,13 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
console . log ( "Add usermedia stream to peer connection" , pc , this . localStream ) ;
if ( this . localStream ) {
pc . addStream ( this . localStream ) ;
var id = pc . id ;
if ( ! peerconnections . hasOwnProperty ( id ) ) {
peerconnections [ id ] = pc ;
pc . currentcall . e . one ( "closed" , function ( ) {
delete peerconnections [ id ] ;
} ) ;
}
}
} ;
@ -262,13 +381,15 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
@@ -262,13 +381,15 @@ define(['jquery', 'underscore', 'audiocontext', 'webrtc.adapter'], function($, _
console . log ( "Remove usermedia stream from peer connection" , pc , this . localStream ) ;
if ( this . localStream ) {
pc . removeStream ( this . localStream ) ;
if ( peerconnections . hasOwnProperty ( pc . id ) ) {
delete peerconnections [ pc . id ] ;
}
}
} ;
UserMedia . prototype . attachMediaStream = function ( video ) {
//console.log("attach", video, this.localStream);
attachMediaStream ( video , this . localStream ) ;
} ;