Changes the implementation of RTCUtils to be static.
This commit is contained in:
parent
a241d4b9b4
commit
2b5d893ec1
|
@ -83,8 +83,8 @@ LocalStream.prototype.setMute = function (mute)
|
|||
this.eventEmitter.emit(eventType, true);
|
||||
} else {
|
||||
var self = this;
|
||||
this.rtcUtils.obtainAudioAndVideoPermissions(
|
||||
(this.isAudioStream() ? ["audio"] : ["video"]))
|
||||
this.rtc.obtainAudioAndVideoPermissions(
|
||||
{devices: (this.isAudioStream() ? ["audio"] : ["video"])})
|
||||
.then(function (stream) {
|
||||
if (isAudio) {
|
||||
self.rtc.changeLocalAudio(stream,
|
||||
|
|
|
@ -11,7 +11,6 @@ var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
|
|||
var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
|
||||
var RTCEvents = require("../../service/RTC/RTCEvents.js");
|
||||
var XMPPEvents = require("../../service/xmpp/XMPPEvents");
|
||||
var UIEvents = require("../../service/UI/UIEvents");
|
||||
var desktopsharing = require("../desktopsharing/desktopsharing");
|
||||
|
||||
function getMediaStreamUsage()
|
||||
|
@ -44,7 +43,6 @@ function getMediaStreamUsage()
|
|||
|
||||
function RTC(options)
|
||||
{
|
||||
this.rtcUtils = null;
|
||||
this.devices = {
|
||||
audio: true,
|
||||
video: true
|
||||
|
@ -68,7 +66,7 @@ function RTC(options)
|
|||
self.eventEmitter.emit(RTCEvents.RTC_READY, true);
|
||||
};
|
||||
|
||||
this.rtcUtils = new RTCUtils(this, onReady);
|
||||
RTCUtils.init(onReady);
|
||||
|
||||
// Call onReady() if Temasys plugin is not used
|
||||
if (!RTCBrowserType.isTemasysPluginUsed()) {
|
||||
|
@ -77,8 +75,8 @@ function RTC(options)
|
|||
}
|
||||
|
||||
RTC.prototype.obtainAudioAndVideoPermissions = function (options) {
|
||||
return this.rtcUtils.obtainAudioAndVideoPermissions(
|
||||
null, getMediaStreamUsage(), options.resolution);
|
||||
return RTCUtils.obtainAudioAndVideoPermissions(this,
|
||||
options.devices, getMediaStreamUsage(), options.resolution);
|
||||
}
|
||||
|
||||
RTC.prototype.onIncommingCall = function(event) {
|
||||
|
@ -154,32 +152,32 @@ RTC.prototype.createRemoteStream = function (data, sid, thessrc) {
|
|||
return remoteStream;
|
||||
};
|
||||
|
||||
RTC.prototype.getPCConstraints = function () {
|
||||
return this.rtcUtils.pc_constraints;
|
||||
RTC.getPCConstraints = function () {
|
||||
return RTCUtils.pc_constraints;
|
||||
};
|
||||
|
||||
RTC.prototype.getUserMediaWithConstraints = function(um, success_callback,
|
||||
failure_callback, resolution,
|
||||
bandwidth, fps, desktopStream)
|
||||
{
|
||||
return this.rtcUtils.getUserMediaWithConstraints(um, success_callback,
|
||||
return RTCUtils.getUserMediaWithConstraints(this, um, success_callback,
|
||||
failure_callback, resolution, bandwidth, fps, desktopStream);
|
||||
};
|
||||
|
||||
RTC.prototype.attachMediaStream = function (elSelector, stream) {
|
||||
this.rtcUtils.attachMediaStream(elSelector, stream);
|
||||
RTC.attachMediaStream = function (elSelector, stream) {
|
||||
RTCUtils.attachMediaStream(elSelector, stream);
|
||||
};
|
||||
|
||||
RTC.prototype.getStreamID = function (stream) {
|
||||
return this.rtcUtils.getStreamID(stream);
|
||||
RTC.getStreamID = function (stream) {
|
||||
return RTCUtils.getStreamID(stream);
|
||||
};
|
||||
|
||||
RTC.prototype.getVideoSrc = function (element) {
|
||||
return this.rtcUtils.getVideoSrc(element);
|
||||
RTC.getVideoSrc = function (element) {
|
||||
return RTCUtils.getVideoSrc(element);
|
||||
};
|
||||
|
||||
RTC.prototype.setVideoSrc = function (element, src) {
|
||||
this.rtcUtils.setVideoSrc(element, src);
|
||||
RTC.setVideoSrc = function (element, src) {
|
||||
RTCUtils.setVideoSrc(element, src);
|
||||
};
|
||||
|
||||
RTC.prototype.getVideoElementName = function () {
|
||||
|
@ -187,9 +185,6 @@ RTC.prototype.getVideoElementName = function () {
|
|||
};
|
||||
|
||||
RTC.prototype.dispose = function() {
|
||||
if (this.rtcUtils) {
|
||||
this.rtcUtils = null;
|
||||
}
|
||||
};
|
||||
|
||||
RTC.prototype.muteRemoteVideoStream = function (jid, value) {
|
||||
|
@ -239,7 +234,7 @@ RTC.prototype.changeLocalVideo = function (stream, isUsingScreenStream, callback
|
|||
if (stream && stream.videoStream) {
|
||||
stream = stream.videoStream;
|
||||
}
|
||||
var videoStream = this.rtcUtils.createStream(stream, true);
|
||||
var videoStream = RTCUtils.createStream(stream, true);
|
||||
this.localVideo = this.createLocalStream(videoStream, "video", true, type);
|
||||
// Stop the stream to trigger onended event for old stream
|
||||
oldStream.stop();
|
||||
|
@ -251,7 +246,7 @@ RTC.prototype.changeLocalVideo = function (stream, isUsingScreenStream, callback
|
|||
|
||||
RTC.prototype.changeLocalAudio = function (stream, callback) {
|
||||
var oldStream = this.localAudio.getOriginalStream();
|
||||
var newStream = this.rtcUtils.createStream(stream);
|
||||
var newStream = RTCUtils.createStream(stream);
|
||||
this.localAudio = this.createLocalStream(newStream, "audio", true);
|
||||
// Stop the stream to trigger onended event for old stream
|
||||
oldStream.stop();
|
||||
|
|
|
@ -5,6 +5,13 @@ var AdapterJS = require("./adapter.screenshare");
|
|||
var SDPUtil = require("../xmpp/SDPUtil");
|
||||
|
||||
var currentResolution = null;
|
||||
function DummyMediaStream(id) {
|
||||
this.id = id;
|
||||
this.label = id;
|
||||
this.stop = function() { };
|
||||
this.getAudioTracks = function() { return []; };
|
||||
this.getVideoTracks = function() { return []; };
|
||||
}
|
||||
|
||||
function getPreviousResolution(resolution) {
|
||||
if(!Resolutions[resolution])
|
||||
|
@ -135,420 +142,413 @@ function getConstraints(um, resolution, bandwidth, fps, desktopStream, isAndroid
|
|||
}
|
||||
|
||||
//Options parameter is to pass config options. Currently uses only "useIPv6".
|
||||
function RTCUtils(RTCService, onTemasysPluginReady)
|
||||
{
|
||||
var self = this;
|
||||
this.service = RTCService;
|
||||
if (RTCBrowserType.isFirefox()) {
|
||||
var FFversion = RTCBrowserType.getFirefoxVersion();
|
||||
if (FFversion >= 40) {
|
||||
this.peerconnection = mozRTCPeerConnection;
|
||||
this.getUserMedia = navigator.mozGetUserMedia.bind(navigator);
|
||||
this.pc_constraints = {};
|
||||
this.attachMediaStream = function (element, stream) {
|
||||
// srcObject is being standardized and FF will eventually
|
||||
// support that unprefixed. FF also supports the
|
||||
// "element.src = URL.createObjectURL(...)" combo, but that
|
||||
// will be deprecated in favour of srcObject.
|
||||
//
|
||||
// https://groups.google.com/forum/#!topic/mozilla.dev.media/pKOiioXonJg
|
||||
// https://github.com/webrtc/samples/issues/302
|
||||
if(!element[0])
|
||||
return;
|
||||
element[0].mozSrcObject = stream;
|
||||
element[0].play();
|
||||
};
|
||||
this.getStreamID = function (stream) {
|
||||
var id = stream.id;
|
||||
if (!id) {
|
||||
var tracks = stream.getVideoTracks();
|
||||
if (!tracks || tracks.length === 0) {
|
||||
tracks = stream.getAudioTracks();
|
||||
var RTCUtils = {
|
||||
init: function (onTemasysPluginReady) {
|
||||
var self = this;
|
||||
if (RTCBrowserType.isFirefox()) {
|
||||
var FFversion = RTCBrowserType.getFirefoxVersion();
|
||||
if (FFversion >= 40) {
|
||||
this.peerconnection = mozRTCPeerConnection;
|
||||
this.getUserMedia = navigator.mozGetUserMedia.bind(navigator);
|
||||
this.pc_constraints = {};
|
||||
this.attachMediaStream = function (element, stream) {
|
||||
// srcObject is being standardized and FF will eventually
|
||||
// support that unprefixed. FF also supports the
|
||||
// "element.src = URL.createObjectURL(...)" combo, but that
|
||||
// will be deprecated in favour of srcObject.
|
||||
//
|
||||
// https://groups.google.com/forum/#!topic/mozilla.dev.media/pKOiioXonJg
|
||||
// https://github.com/webrtc/samples/issues/302
|
||||
if (!element[0])
|
||||
return;
|
||||
element[0].mozSrcObject = stream;
|
||||
element[0].play();
|
||||
};
|
||||
this.getStreamID = function (stream) {
|
||||
var id = stream.id;
|
||||
if (!id) {
|
||||
var tracks = stream.getVideoTracks();
|
||||
if (!tracks || tracks.length === 0) {
|
||||
tracks = stream.getAudioTracks();
|
||||
}
|
||||
id = tracks[0].id;
|
||||
}
|
||||
id = tracks[0].id;
|
||||
}
|
||||
return SDPUtil.filter_special_chars(id);
|
||||
return SDPUtil.filter_special_chars(id);
|
||||
};
|
||||
this.getVideoSrc = function (element) {
|
||||
if (!element)
|
||||
return null;
|
||||
return element.mozSrcObject;
|
||||
};
|
||||
this.setVideoSrc = function (element, src) {
|
||||
if (element)
|
||||
element.mozSrcObject = src;
|
||||
};
|
||||
RTCSessionDescription = mozRTCSessionDescription;
|
||||
RTCIceCandidate = mozRTCIceCandidate;
|
||||
} else {
|
||||
console.error(
|
||||
"Firefox version too old: " + FFversion + ". Required >= 40.");
|
||||
window.location.href = 'unsupported_browser.html';
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (RTCBrowserType.isChrome() || RTCBrowserType.isOpera()) {
|
||||
this.peerconnection = webkitRTCPeerConnection;
|
||||
this.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
|
||||
this.attachMediaStream = function (element, stream) {
|
||||
element.attr('src', webkitURL.createObjectURL(stream));
|
||||
};
|
||||
this.getStreamID = function (stream) {
|
||||
// streams from FF endpoints have the characters '{' and '}'
|
||||
// that make jQuery choke.
|
||||
return SDPUtil.filter_special_chars(stream.id);
|
||||
};
|
||||
this.getVideoSrc = function (element) {
|
||||
if(!element)
|
||||
if (!element)
|
||||
return null;
|
||||
return element.mozSrcObject;
|
||||
return element.getAttribute("src");
|
||||
};
|
||||
this.setVideoSrc = function (element, src) {
|
||||
if(element)
|
||||
element.mozSrcObject = src;
|
||||
if (element)
|
||||
element.setAttribute("src", src);
|
||||
};
|
||||
RTCSessionDescription = mozRTCSessionDescription;
|
||||
RTCIceCandidate = mozRTCIceCandidate;
|
||||
} else {
|
||||
console.error(
|
||||
"Firefox version too old: " + FFversion + ". Required >= 40.");
|
||||
window.location.href = 'unsupported_browser.html';
|
||||
return;
|
||||
// DTLS should now be enabled by default but..
|
||||
this.pc_constraints = {'optional': [
|
||||
{'DtlsSrtpKeyAgreement': 'true'}
|
||||
]};
|
||||
if (this.service.options.useIPv6) {
|
||||
// https://code.google.com/p/webrtc/issues/detail?id=2828
|
||||
this.pc_constraints.optional.push({googIPv6: true});
|
||||
}
|
||||
if (navigator.userAgent.indexOf('Android') != -1) {
|
||||
this.pc_constraints = {}; // disable DTLS on Android
|
||||
}
|
||||
if (!webkitMediaStream.prototype.getVideoTracks) {
|
||||
webkitMediaStream.prototype.getVideoTracks = function () {
|
||||
return this.videoTracks;
|
||||
};
|
||||
}
|
||||
if (!webkitMediaStream.prototype.getAudioTracks) {
|
||||
webkitMediaStream.prototype.getAudioTracks = function () {
|
||||
return this.audioTracks;
|
||||
};
|
||||
}
|
||||
}
|
||||
// Detect IE/Safari
|
||||
else if (RTCBrowserType.isTemasysPluginUsed()) {
|
||||
|
||||
} else if (RTCBrowserType.isChrome() || RTCBrowserType.isOpera()) {
|
||||
this.peerconnection = webkitRTCPeerConnection;
|
||||
this.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
|
||||
this.attachMediaStream = function (element, stream) {
|
||||
element.attr('src', webkitURL.createObjectURL(stream));
|
||||
};
|
||||
this.getStreamID = function (stream) {
|
||||
// streams from FF endpoints have the characters '{' and '}'
|
||||
// that make jQuery choke.
|
||||
return SDPUtil.filter_special_chars(stream.id);
|
||||
};
|
||||
this.getVideoSrc = function (element) {
|
||||
if(!element)
|
||||
return null;
|
||||
return element.getAttribute("src");
|
||||
};
|
||||
this.setVideoSrc = function (element, src) {
|
||||
if(element)
|
||||
element.setAttribute("src", src);
|
||||
};
|
||||
// DTLS should now be enabled by default but..
|
||||
this.pc_constraints = {'optional': [{'DtlsSrtpKeyAgreement': 'true'}]};
|
||||
if (this.service.options.useIPv6) {
|
||||
// https://code.google.com/p/webrtc/issues/detail?id=2828
|
||||
this.pc_constraints.optional.push({googIPv6: true});
|
||||
}
|
||||
if (navigator.userAgent.indexOf('Android') != -1) {
|
||||
this.pc_constraints = {}; // disable DTLS on Android
|
||||
}
|
||||
if (!webkitMediaStream.prototype.getVideoTracks) {
|
||||
webkitMediaStream.prototype.getVideoTracks = function () {
|
||||
return this.videoTracks;
|
||||
};
|
||||
}
|
||||
if (!webkitMediaStream.prototype.getAudioTracks) {
|
||||
webkitMediaStream.prototype.getAudioTracks = function () {
|
||||
return this.audioTracks;
|
||||
};
|
||||
}
|
||||
}
|
||||
// Detect IE/Safari
|
||||
else if (RTCBrowserType.isTemasysPluginUsed()) {
|
||||
//AdapterJS.WebRTCPlugin.setLogLevel(
|
||||
// AdapterJS.WebRTCPlugin.PLUGIN_LOG_LEVELS.VERBOSE);
|
||||
|
||||
//AdapterJS.WebRTCPlugin.setLogLevel(
|
||||
// AdapterJS.WebRTCPlugin.PLUGIN_LOG_LEVELS.VERBOSE);
|
||||
AdapterJS.webRTCReady(function (isPlugin) {
|
||||
|
||||
AdapterJS.webRTCReady(function (isPlugin) {
|
||||
self.peerconnection = RTCPeerConnection;
|
||||
self.getUserMedia = getUserMedia;
|
||||
self.attachMediaStream = function (elSel, stream) {
|
||||
|
||||
self.peerconnection = RTCPeerConnection;
|
||||
self.getUserMedia = getUserMedia;
|
||||
self.attachMediaStream = function (elSel, stream) {
|
||||
if (stream.id === "dummyAudio" || stream.id === "dummyVideo") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stream.id === "dummyAudio" || stream.id === "dummyVideo") {
|
||||
return;
|
||||
}
|
||||
|
||||
attachMediaStream(elSel[0], stream);
|
||||
};
|
||||
self.getStreamID = function (stream) {
|
||||
var id = SDPUtil.filter_special_chars(stream.label);
|
||||
return id;
|
||||
};
|
||||
self.getVideoSrc = function (element) {
|
||||
if (!element) {
|
||||
console.warn("Attempt to get video SRC of null element");
|
||||
attachMediaStream(elSel[0], stream);
|
||||
};
|
||||
self.getStreamID = function (stream) {
|
||||
var id = SDPUtil.filter_special_chars(stream.label);
|
||||
return id;
|
||||
};
|
||||
self.getVideoSrc = function (element) {
|
||||
if (!element) {
|
||||
console.warn("Attempt to get video SRC of null element");
|
||||
return null;
|
||||
}
|
||||
var children = element.children;
|
||||
for (var i = 0; i !== children.length; ++i) {
|
||||
if (children[i].name === 'streamId') {
|
||||
return children[i].value;
|
||||
}
|
||||
}
|
||||
//console.info(element.id + " SRC: " + src);
|
||||
return null;
|
||||
}
|
||||
var children = element.children;
|
||||
for (var i = 0; i !== children.length; ++i) {
|
||||
if (children[i].name === 'streamId') {
|
||||
return children[i].value;
|
||||
};
|
||||
self.setVideoSrc = function (element, src) {
|
||||
//console.info("Set video src: ", element, src);
|
||||
if (!src) {
|
||||
console.warn("Not attaching video stream, 'src' is null");
|
||||
return;
|
||||
}
|
||||
}
|
||||
//console.info(element.id + " SRC: " + src);
|
||||
return null;
|
||||
};
|
||||
self.setVideoSrc = function (element, src) {
|
||||
//console.info("Set video src: ", element, src);
|
||||
if (!src) {
|
||||
console.warn("Not attaching video stream, 'src' is null");
|
||||
return;
|
||||
}
|
||||
AdapterJS.WebRTCPlugin.WaitForPluginReady();
|
||||
var stream = AdapterJS.WebRTCPlugin.plugin
|
||||
.getStreamWithId(AdapterJS.WebRTCPlugin.pageId, src);
|
||||
attachMediaStream(element, stream);
|
||||
};
|
||||
AdapterJS.WebRTCPlugin.WaitForPluginReady();
|
||||
var stream = AdapterJS.WebRTCPlugin.plugin
|
||||
.getStreamWithId(AdapterJS.WebRTCPlugin.pageId, src);
|
||||
attachMediaStream(element, stream);
|
||||
};
|
||||
|
||||
onTemasysPluginReady(isPlugin);
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
console.log('Browser does not appear to be WebRTC-capable');
|
||||
} catch (e) { }
|
||||
window.location.href = 'unsupported_browser.html';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
RTCUtils.prototype.getUserMediaWithConstraints = function(
|
||||
um, success_callback, failure_callback, resolution,bandwidth, fps,
|
||||
desktopStream) {
|
||||
currentResolution = resolution;
|
||||
// Check if we are running on Android device
|
||||
var isAndroid = navigator.userAgent.indexOf('Android') != -1;
|
||||
|
||||
var constraints = getConstraints(
|
||||
um, resolution, bandwidth, fps, desktopStream, isAndroid);
|
||||
|
||||
console.info("Get media constraints", constraints);
|
||||
|
||||
var self = this;
|
||||
|
||||
try {
|
||||
this.getUserMedia(constraints,
|
||||
function (stream) {
|
||||
console.log('onUserMediaSuccess');
|
||||
self.setAvailableDevices(um, true);
|
||||
success_callback(stream);
|
||||
},
|
||||
function (error) {
|
||||
self.setAvailableDevices(um, false);
|
||||
console.warn('Failed to get access to local media. Error ',
|
||||
error, constraints);
|
||||
if (failure_callback) {
|
||||
failure_callback(error);
|
||||
}
|
||||
onTemasysPluginReady(isPlugin);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('GUM failed: ', e);
|
||||
if(failure_callback) {
|
||||
failure_callback(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RTCUtils.prototype.setAvailableDevices = function (um, available) {
|
||||
var devices = {};
|
||||
if(um.indexOf("video") != -1) {
|
||||
devices.video = available;
|
||||
}
|
||||
if(um.indexOf("audio") != -1) {
|
||||
devices.audio = available;
|
||||
}
|
||||
this.service.setDeviceAvailability(devices);
|
||||
};
|
||||
|
||||
/**
|
||||
* We ask for audio and video combined stream in order to get permissions and
|
||||
* not to ask twice.
|
||||
*/
|
||||
RTCUtils.prototype.obtainAudioAndVideoPermissions =
|
||||
function(devices, usageOptions, resolution)
|
||||
{
|
||||
var self = this;
|
||||
// Get AV
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
var successCallback = function (stream) {
|
||||
resolve(self.successCallback(stream, usageOptions));
|
||||
};
|
||||
|
||||
if (!devices)
|
||||
devices = ['audio', 'video'];
|
||||
|
||||
var newDevices = [];
|
||||
|
||||
|
||||
if (usageOptions)
|
||||
for (var i = 0; i < devices.length; i++) {
|
||||
var device = devices[i];
|
||||
if (usageOptions[device] === true)
|
||||
newDevices.push(device);
|
||||
}
|
||||
else
|
||||
newDevices = devices;
|
||||
|
||||
if (newDevices.length === 0) {
|
||||
successCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
if (RTCBrowserType.isFirefox() || RTCBrowserType.isTemasysPluginUsed()) {
|
||||
|
||||
// With FF/IE we can't split the stream into audio and video because FF
|
||||
// doesn't support media stream constructors. So, we need to get the
|
||||
// audio stream separately from the video stream using two distinct GUM
|
||||
// calls. Not very user friendly :-( but we don't have many other
|
||||
// options neither.
|
||||
//
|
||||
// Note that we pack those 2 streams in a single object and pass it to
|
||||
// the successCallback method.
|
||||
var obtainVideo = function (audioStream) {
|
||||
self.getUserMediaWithConstraints(
|
||||
['video'],
|
||||
function (videoStream) {
|
||||
return successCallback({
|
||||
audioStream: audioStream,
|
||||
videoStream: videoStream
|
||||
});
|
||||
},
|
||||
function (error) {
|
||||
console.error(
|
||||
'failed to obtain video stream - stop', error);
|
||||
self.errorCallback(error, resolve);
|
||||
},
|
||||
config.resolution || '360');
|
||||
};
|
||||
var obtainAudio = function () {
|
||||
self.getUserMediaWithConstraints(
|
||||
['audio'],
|
||||
function (audioStream) {
|
||||
if (newDevices.indexOf('video') !== -1)
|
||||
obtainVideo(audioStream);
|
||||
},
|
||||
function (error) {
|
||||
console.error(
|
||||
'failed to obtain audio stream - stop', error);
|
||||
self.errorCallback(error, resolve);
|
||||
}
|
||||
);
|
||||
};
|
||||
if (newDevices.indexOf('audio') !== -1) {
|
||||
obtainAudio();
|
||||
} else {
|
||||
obtainVideo(null);
|
||||
}
|
||||
} else {
|
||||
this.getUserMediaWithConstraints(
|
||||
newDevices,
|
||||
try {
|
||||
console.log('Browser does not appear to be WebRTC-capable');
|
||||
} catch (e) {
|
||||
}
|
||||
window.location.href = 'unsupported_browser.html';
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
getUserMediaWithConstraints: function (RTC, um, success_callback, failure_callback, resolution, bandwidth, fps, desktopStream) {
|
||||
// Check if we are running on Android device
|
||||
var isAndroid = navigator.userAgent.indexOf('Android') != -1;
|
||||
|
||||
var constraints = getConstraints(
|
||||
um, resolution, bandwidth, fps, desktopStream, isAndroid);
|
||||
|
||||
console.info("Get media constraints", constraints);
|
||||
|
||||
var self = this;
|
||||
|
||||
try {
|
||||
this.getUserMedia(constraints,
|
||||
function (stream) {
|
||||
successCallback(stream);
|
||||
console.log('onUserMediaSuccess');
|
||||
self.setAvailableDevices(RTC, um, true);
|
||||
success_callback(stream);
|
||||
},
|
||||
function (error) {
|
||||
self.errorCallback(error, resolve);
|
||||
self.setAvailableDevices(RTC, um, false);
|
||||
console.warn('Failed to get access to local media. Error ',
|
||||
error, constraints);
|
||||
if (failure_callback) {
|
||||
failure_callback(error, resolution);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('GUM failed: ', e);
|
||||
if (failure_callback) {
|
||||
failure_callback(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setAvailableDevices: function (RTC, um, available) {
|
||||
var devices = {};
|
||||
if (um.indexOf("video") != -1) {
|
||||
devices.video = available;
|
||||
}
|
||||
if (um.indexOf("audio") != -1) {
|
||||
devices.audio = available;
|
||||
}
|
||||
RTC.setDeviceAvailability(devices);
|
||||
},
|
||||
|
||||
/**
|
||||
* We ask for audio and video combined stream in order to get permissions and
|
||||
* not to ask twice.
|
||||
*/
|
||||
obtainAudioAndVideoPermissions: function (RTC, devices, usageOptions, resolution) {
|
||||
var self = this;
|
||||
// Get AV
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
var successCallback = function (stream) {
|
||||
resolve(self.successCallback(stream, usageOptions));
|
||||
};
|
||||
|
||||
if (!devices)
|
||||
devices = ['audio', 'video'];
|
||||
|
||||
var newDevices = [];
|
||||
|
||||
|
||||
if (usageOptions)
|
||||
for (var i = 0; i < devices.length; i++) {
|
||||
var device = devices[i];
|
||||
if (usageOptions[device] === true)
|
||||
newDevices.push(device);
|
||||
}
|
||||
else
|
||||
newDevices = devices;
|
||||
|
||||
if (newDevices.length === 0) {
|
||||
successCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
if (RTCBrowserType.isFirefox() || RTCBrowserType.isTemasysPluginUsed()) {
|
||||
|
||||
// With FF/IE we can't split the stream into audio and video because FF
|
||||
// doesn't support media stream constructors. So, we need to get the
|
||||
// audio stream separately from the video stream using two distinct GUM
|
||||
// calls. Not very user friendly :-( but we don't have many other
|
||||
// options neither.
|
||||
//
|
||||
// Note that we pack those 2 streams in a single object and pass it to
|
||||
// the successCallback method.
|
||||
var obtainVideo = function (audioStream) {
|
||||
self.getUserMediaWithConstraints(
|
||||
RTC,
|
||||
['video'],
|
||||
function (videoStream) {
|
||||
return successCallback({
|
||||
audioStream: audioStream,
|
||||
videoStream: videoStream
|
||||
});
|
||||
},
|
||||
function (error, resolution) {
|
||||
console.error(
|
||||
'failed to obtain video stream - stop', error);
|
||||
self.errorCallback(error, resolve, RTC, resolution);
|
||||
},
|
||||
config.resolution || '360');
|
||||
};
|
||||
var obtainAudio = function () {
|
||||
self.getUserMediaWithConstraints(
|
||||
RTC,
|
||||
['audio'],
|
||||
function (audioStream) {
|
||||
if (newDevices.indexOf('video') !== -1)
|
||||
obtainVideo(audioStream);
|
||||
},
|
||||
function (error) {
|
||||
console.error(
|
||||
'failed to obtain audio stream - stop', error);
|
||||
self.errorCallback(error, resolve, RTC);
|
||||
}
|
||||
);
|
||||
};
|
||||
if (newDevices.indexOf('audio') !== -1) {
|
||||
obtainAudio();
|
||||
} else {
|
||||
obtainVideo(null);
|
||||
}
|
||||
} else {
|
||||
this.getUserMediaWithConstraints(
|
||||
RTC,
|
||||
newDevices,
|
||||
function (stream) {
|
||||
successCallback(stream);
|
||||
},
|
||||
function (error, resolution) {
|
||||
self.errorCallback(error, resolve, RTC, resolution);
|
||||
},
|
||||
resolution || '360');
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
successCallback: function (stream, usageOptions) {
|
||||
// If this is FF or IE, the stream parameter is *not* a MediaStream object,
|
||||
// it's an object with two properties: audioStream, videoStream.
|
||||
if (stream && stream.getAudioTracks && stream.getVideoTracks)
|
||||
console.log('got', stream, stream.getAudioTracks().length,
|
||||
stream.getVideoTracks().length);
|
||||
return this.handleLocalStream(stream, usageOptions);
|
||||
},
|
||||
|
||||
errorCallback: function (error, resolve, RTC, currentResolution) {
|
||||
var self = this;
|
||||
console.error('failed to obtain audio/video stream - trying audio only', error);
|
||||
var resolution = getPreviousResolution(currentResolution);
|
||||
if (typeof error == "object" && error.constraintName && error.name
|
||||
&& (error.name == "ConstraintNotSatisfiedError" ||
|
||||
error.name == "OverconstrainedError") &&
|
||||
(error.constraintName == "minWidth" || error.constraintName == "maxWidth" ||
|
||||
error.constraintName == "minHeight" || error.constraintName == "maxHeight")
|
||||
&& resolution != null) {
|
||||
self.getUserMediaWithConstraints(RTC, ['audio', 'video'],
|
||||
function (stream) {
|
||||
resolve(self.successCallback(stream));
|
||||
}, function (error, resolution) {
|
||||
return self.errorCallback(error, resolve, RTC, resolution);
|
||||
}, resolution);
|
||||
}
|
||||
else {
|
||||
self.getUserMediaWithConstraints(
|
||||
RTC,
|
||||
['audio'],
|
||||
function (stream) {
|
||||
resolve(self.successCallback(stream));
|
||||
},
|
||||
resolution || '360');
|
||||
function (error) {
|
||||
console.error('failed to obtain audio/video stream - stop',
|
||||
error);
|
||||
resolve(self.successCallback(null));
|
||||
}
|
||||
);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
},
|
||||
|
||||
RTCUtils.prototype.successCallback = function (stream, usageOptions) {
|
||||
// If this is FF or IE, the stream parameter is *not* a MediaStream object,
|
||||
// it's an object with two properties: audioStream, videoStream.
|
||||
if (stream && stream.getAudioTracks && stream.getVideoTracks)
|
||||
console.log('got', stream, stream.getAudioTracks().length,
|
||||
stream.getVideoTracks().length);
|
||||
return this.handleLocalStream(stream, usageOptions);
|
||||
};
|
||||
handleLocalStream: function (stream, usageOptions) {
|
||||
// If this is FF, the stream parameter is *not* a MediaStream object, it's
|
||||
// an object with two properties: audioStream, videoStream.
|
||||
if (window.webkitMediaStream) {
|
||||
audioStream = new webkitMediaStream();
|
||||
videoStream = new webkitMediaStream();
|
||||
if (stream) {
|
||||
var audioTracks = stream.getAudioTracks();
|
||||
|
||||
RTCUtils.prototype.errorCallback = function (error, resolve) {
|
||||
var self = this;
|
||||
console.error('failed to obtain audio/video stream - trying audio only', error);
|
||||
var resolution = getPreviousResolution(currentResolution);
|
||||
if(typeof error == "object" && error.constraintName && error.name
|
||||
&& (error.name == "ConstraintNotSatisfiedError" ||
|
||||
error.name == "OverconstrainedError") &&
|
||||
(error.constraintName == "minWidth" || error.constraintName == "maxWidth" ||
|
||||
error.constraintName == "minHeight" || error.constraintName == "maxHeight")
|
||||
&& resolution != null)
|
||||
{
|
||||
self.getUserMediaWithConstraints(['audio', 'video'],
|
||||
function (stream) {
|
||||
resolve(self.successCallback(stream));
|
||||
}, function (error) {
|
||||
return self.errorCallback(error);
|
||||
}, resolution);
|
||||
}
|
||||
else {
|
||||
self.getUserMediaWithConstraints(
|
||||
['audio'],
|
||||
function (stream) {
|
||||
resolve(self.successCallback(stream));
|
||||
},
|
||||
function (error) {
|
||||
console.error('failed to obtain audio/video stream - stop',
|
||||
error);
|
||||
resolve(self.successCallback(null));
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
for (var i = 0; i < audioTracks.length; i++) {
|
||||
audioStream.addTrack(audioTracks[i]);
|
||||
}
|
||||
|
||||
RTCUtils.prototype.handleLocalStream = function(stream, usageOptions) {
|
||||
// If this is FF, the stream parameter is *not* a MediaStream object, it's
|
||||
// an object with two properties: audioStream, videoStream.
|
||||
if(window.webkitMediaStream)
|
||||
{
|
||||
audioStream = new webkitMediaStream();
|
||||
videoStream = new webkitMediaStream();
|
||||
if(stream) {
|
||||
var audioTracks = stream.getAudioTracks();
|
||||
var videoTracks = stream.getVideoTracks();
|
||||
|
||||
for (var i = 0; i < audioTracks.length; i++) {
|
||||
audioStream.addTrack(audioTracks[i]);
|
||||
for (i = 0; i < videoTracks.length; i++) {
|
||||
videoStream.addTrack(videoTracks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var videoTracks = stream.getVideoTracks();
|
||||
}
|
||||
else if (RTCBrowserType.isFirefox() || RTCBrowserType.isTemasysPluginUsed()) { // Firefox and Temasys plugin
|
||||
if (stream && stream.audioStream)
|
||||
audioStream = stream.audioStream;
|
||||
else
|
||||
audioStream = new DummyMediaStream("dummyAudio");
|
||||
|
||||
for (i = 0; i < videoTracks.length; i++) {
|
||||
videoStream.addTrack(videoTracks[i]);
|
||||
if (stream && stream.videoStream)
|
||||
videoStream = stream.videoStream;
|
||||
else
|
||||
videoStream = new DummyMediaStream("dummyVideo");
|
||||
}
|
||||
|
||||
var audioMuted = (usageOptions && usageOptions.audio === false),
|
||||
videoMuted = (usageOptions && usageOptions.video === false);
|
||||
|
||||
var audioGUM = (!usageOptions || usageOptions.audio !== false),
|
||||
videoGUM = (!usageOptions || usageOptions.video !== false);
|
||||
|
||||
return this.service.createLocalStreams(
|
||||
[
|
||||
{stream: audioStream, type: "audio", isMuted: audioMuted, isGUMStream: audioGUM, videoType: null},
|
||||
{stream: videoStream, type: "video", isMuted: videoMuted, isGUMStream: videoGUM, videoType: "camera"}
|
||||
]);
|
||||
},
|
||||
|
||||
createStream: function (stream, isVideo) {
|
||||
var newStream = null;
|
||||
if (window.webkitMediaStream) {
|
||||
newStream = new webkitMediaStream();
|
||||
if (newStream) {
|
||||
var tracks = (isVideo ? stream.getVideoTracks() : stream.getAudioTracks());
|
||||
|
||||
for (var i = 0; i < tracks.length; i++) {
|
||||
newStream.addTrack(tracks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// FIXME: this is duplicated with 'handleLocalStream' !!!
|
||||
if (stream) {
|
||||
newStream = stream;
|
||||
} else {
|
||||
newStream =
|
||||
new DummyMediaStream(isVideo ? "dummyVideo" : "dummyAudio");
|
||||
}
|
||||
}
|
||||
|
||||
return newStream;
|
||||
}
|
||||
else if (RTCBrowserType.isFirefox() || RTCBrowserType.isTemasysPluginUsed())
|
||||
{ // Firefox and Temasys plugin
|
||||
if (stream && stream.audioStream)
|
||||
audioStream = stream.audioStream;
|
||||
else
|
||||
audioStream = new DummyMediaStream("dummyAudio");
|
||||
|
||||
if (stream && stream.videoStream)
|
||||
videoStream = stream.videoStream;
|
||||
else
|
||||
videoStream = new DummyMediaStream("dummyVideo");
|
||||
}
|
||||
|
||||
var audioMuted = (usageOptions && usageOptions.audio === false),
|
||||
videoMuted = (usageOptions && usageOptions.video === false);
|
||||
|
||||
var audioGUM = (!usageOptions || usageOptions.audio !== false),
|
||||
videoGUM = (!usageOptions || usageOptions.video !== false);
|
||||
|
||||
return this.service.createLocalStreams(
|
||||
[{stream: audioStream, type: "audio", isMuted: audioMuted, isGUMStream: audioGUM, videoType: null},
|
||||
{stream: videoStream, type: "video", isMuted: videoMuted, isGUMStream: videoGUM, videoType: "camera"}]);
|
||||
};
|
||||
|
||||
function DummyMediaStream(id) {
|
||||
this.id = id;
|
||||
this.label = id;
|
||||
this.stop = function() { };
|
||||
this.getAudioTracks = function() { return []; };
|
||||
this.getVideoTracks = function() { return []; };
|
||||
}
|
||||
|
||||
RTCUtils.prototype.createStream = function(stream, isVideo) {
|
||||
var newStream = null;
|
||||
if (window.webkitMediaStream) {
|
||||
newStream = new webkitMediaStream();
|
||||
if (newStream) {
|
||||
var tracks = (isVideo ? stream.getVideoTracks() : stream.getAudioTracks());
|
||||
|
||||
for (var i = 0; i < tracks.length; i++) {
|
||||
newStream.addTrack(tracks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// FIXME: this is duplicated with 'handleLocalStream' !!!
|
||||
if (stream) {
|
||||
newStream = stream;
|
||||
} else {
|
||||
newStream =
|
||||
new DummyMediaStream(isVideo ? "dummyVideo" : "dummyAudio");
|
||||
}
|
||||
}
|
||||
|
||||
return newStream;
|
||||
};
|
||||
|
||||
module.exports = RTCUtils;
|
||||
|
|
|
@ -9,6 +9,7 @@ var transform = require("sdp-transform");
|
|||
var XMPPEvents = require("../../service/xmpp/XMPPEvents");
|
||||
var RTCBrowserType = require("../RTC/RTCBrowserType");
|
||||
var SSRCReplacement = require("./LocalSSRCReplacement");
|
||||
var RTC = require("../RTC/RTC");
|
||||
|
||||
// Jingle stuff
|
||||
function JingleSessionPC(me, sid, connection, service, eventEmitter) {
|
||||
|
@ -94,8 +95,8 @@ JingleSessionPC.prototype.doInitialize = function () {
|
|||
};
|
||||
this.peerconnection.onaddstream = function (event) {
|
||||
if (event.stream.id !== 'default') {
|
||||
console.log("REMOTE STREAM ADDED: ", event.stream , event.stream.id);
|
||||
self.remoteStreamAdded(event);
|
||||
console.log("REMOTE STREAM ADDED: ", event.stream , event.stream.id);
|
||||
self.remoteStreamAdded(event);
|
||||
} else {
|
||||
// This is a recvonly stream. Clients that implement Unified Plan,
|
||||
// such as Firefox use recvonly "streams/channels/tracks" for
|
||||
|
|
Loading…
Reference in New Issue