diff --git a/modules/RTC/DataChannels.js b/modules/RTC/DataChannels.js
deleted file mode 100644
index de0efa043..000000000
--- a/modules/RTC/DataChannels.js
+++ /dev/null
@@ -1,211 +0,0 @@
-/* global config, APP, Strophe */
-/* jshint -W101 */
-
-// cache datachannels to avoid garbage collection
-// https://code.google.com/p/chromium/issues/detail?id=405545
-var RTCEvents = require("../../service/RTC/RTCEvents");
-
-var _dataChannels = [];
-var eventEmitter = null;
-
-var DataChannels = {
- /**
- * Callback triggered by PeerConnection when new data channel is opened
- * on the bridge.
- * @param event the event info object.
- */
- onDataChannel: function (event) {
- var dataChannel = event.channel;
-
- dataChannel.onopen = function () {
- console.info("Data channel opened by the Videobridge!", dataChannel);
-
- // Code sample for sending string and/or binary data
- // Sends String message to the bridge
- //dataChannel.send("Hello bridge!");
- // Sends 12 bytes binary message to the bridge
- //dataChannel.send(new ArrayBuffer(12));
-
- eventEmitter.emit(RTCEvents.DATA_CHANNEL_OPEN);
- };
-
- dataChannel.onerror = function (error) {
- console.error("Data Channel Error:", error, dataChannel);
- };
-
- dataChannel.onmessage = function (event) {
- var data = event.data;
- // JSON
- var obj;
-
- try {
- obj = JSON.parse(data);
- }
- catch (e) {
- console.error(
- "Failed to parse data channel message as JSON: ",
- data,
- dataChannel);
- }
- if (('undefined' !== typeof(obj)) && (null !== obj)) {
- var colibriClass = obj.colibriClass;
-
- if ("DominantSpeakerEndpointChangeEvent" === colibriClass) {
- // Endpoint ID from the Videobridge.
- var dominantSpeakerEndpoint = obj.dominantSpeakerEndpoint;
-
- console.info(
- "Data channel new dominant speaker event: ",
- dominantSpeakerEndpoint);
- eventEmitter.emit(RTCEvents.DOMINANTSPEAKER_CHANGED, dominantSpeakerEndpoint);
- }
- else if ("InLastNChangeEvent" === colibriClass) {
- var oldValue = obj.oldValue;
- var newValue = obj.newValue;
- // Make sure that oldValue and newValue are of type boolean.
- var type;
-
- if ((type = typeof oldValue) !== 'boolean') {
- if (type === 'string') {
- oldValue = (oldValue == "true");
- } else {
- oldValue = Boolean(oldValue).valueOf();
- }
- }
- if ((type = typeof newValue) !== 'boolean') {
- if (type === 'string') {
- newValue = (newValue == "true");
- } else {
- newValue = Boolean(newValue).valueOf();
- }
- }
-
- eventEmitter.emit(RTCEvents.LASTN_CHANGED, oldValue, newValue);
- }
- else if ("LastNEndpointsChangeEvent" === colibriClass) {
- // The new/latest list of last-n endpoint IDs.
- var lastNEndpoints = obj.lastNEndpoints;
- // The list of endpoint IDs which are entering the list of
- // last-n at this time i.e. were not in the old list of last-n
- // endpoint IDs.
- var endpointsEnteringLastN = obj.endpointsEnteringLastN;
-
- console.info(
- "Data channel new last-n event: ",
- lastNEndpoints, endpointsEnteringLastN, obj);
- eventEmitter.emit(RTCEvents.LASTN_ENDPOINT_CHANGED,
- lastNEndpoints, endpointsEnteringLastN, obj);
- }
- else {
- console.debug("Data channel JSON-formatted message: ", obj);
- // The received message appears to be appropriately
- // formatted (i.e. is a JSON object which assigns a value to
- // the mandatory property colibriClass) so don't just
- // swallow it, expose it to public consumption.
- eventEmitter.emit("rtc.datachannel." + colibriClass, obj);
- }
- }
- };
-
- dataChannel.onclose = function () {
- console.info("The Data Channel closed", dataChannel);
- var idx = _dataChannels.indexOf(dataChannel);
- if (idx > -1)
- _dataChannels = _dataChannels.splice(idx, 1);
- };
- _dataChannels.push(dataChannel);
- },
-
- /**
- * Binds "ondatachannel" event listener to given PeerConnection instance.
- * @param peerConnection WebRTC peer connection instance.
- */
- init: function (peerConnection, emitter) {
- if(!config.openSctp)
- return;
-
- peerConnection.ondatachannel = this.onDataChannel;
- eventEmitter = emitter;
-
- // Sample code for opening new data channel from Jitsi Meet to the bridge.
- // Although it's not a requirement to open separate channels from both bridge
- // and peer as single channel can be used for sending and receiving data.
- // So either channel opened by the bridge or the one opened here is enough
- // for communication with the bridge.
- /*var dataChannelOptions =
- {
- reliable: true
- };
- var dataChannel
- = peerConnection.createDataChannel("myChannel", dataChannelOptions);
-
- // Can be used only when is in open state
- dataChannel.onopen = function ()
- {
- dataChannel.send("My channel !!!");
- };
- dataChannel.onmessage = function (event)
- {
- var msgData = event.data;
- console.info("Got My Data Channel Message:", msgData, dataChannel);
- };*/
- },
-
- handleSelectedEndpointEvent: function (userResource) {
- onXXXEndpointChanged("selected", userResource);
- },
- handlePinnedEndpointEvent: function (userResource) {
- onXXXEndpointChanged("pinned", userResource);
- },
-
- some: function (callback, thisArg) {
- if (_dataChannels && _dataChannels.length !== 0) {
- if (thisArg)
- return _dataChannels.some(callback, thisArg);
- else
- return _dataChannels.some(callback);
- } else {
- return false;
- }
- }
-};
-
-/**
- * Notifies Videobridge about a change in the value of a specific
- * endpoint-related property such as selected endpoint and pinnned endpoint.
- *
- * @param xxx the name of the endpoint-related property whose value changed
- * @param userResource the new value of the endpoint-related property after the
- * change
- */
-function onXXXEndpointChanged(xxx, userResource) {
- // Derive the correct words from xxx such as selected and Selected, pinned
- // and Pinned.
- var head = xxx.charAt(0);
- var tail = xxx.substring(1);
- var lower = head.toLowerCase() + tail;
- var upper = head.toUpperCase() + tail;
-
- // Notify Videobridge about the specified endpoint change.
- console.log(lower + ' endpoint changed: ', userResource);
- DataChannels.some(function (dataChannel) {
- if (dataChannel.readyState == 'open') {
- console.log(
- 'sending ' + lower
- + ' endpoint changed notification to the bridge: ',
- userResource);
-
- var jsonObject = {};
-
- jsonObject.colibriClass = (upper + 'EndpointChangedEvent');
- jsonObject[lower + "Endpoint"]
- = (userResource ? userResource : null);
- dataChannel.send(JSON.stringify(jsonObject));
-
- return true;
- }
- });
-}
-
-module.exports = DataChannels;
-
diff --git a/modules/RTC/LocalStream.js b/modules/RTC/LocalStream.js
deleted file mode 100644
index bf30305f1..000000000
--- a/modules/RTC/LocalStream.js
+++ /dev/null
@@ -1,145 +0,0 @@
-/* global APP */
-var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
-var RTCEvents = require("../../service/RTC/RTCEvents");
-var RTCBrowserType = require("./RTCBrowserType");
-var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js");
-
-/**
- * This implements 'onended' callback normally fired by WebRTC after the stream
- * is stopped. There is no such behaviour yet in FF, so we have to add it.
- * @param stream original WebRTC stream object to which 'onended' handling
- * will be added.
- */
-function implementOnEndedHandling(localStream) {
- var stream = localStream.getOriginalStream();
- var originalStop = stream.stop;
- stream.stop = function () {
- originalStop.apply(stream);
- if (localStream.isActive()) {
- stream.onended();
- }
- };
-}
-
-function LocalStream(stream, type, eventEmitter, videoType, isGUMStream) {
- this.stream = stream;
- this.eventEmitter = eventEmitter;
- this.type = type;
- this.videoType = videoType;
- this.isGUMStream = true;
- if(isGUMStream === false)
- this.isGUMStream = isGUMStream;
- var self = this;
- if (MediaStreamType.AUDIO_TYPE === type) {
- this.getTracks = function () {
- return self.stream.getAudioTracks();
- };
- } else {
- this.getTracks = function () {
- return self.stream.getVideoTracks();
- };
- }
-
- APP.RTC.addMediaStreamInactiveHandler(
- this.stream,
- function () {
- self.streamEnded();
- });
-
- if (RTCBrowserType.isFirefox()) {
- implementOnEndedHandling(this);
- }
-}
-
-LocalStream.prototype.streamEnded = function () {
- this.eventEmitter.emit(StreamEventTypes.EVENT_TYPE_LOCAL_ENDED, this);
-};
-
-LocalStream.prototype.getOriginalStream = function()
-{
- return this.stream;
-};
-
-LocalStream.prototype.isAudioStream = function () {
- return MediaStreamType.AUDIO_TYPE === this.type;
-};
-
-LocalStream.prototype.isVideoStream = function () {
- return MediaStreamType.VIDEO_TYPE === this.type;
-};
-
-LocalStream.prototype.setMute = function (mute)
-{
- var isAudio = this.isAudioStream();
- var eventType = isAudio ? RTCEvents.AUDIO_MUTE : RTCEvents.VIDEO_MUTE;
-
- if ((window.location.protocol != "https:" && this.isGUMStream) ||
- (isAudio && this.isGUMStream) || this.videoType === "screen" ||
- // FIXME FF does not support 'removeStream' method used to mute
- RTCBrowserType.isFirefox()) {
-
- var tracks = this.getTracks();
- for (var idx = 0; idx < tracks.length; idx++) {
- tracks[idx].enabled = !mute;
- }
- this.eventEmitter.emit(eventType, mute);
- } else {
- if (mute) {
- APP.xmpp.removeStream(this.stream);
- APP.RTC.stopMediaStream(this.stream);
- this.eventEmitter.emit(eventType, true);
- } else {
- var self = this;
- APP.RTC.rtcUtils.obtainAudioAndVideoPermissions(
- (this.isAudioStream() ? ["audio"] : ["video"]),
- function (stream) {
- if (isAudio) {
- APP.RTC.changeLocalAudio(stream,
- function () {
- self.eventEmitter.emit(eventType, false);
- });
- } else {
- APP.RTC.changeLocalVideo(stream, false,
- function () {
- self.eventEmitter.emit(eventType, false);
- });
- }
- });
- }
- }
-};
-
-LocalStream.prototype.isMuted = function () {
- var tracks = [];
- if (this.isAudioStream()) {
- tracks = this.stream.getAudioTracks();
- } else {
- if (!this.isActive())
- return true;
- tracks = this.stream.getVideoTracks();
- }
- for (var idx = 0; idx < tracks.length; idx++) {
- if(tracks[idx].enabled)
- return false;
- }
- return true;
-};
-
-LocalStream.prototype.getId = function () {
- return this.stream.getTracks()[0].id;
-};
-
-/**
- * Checks whether the MediaStream is avtive/not ended.
- * When there is no check for active we don't have information and so
- * will return that stream is active (in case of FF).
- * @returns {boolean} whether MediaStream is active.
- */
-LocalStream.prototype.isActive = function () {
- if((typeof this.stream.active !== "undefined"))
- return this.stream.active;
- else
- return true;
-};
-
-module.exports = LocalStream;
diff --git a/modules/RTC/MediaStream.js b/modules/RTC/MediaStream.js
deleted file mode 100644
index fc500781e..000000000
--- a/modules/RTC/MediaStream.js
+++ /dev/null
@@ -1,57 +0,0 @@
-var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
-
-/**
- * Creates a MediaStream object for the given data, session id and ssrc.
- * It is a wrapper class for the MediaStream.
- *
- * @param data the data object from which we obtain the stream,
- * the peerjid, etc.
- * @param ssrc the ssrc corresponding to this MediaStream
- * @param mute the whether this MediaStream is muted
- *
- * @constructor
- */
-function MediaStream(data, ssrc, browser, eventEmitter, muted, type) {
-
- // XXX(gp) to minimize headaches in the future, we should build our
- // abstractions around tracks and not streams. ORTC is track based API.
- // Mozilla expects m-lines to represent media tracks.
- //
- // Practically, what I'm saying is that we should have a MediaTrack class
- // and not a MediaStream class.
- //
- // Also, we should be able to associate multiple SSRCs with a MediaTrack as
- // a track might have an associated RTX and FEC sources.
-
- if (!type) {
- console.log("Errrm...some code needs an update...");
- }
-
- this.stream = data.stream;
- this.peerjid = data.peerjid;
- this.videoType = data.videoType;
- this.ssrc = ssrc;
- this.type = type;
- this.muted = muted;
- this.eventEmitter = eventEmitter;
-}
-
-// FIXME duplicated with LocalStream methods - extract base class
-MediaStream.prototype.isAudioStream = function () {
- return MediaStreamType.AUDIO_TYPE === this.type;
-};
-
-MediaStream.prototype.isVideoStream = function () {
- return MediaStreamType.VIDEO_TYPE === this.type;
-};
-
-MediaStream.prototype.getOriginalStream = function () {
- return this.stream;
-};
-
-MediaStream.prototype.setMute = function (value) {
- this.stream.muted = value;
- this.muted = value;
-};
-
-module.exports = MediaStream;
diff --git a/modules/RTC/RTC.js b/modules/RTC/RTC.js
deleted file mode 100644
index 790e81708..000000000
--- a/modules/RTC/RTC.js
+++ /dev/null
@@ -1,335 +0,0 @@
-/* global APP */
-var EventEmitter = require("events");
-var RTCBrowserType = require("./RTCBrowserType");
-var RTCUtils = require("./RTCUtils.js");
-var LocalStream = require("./LocalStream.js");
-var DataChannels = require("./DataChannels");
-var MediaStream = require("./MediaStream.js");
-var DesktopSharingEventTypes
- = require("../../service/desktopsharing/DesktopSharingEventTypes");
-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 eventEmitter = new EventEmitter();
-
-
-function getMediaStreamUsage()
-{
- var result = {
- audio: true,
- video: true
- };
-
- /** There are some issues with the desktop sharing
- * when this property is enabled.
- * WARNING: We must change the implementation to start video/audio if we
- * receive from the focus that the peer is not muted.
-
- var isSecureConnection = window.location.protocol == "https:";
-
- if(config.disableEarlyMediaPermissionRequests || !isSecureConnection)
- {
- result = {
- audio: false,
- video: false
- };
-
- }
- **/
-
- return result;
-}
-
-var RTC = {
- // Exposes DataChannels to public consumption (e.g. jitsi-meet-torture)
- // without the necessity to require the module.
- "DataChannels": DataChannels,
-
- rtcUtils: null,
- devices: {
- audio: true,
- video: true
- },
- remoteStreams: {},
- localAudio: null,
- localVideo: null,
- addStreamListener: function (listener, eventType) {
- eventEmitter.on(eventType, listener);
- },
- addListener: function (type, listener) {
- eventEmitter.on(type, listener);
- },
- removeStreamListener: function (listener, eventType) {
- if(!(eventType instanceof StreamEventTypes))
- throw "Illegal argument";
-
- eventEmitter.removeListener(eventType, listener);
- },
- createLocalStream: function (stream, type, change, videoType,
- isMuted, isGUMStream) {
-
- var localStream =
- new LocalStream(stream, type, eventEmitter, videoType, isGUMStream);
- if(isMuted === true)
- localStream.setMute(true);
-
- if (MediaStreamType.AUDIO_TYPE === type) {
- this.localAudio = localStream;
- } else {
- this.localVideo = localStream;
- }
- var eventType = StreamEventTypes.EVENT_TYPE_LOCAL_CREATED;
- if(change)
- eventType = StreamEventTypes.EVENT_TYPE_LOCAL_CHANGED;
-
- eventEmitter.emit(eventType, localStream, isMuted);
- return localStream;
- },
- createRemoteStream: function (data, ssrc) {
- var jid = data.peerjid || APP.xmpp.myJid();
-
- // check the video muted state from last stored presence if any
- var muted = false;
- var pres = APP.xmpp.getLastPresence(jid);
- if (pres && pres.videoMuted) {
- muted = pres.videoMuted;
- }
-
- var self = this;
- [MediaStreamType.AUDIO_TYPE, MediaStreamType.VIDEO_TYPE].forEach(
- function (type) {
- var tracks =
- type == MediaStreamType.AUDIO_TYPE
- ? data.stream.getAudioTracks() : data.stream.getVideoTracks();
- if (!tracks || !Array.isArray(tracks) || !tracks.length) {
- console.log("Not creating a(n) " + type + " stream: no tracks");
- return;
- }
-
- var remoteStream = new MediaStream(data, ssrc,
- RTCBrowserType.getBrowserType(), eventEmitter, muted, type);
-
- if (!self.remoteStreams[jid]) {
- self.remoteStreams[jid] = {};
- }
- self.remoteStreams[jid][type] = remoteStream;
- eventEmitter.emit(StreamEventTypes.EVENT_TYPE_REMOTE_CREATED,
- remoteStream);
- });
- },
- getPCConstraints: function () {
- return this.rtcUtils.pc_constraints;
- },
- getUserMediaWithConstraints:function(um, success_callback,
- failure_callback, resolution,
- bandwidth, fps, desktopStream)
- {
- return this.rtcUtils.getUserMediaWithConstraints(um, success_callback,
- failure_callback, resolution, bandwidth, fps, desktopStream);
- },
- attachMediaStream: function (elSelector, stream) {
- this.rtcUtils.attachMediaStream(elSelector, stream);
- },
- getStreamID: function (stream) {
- return this.rtcUtils.getStreamID(stream);
- },
- getVideoSrc: function (element) {
- return this.rtcUtils.getVideoSrc(element);
- },
- setVideoSrc: function (element, src) {
- this.rtcUtils.setVideoSrc(element, src);
- },
- getVideoElementName: function () {
- return RTCBrowserType.isTemasysPluginUsed() ? 'object' : 'video';
- },
- dispose: function() {
- if (this.rtcUtils) {
- this.rtcUtils = null;
- }
- },
- stop: function () {
- this.dispose();
- },
- start: function () {
- var self = this;
- APP.desktopsharing.addListener(
- DesktopSharingEventTypes.NEW_STREAM_CREATED,
- function (stream, isUsingScreenStream, callback) {
- self.changeLocalVideo(stream, isUsingScreenStream, callback);
- });
- APP.xmpp.addListener(XMPPEvents.CALL_INCOMING, function(event) {
- DataChannels.init(event.peerconnection, eventEmitter);
- });
- APP.UI.addListener(UIEvents.SELECTED_ENDPOINT,
- DataChannels.handleSelectedEndpointEvent);
- APP.UI.addListener(UIEvents.PINNED_ENDPOINT,
- DataChannels.handlePinnedEndpointEvent);
-
- // In case of IE we continue from 'onReady' callback
- // passed to RTCUtils constructor. It will be invoked by Temasys plugin
- // once it is initialized.
- var onReady = function () {
- eventEmitter.emit(RTCEvents.RTC_READY, true);
- self.rtcUtils.obtainAudioAndVideoPermissions(
- null, null, getMediaStreamUsage());
- };
-
- this.rtcUtils = new RTCUtils(this, eventEmitter, onReady);
-
- // Call onReady() if Temasys plugin is not used
- if (!RTCBrowserType.isTemasysPluginUsed()) {
- onReady();
- }
- },
- muteRemoteVideoStream: function (jid, value) {
- var stream;
-
- if(this.remoteStreams[jid] &&
- this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) {
- stream = this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE];
- }
-
- if(!stream)
- return true;
-
- if (value != stream.muted) {
- stream.setMute(value);
- return true;
- }
- return false;
- },
- changeLocalVideo: function (stream, isUsingScreenStream, callback) {
- var oldStream = this.localVideo.getOriginalStream();
- var type = (isUsingScreenStream ? "screen" : "camera");
- var localCallback = callback;
- if(this.localVideo.isMuted() && this.localVideo.videoType !== type) {
- localCallback = function() {
- APP.xmpp.setVideoMute(false, function(mute) {
- eventEmitter.emit(RTCEvents.VIDEO_MUTE, mute);
- });
-
- callback();
- };
- }
- // FIXME: Workaround for FF/IE/Safari
- if (stream && stream.videoStream) {
- stream = stream.videoStream;
- }
- var videoStream = this.rtcUtils.createStream(stream, true);
- this.localVideo =
- this.createLocalStream(videoStream, "video", true, type);
- // Stop the stream
- this.stopMediaStream(oldStream);
-
- APP.xmpp.switchStreams(videoStream, oldStream,localCallback);
- },
- changeLocalAudio: function (stream, callback) {
- var oldStream = this.localAudio.getOriginalStream();
- var newStream = this.rtcUtils.createStream(stream);
- this.localAudio
- = this.createLocalStream(
- newStream, MediaStreamType.AUDIO_TYPE, true);
- // Stop the stream
- this.stopMediaStream(oldStream);
- APP.xmpp.switchStreams(newStream, oldStream, callback, true);
- },
- isVideoMuted: function (jid) {
- if (jid === APP.xmpp.myJid()) {
- var localVideo = APP.RTC.localVideo;
- return (!localVideo || localVideo.isMuted());
- } else {
- if (!APP.RTC.remoteStreams[jid] ||
- !APP.RTC.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) {
- return null;
- }
- return APP.RTC.remoteStreams[jid][MediaStreamType.VIDEO_TYPE].muted;
- }
- },
- setVideoMute: function (mute, callback, options) {
- if (!this.localVideo)
- return;
-
- if (mute == APP.RTC.localVideo.isMuted())
- {
- APP.xmpp.sendVideoInfoPresence(mute);
- if (callback)
- callback(mute);
- }
- else
- {
- APP.RTC.localVideo.setMute(mute);
- APP.xmpp.setVideoMute(
- mute,
- callback,
- options);
- }
- },
- setDeviceAvailability: function (devices) {
- if(!devices)
- return;
- if(devices.audio === true || devices.audio === false)
- this.devices.audio = devices.audio;
- if(devices.video === true || devices.video === false)
- this.devices.video = devices.video;
- eventEmitter.emit(RTCEvents.AVAILABLE_DEVICES_CHANGED, this.devices);
- },
- /**
- * A method to handle stopping of the stream.
- * One point to handle the differences in various implementations.
- * @param mediaStream MediaStream object to stop.
- */
- stopMediaStream: function (mediaStream) {
- mediaStream.getTracks().forEach(function (track) {
- // stop() not supported with IE
- if (track.stop) {
- track.stop();
- }
- });
-
- // leave stop for implementation still using it
- if (mediaStream.stop) {
- mediaStream.stop();
- }
- },
- /**
- * Adds onended/inactive handler to a MediaStream.
- * @param mediaStream a MediaStream to attach onended/inactive handler
- * @param handler the handler
- */
- addMediaStreamInactiveHandler: function (mediaStream, handler) {
- if (mediaStream.addEventListener) {
- // chrome
- if(typeof mediaStream.active !== "undefined")
- mediaStream.oninactive = handler;
- else
- mediaStream.onended = handler;
- } else {
- // themasys
- mediaStream.attachEvent('ended', function () {
- handler(mediaStream);
- });
- }
- },
- /**
- * Removes onended/inactive handler.
- * @param mediaStream the MediaStream to remove the handler from.
- * @param handler the handler to remove.
- */
- removeMediaStreamInactiveHandler: function (mediaStream, handler) {
- if (mediaStream.removeEventListener) {
- // chrome
- if(typeof mediaStream.active !== "undefined")
- mediaStream.oninactive = null;
- else
- mediaStream.onended = null;
- } else {
- // themasys
- mediaStream.detachEvent('ended', handler);
- }
- }
-};
-
-module.exports = RTC;
diff --git a/modules/RTC/RTCUtils.js b/modules/RTC/RTCUtils.js
deleted file mode 100644
index 67872b76f..000000000
--- a/modules/RTC/RTCUtils.js
+++ /dev/null
@@ -1,574 +0,0 @@
-/* global APP, config, require, attachMediaStream, getUserMedia,
- RTCPeerConnection, webkitMediaStream, webkitURL, webkitRTCPeerConnection,
- mozRTCIceCandidate, mozRTCSessionDescription, mozRTCPeerConnection */
-/* jshint -W101 */
-var MediaStreamType = require("../../service/RTC/MediaStreamTypes");
-var RTCBrowserType = require("./RTCBrowserType");
-var Resolutions = require("../../service/RTC/Resolutions");
-var RTCEvents = require("../../service/RTC/RTCEvents");
-var AdapterJS = require("./adapter.screenshare");
-
-var currentResolution = null;
-
-function getPreviousResolution(resolution) {
- if(!Resolutions[resolution])
- return null;
- var order = Resolutions[resolution].order;
- var res = null;
- var resName = null;
- for(var i in Resolutions) {
- var tmp = Resolutions[i];
- if (!res || (res.order < tmp.order && tmp.order < order)) {
- resName = i;
- res = tmp;
- }
- }
- return resName;
-}
-
-function setResolutionConstraints(constraints, resolution) {
- var isAndroid = RTCBrowserType.isAndroid();
-
- if (Resolutions[resolution]) {
- constraints.video.mandatory.minWidth = Resolutions[resolution].width;
- constraints.video.mandatory.minHeight = Resolutions[resolution].height;
- }
- else if (isAndroid) {
- // FIXME can't remember if the purpose of this was to always request
- // low resolution on Android ? if yes it should be moved up front
- constraints.video.mandatory.minWidth = 320;
- constraints.video.mandatory.minHeight = 240;
- constraints.video.mandatory.maxFrameRate = 15;
- }
-
- if (constraints.video.mandatory.minWidth)
- constraints.video.mandatory.maxWidth =
- constraints.video.mandatory.minWidth;
- if (constraints.video.mandatory.minHeight)
- constraints.video.mandatory.maxHeight =
- constraints.video.mandatory.minHeight;
-}
-
-function getConstraints(um, resolution, bandwidth, fps, desktopStream) {
- var constraints = {audio: false, video: false};
-
- if (um.indexOf('video') >= 0) {
- // same behaviour as true
- constraints.video = { mandatory: {}, optional: [] };
-
- constraints.video.optional.push({ googLeakyBucket: true });
-
- setResolutionConstraints(constraints, resolution);
- }
- if (um.indexOf('audio') >= 0) {
- if (!RTCBrowserType.isFirefox()) {
- // same behaviour as true
- constraints.audio = { mandatory: {}, optional: []};
- // if it is good enough for hangouts...
- constraints.audio.optional.push(
- {googEchoCancellation: true},
- {googAutoGainControl: true},
- {googNoiseSupression: true},
- {googHighpassFilter: true},
- {googNoisesuppression2: true},
- {googEchoCancellation2: true},
- {googAutoGainControl2: true}
- );
- } else {
- constraints.audio = true;
- }
- }
- if (um.indexOf('screen') >= 0) {
- if (RTCBrowserType.isChrome()) {
- constraints.video = {
- mandatory: {
- chromeMediaSource: "screen",
- googLeakyBucket: true,
- maxWidth: window.screen.width,
- maxHeight: window.screen.height,
- maxFrameRate: 3
- },
- optional: []
- };
- } else if (RTCBrowserType.isTemasysPluginUsed()) {
- constraints.video = {
- optional: [
- {
- sourceId: AdapterJS.WebRTCPlugin.plugin.screensharingKey
- }
- ]
- };
- } else if (RTCBrowserType.isFirefox()) {
- constraints.video = {
- mozMediaSource: "window",
- mediaSource: "window"
- };
-
- } else {
- console.error(
- "'screen' WebRTC media source is supported only in Chrome" +
- " and with Temasys plugin");
- }
- }
- if (um.indexOf('desktop') >= 0) {
- constraints.video = {
- mandatory: {
- chromeMediaSource: "desktop",
- chromeMediaSourceId: desktopStream,
- googLeakyBucket: true,
- maxWidth: window.screen.width,
- maxHeight: window.screen.height,
- maxFrameRate: 3
- },
- optional: []
- };
- }
-
- if (bandwidth) {
- if (!constraints.video) {
- //same behaviour as true
- constraints.video = {mandatory: {}, optional: []};
- }
- constraints.video.optional.push({bandwidth: bandwidth});
- }
- if (fps) {
- // for some cameras it might be necessary to request 30fps
- // so they choose 30fps mjpg over 10fps yuy2
- if (!constraints.video) {
- // same behaviour as true;
- constraints.video = {mandatory: {}, optional: []};
- }
- constraints.video.mandatory.minFrameRate = fps;
- }
-
- // we turn audio for both audio and video tracks, the fake audio & video seems to work
- // only when enabled in one getUserMedia call, we cannot get fake audio separate by fake video
- // this later can be a problem with some of the tests
- if(RTCBrowserType.isFirefox() && config.firefox_fake_device)
- {
- constraints.audio = true;
- constraints.fake = true;
- }
-
- return constraints;
-}
-
-
-function RTCUtils(RTCService, eventEmitter, onTemasysPluginReady)
-{
- var self = this;
- this.service = RTCService;
- this.eventEmitter = eventEmitter;
- 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;
- }
- return APP.xmpp.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;
- };
- window.RTCSessionDescription = mozRTCSessionDescription;
- window.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 APP.xmpp.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 (RTCBrowserType.isAndroid()) {
- 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.webRTCReady(function (isPlugin) {
-
- self.peerconnection = RTCPeerConnection;
- self.getUserMedia = getUserMedia;
- self.attachMediaStream = function (elSel, stream) {
-
- if (stream.id === "dummyAudio" || stream.id === "dummyVideo") {
- return;
- }
-
- attachMediaStream(elSel[0], stream);
- };
- self.getStreamID = function (stream) {
- return APP.xmpp.filter_special_chars(stream.label);
- };
- 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;
- };
- 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);
- };
-
- 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;
-
- var constraints = getConstraints(
- um, resolution, bandwidth, fps, desktopStream);
-
- 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);
- self.eventEmitter.emit(RTCEvents.GET_USER_MEDIA_FAILED, error);
- if (failure_callback) {
- failure_callback(error);
- }
- });
- } catch (e) {
- console.error('GUM failed: ', e);
- self.eventEmitter.emit(RTCEvents.GET_USER_MEDIA_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, callback, usageOptions)
-{
- var self = this;
- // Get AV
-
- var successCallback = function (stream) {
- if(callback)
- callback(stream, usageOptions);
- else
- 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);
- },
- 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);
- }
- );
- };
- if (newDevices.indexOf('audio') !== -1) {
- obtainAudio();
- } else {
- obtainVideo(null);
- }
- } else {
- this.getUserMediaWithConstraints(
- newDevices,
- function (stream) {
- successCallback(stream);
- },
- function (error) {
- self.errorCallback(error);
- },
- config.resolution || '360');
- }
-};
-
-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);
- this.handleLocalStream(stream, usageOptions);
-};
-
-RTCUtils.prototype.errorCallback = function (error) {
- 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)
- {
- self.getUserMediaWithConstraints(['audio', 'video'],
- function (stream) {
- return self.successCallback(stream);
- }, function (error) {
- return self.errorCallback(error);
- }, resolution);
- }
- else {
- self.getUserMediaWithConstraints(
- ['audio'],
- function (stream) {
- return self.successCallback(stream);
- },
- function (error) {
- console.error('failed to obtain audio/video stream - stop',
- error);
- return self.successCallback(null);
- }
- );
- }
-};
-
-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.
- var audioStream, videoStream;
- if(window.webkitMediaStream)
- {
- audioStream = new webkitMediaStream();
- videoStream = new webkitMediaStream();
- if(stream) {
- var audioTracks = stream.getAudioTracks();
-
- for (var i = 0; i < audioTracks.length; i++) {
- audioStream.addTrack(audioTracks[i]);
- }
-
- var videoTracks = stream.getVideoTracks();
-
- for (i = 0; i < videoTracks.length; i++) {
- videoStream.addTrack(videoTracks[i]);
- }
- }
- }
- 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);
-
-
- this.service.createLocalStream(
- audioStream, MediaStreamType.AUDIO_TYPE, null, null,
- audioMuted, audioGUM);
-
- this.service.createLocalStream(
- videoStream, MediaStreamType.VIDEO_TYPE, null, 'camera',
- videoMuted, videoGUM);
-};
-
-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;
diff --git a/modules/RTC/adapter.screenshare.js b/modules/RTC/adapter.screenshare.js
deleted file mode 100644
index 345c9fb0b..000000000
--- a/modules/RTC/adapter.screenshare.js
+++ /dev/null
@@ -1,1168 +0,0 @@
-/*! adapterjs - v0.12.0 - 2015-09-04 */
-
-// Adapter's interface.
-var AdapterJS = AdapterJS || {};
-
-// Browserify compatibility
-if(typeof exports !== 'undefined') {
- module.exports = AdapterJS;
-}
-
-AdapterJS.options = AdapterJS.options || {};
-
-// uncomment to get virtual webcams
-// AdapterJS.options.getAllCams = true;
-
-// uncomment to prevent the install prompt when the plugin in not yet installed
-// AdapterJS.options.hidePluginInstallPrompt = true;
-
-// AdapterJS version
-AdapterJS.VERSION = '0.12.0';
-
-// This function will be called when the WebRTC API is ready to be used
-// Whether it is the native implementation (Chrome, Firefox, Opera) or
-// the plugin
-// You may Override this function to synchronise the start of your application
-// with the WebRTC API being ready.
-// If you decide not to override use this synchronisation, it may result in
-// an extensive CPU usage on the plugin start (once per tab loaded)
-// Params:
-// - isUsingPlugin: true is the WebRTC plugin is being used, false otherwise
-//
-AdapterJS.onwebrtcready = AdapterJS.onwebrtcready || function(isUsingPlugin) {
- // The WebRTC API is ready.
- // Override me and do whatever you want here
-};
-
-// Sets a callback function to be called when the WebRTC interface is ready.
-// The first argument is the function to callback.\
-// Throws an error if the first argument is not a function
-AdapterJS.webRTCReady = function (callback) {
- if (typeof callback !== 'function') {
- throw new Error('Callback provided is not a function');
- }
-
- if (true === AdapterJS.onwebrtcreadyDone) {
- // All WebRTC interfaces are ready, just call the callback
- callback(null !== AdapterJS.WebRTCPlugin.plugin);
- } else {
- // will be triggered automatically when your browser/plugin is ready.
- AdapterJS.onwebrtcready = callback;
- }
-};
-
-// Plugin namespace
-AdapterJS.WebRTCPlugin = AdapterJS.WebRTCPlugin || {};
-
-// The object to store plugin information
-AdapterJS.WebRTCPlugin.pluginInfo = {
- prefix : 'Tem',
- plugName : 'TemWebRTCPlugin',
- pluginId : 'plugin0',
- type : 'application/x-temwebrtcplugin',
- onload : '__TemWebRTCReady0',
- portalLink : 'http://skylink.io/plugin/',
- downloadLink : null, //set below
- companyName: 'Temasys'
-};
-if(!!navigator.platform.match(/^Mac/i)) {
- AdapterJS.WebRTCPlugin.pluginInfo.downloadLink = 'http://bit.ly/1n77hco';
-}
-else if(!!navigator.platform.match(/^Win/i)) {
- AdapterJS.WebRTCPlugin.pluginInfo.downloadLink = 'http://bit.ly/1kkS4FN';
-}
-
-AdapterJS.WebRTCPlugin.TAGS = {
- NONE : 'none',
- AUDIO : 'audio',
- VIDEO : 'video'
-};
-
-// Unique identifier of each opened page
-AdapterJS.WebRTCPlugin.pageId = Math.random().toString(36).slice(2);
-
-// Use this whenever you want to call the plugin.
-AdapterJS.WebRTCPlugin.plugin = null;
-
-// Set log level for the plugin once it is ready.
-// The different values are
-// This is an asynchronous function that will run when the plugin is ready
-AdapterJS.WebRTCPlugin.setLogLevel = null;
-
-// Defines webrtc's JS interface according to the plugin's implementation.
-// Define plugin Browsers as WebRTC Interface.
-AdapterJS.WebRTCPlugin.defineWebRTCInterface = null;
-
-// This function detects whether or not a plugin is installed.
-// Checks if Not IE (firefox, for example), else if it's IE,
-// we're running IE and do something. If not it is not supported.
-AdapterJS.WebRTCPlugin.isPluginInstalled = null;
-
- // Lets adapter.js wait until the the document is ready before injecting the plugin
-AdapterJS.WebRTCPlugin.pluginInjectionInterval = null;
-
-// Inject the HTML DOM object element into the page.
-AdapterJS.WebRTCPlugin.injectPlugin = null;
-
-// States of readiness that the plugin goes through when
-// being injected and stated
-AdapterJS.WebRTCPlugin.PLUGIN_STATES = {
- NONE : 0, // no plugin use
- INITIALIZING : 1, // Detected need for plugin
- INJECTING : 2, // Injecting plugin
- INJECTED: 3, // Plugin element injected but not usable yet
- READY: 4 // Plugin ready to be used
-};
-
-// Current state of the plugin. You cannot use the plugin before this is
-// equal to AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY
-AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.NONE;
-
-// True is AdapterJS.onwebrtcready was already called, false otherwise
-// Used to make sure AdapterJS.onwebrtcready is only called once
-AdapterJS.onwebrtcreadyDone = false;
-
-// Log levels for the plugin.
-// To be set by calling AdapterJS.WebRTCPlugin.setLogLevel
-/*
-Log outputs are prefixed in some cases.
- INFO: Information reported by the plugin.
- ERROR: Errors originating from within the plugin.
- WEBRTC: Error originating from within the libWebRTC library
-*/
-// From the least verbose to the most verbose
-AdapterJS.WebRTCPlugin.PLUGIN_LOG_LEVELS = {
- NONE : 'NONE',
- ERROR : 'ERROR',
- WARNING : 'WARNING',
- INFO: 'INFO',
- VERBOSE: 'VERBOSE',
- SENSITIVE: 'SENSITIVE'
-};
-
-// Does a waiting check before proceeding to load the plugin.
-AdapterJS.WebRTCPlugin.WaitForPluginReady = null;
-
-// This methid will use an interval to wait for the plugin to be ready.
-AdapterJS.WebRTCPlugin.callWhenPluginReady = null;
-
-// !!!! WARNING: DO NOT OVERRIDE THIS FUNCTION. !!!
-// This function will be called when plugin is ready. It sends necessary
-// details to the plugin.
-// The function will wait for the document to be ready and the set the
-// plugin state to AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY,
-// indicating that it can start being requested.
-// This function is not in the IE/Safari condition brackets so that
-// TemPluginLoaded function might be called on Chrome/Firefox.
-// This function is the only private function that is not encapsulated to
-// allow the plugin method to be called.
-__TemWebRTCReady0 = function () {
- if (document.readyState === 'complete') {
- AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY;
-
- AdapterJS.maybeThroughWebRTCReady();
- } else {
- AdapterJS.WebRTCPlugin.documentReadyInterval = setInterval(function () {
- if (document.readyState === 'complete') {
- // TODO: update comments, we wait for the document to be ready
- clearInterval(AdapterJS.WebRTCPlugin.documentReadyInterval);
- AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY;
-
- AdapterJS.maybeThroughWebRTCReady();
- }
- }, 100);
- }
-};
-
-AdapterJS.maybeThroughWebRTCReady = function() {
- if (!AdapterJS.onwebrtcreadyDone) {
- AdapterJS.onwebrtcreadyDone = true;
-
- if (typeof(AdapterJS.onwebrtcready) === 'function') {
- AdapterJS.onwebrtcready(AdapterJS.WebRTCPlugin.plugin !== null);
- }
- }
-};
-
-// Text namespace
-AdapterJS.TEXT = {
- PLUGIN: {
- REQUIRE_INSTALLATION: 'This website requires you to install a WebRTC-enabling plugin ' +
- 'to work on this browser.',
- NOT_SUPPORTED: 'Your browser does not support WebRTC.',
- BUTTON: 'Install Now'
- },
- REFRESH: {
- REQUIRE_REFRESH: 'Please refresh page',
- BUTTON: 'Refresh Page'
- }
-};
-
-// The result of ice connection states.
-// - starting: Ice connection is starting.
-// - checking: Ice connection is checking.
-// - connected Ice connection is connected.
-// - completed Ice connection is connected.
-// - done Ice connection has been completed.
-// - disconnected Ice connection has been disconnected.
-// - failed Ice connection has failed.
-// - closed Ice connection is closed.
-AdapterJS._iceConnectionStates = {
- starting : 'starting',
- checking : 'checking',
- connected : 'connected',
- completed : 'connected',
- done : 'completed',
- disconnected : 'disconnected',
- failed : 'failed',
- closed : 'closed'
-};
-
-//The IceConnection states that has been fired for each peer.
-AdapterJS._iceConnectionFiredStates = [];
-
-
-// Check if WebRTC Interface is defined.
-AdapterJS.isDefined = null;
-
-// This function helps to retrieve the webrtc detected browser information.
-// This sets:
-// - webrtcDetectedBrowser: The browser agent name.
-// - webrtcDetectedVersion: The browser version.
-// - webrtcDetectedType: The types of webRTC support.
-// - 'moz': Mozilla implementation of webRTC.
-// - 'webkit': WebKit implementation of webRTC.
-// - 'plugin': Using the plugin implementation.
-AdapterJS.parseWebrtcDetectedBrowser = function () {
- var hasMatch, checkMatch = navigator.userAgent.match(
- /(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
- if (/trident/i.test(checkMatch[1])) {
- hasMatch = /\brv[ :]+(\d+)/g.exec(navigator.userAgent) || [];
- webrtcDetectedBrowser = 'IE';
- webrtcDetectedVersion = parseInt(hasMatch[1] || '0', 10);
- } else if (checkMatch[1] === 'Chrome') {
- hasMatch = navigator.userAgent.match(/\bOPR\/(\d+)/);
- if (hasMatch !== null) {
- webrtcDetectedBrowser = 'opera';
- webrtcDetectedVersion = parseInt(hasMatch[1], 10);
- }
- }
- if (navigator.userAgent.indexOf('Safari')) {
- if (typeof InstallTrigger !== 'undefined') {
- webrtcDetectedBrowser = 'firefox';
- } else if (/*@cc_on!@*/ false || !!document.documentMode) {
- webrtcDetectedBrowser = 'IE';
- } else if (
- Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0) {
- webrtcDetectedBrowser = 'safari';
- } else if (!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) {
- webrtcDetectedBrowser = 'opera';
- } else if (!!window.chrome) {
- webrtcDetectedBrowser = 'chrome';
- }
- }
- if (!webrtcDetectedBrowser) {
- webrtcDetectedVersion = checkMatch[1];
- }
- if (!webrtcDetectedVersion) {
- try {
- checkMatch = (checkMatch[2]) ? [checkMatch[1], checkMatch[2]] :
- [navigator.appName, navigator.appVersion, '-?'];
- if ((hasMatch = navigator.userAgent.match(/version\/(\d+)/i)) !== null) {
- checkMatch.splice(1, 1, hasMatch[1]);
- }
- webrtcDetectedVersion = parseInt(checkMatch[1], 10);
- } catch (error) { }
- }
-};
-
-// To fix configuration as some browsers does not support
-// the 'urls' attribute.
-AdapterJS.maybeFixConfiguration = function (pcConfig) {
- if (pcConfig === null) {
- return;
- }
- for (var i = 0; i < pcConfig.iceServers.length; i++) {
- if (pcConfig.iceServers[i].hasOwnProperty('urls')) {
- pcConfig.iceServers[i].url = pcConfig.iceServers[i].urls;
- delete pcConfig.iceServers[i].urls;
- }
- }
-};
-
-AdapterJS.addEvent = function(elem, evnt, func) {
- if (elem.addEventListener) { // W3C DOM
- elem.addEventListener(evnt, func, false);
- } else if (elem.attachEvent) {// OLD IE DOM
- elem.attachEvent('on'+evnt, func);
- } else { // No much to do
- elem[evnt] = func;
- }
-};
-
-AdapterJS.renderNotificationBar = function (text, buttonText, buttonLink, openNewTab, displayRefreshBar) {
- // only inject once the page is ready
- if (document.readyState !== 'complete') {
- return;
- }
-
- var w = window;
- var i = document.createElement('iframe');
- i.style.position = 'fixed';
- i.style.top = '-41px';
- i.style.left = 0;
- i.style.right = 0;
- i.style.width = '100%';
- i.style.height = '40px';
- i.style.backgroundColor = '#ffffe1';
- i.style.border = 'none';
- i.style.borderBottom = '1px solid #888888';
- i.style.zIndex = '9999999';
- if(typeof i.style.webkitTransition === 'string') {
- i.style.webkitTransition = 'all .5s ease-out';
- } else if(typeof i.style.transition === 'string') {
- i.style.transition = 'all .5s ease-out';
- }
- document.body.appendChild(i);
- c = (i.contentWindow) ? i.contentWindow :
- (i.contentDocument.document) ? i.contentDocument.document : i.contentDocument;
- c.document.open();
- c.document.write('' + text + '');
- if(buttonText && buttonLink) {
- c.document.write('');
- c.document.close();
-
- // On click on okay
- AdapterJS.addEvent(c.document.getElementById('okay'), 'click', function(e) {
- if (!!displayRefreshBar) {
- AdapterJS.renderNotificationBar(AdapterJS.TEXT.EXTENSION ?
- AdapterJS.TEXT.EXTENSION.REQUIRE_REFRESH : AdapterJS.TEXT.REFRESH.REQUIRE_REFRESH,
- AdapterJS.TEXT.REFRESH.BUTTON, 'javascript:location.reload()');
- }
- window.open(buttonLink, !!openNewTab ? '_blank' : '_top');
-
- e.preventDefault();
- try {
- event.cancelBubble = true;
- } catch(error) { }
-
- var pluginInstallInterval = setInterval(function(){
- if(! isIE) {
- navigator.plugins.refresh(false);
- }
- AdapterJS.WebRTCPlugin.isPluginInstalled(
- AdapterJS.WebRTCPlugin.pluginInfo.prefix,
- AdapterJS.WebRTCPlugin.pluginInfo.plugName,
- function() { // plugin now installed
- clearInterval(pluginInstallInterval);
- AdapterJS.WebRTCPlugin.defineWebRTCInterface();
- },
- function() {
- // still no plugin detected, nothing to do
- });
- } , 500);
- });
-
- // On click on Cancel
- AdapterJS.addEvent(c.document.getElementById('cancel'), 'click', function(e) {
- w.document.body.removeChild(i);
- });
- } else {
- c.document.close();
- }
- setTimeout(function() {
- if(typeof i.style.webkitTransform === 'string') {
- i.style.webkitTransform = 'translateY(40px)';
- } else if(typeof i.style.transform === 'string') {
- i.style.transform = 'translateY(40px)';
- } else {
- i.style.top = '0px';
- }
- }, 300);
-};
-
-// -----------------------------------------------------------
-// Detected webrtc implementation. Types are:
-// - 'moz': Mozilla implementation of webRTC.
-// - 'webkit': WebKit implementation of webRTC.
-// - 'plugin': Using the plugin implementation.
-webrtcDetectedType = null;
-
-// Detected webrtc datachannel support. Types are:
-// - 'SCTP': SCTP datachannel support.
-// - 'RTP': RTP datachannel support.
-webrtcDetectedDCSupport = null;
-
-// Set the settings for creating DataChannels, MediaStream for
-// Cross-browser compability.
-// - This is only for SCTP based support browsers.
-// the 'urls' attribute.
-checkMediaDataChannelSettings =
- function (peerBrowserAgent, peerBrowserVersion, callback, constraints) {
- if (typeof callback !== 'function') {
- return;
- }
- var beOfferer = true;
- var isLocalFirefox = webrtcDetectedBrowser === 'firefox';
- // Nightly version does not require MozDontOfferDataChannel for interop
- var isLocalFirefoxInterop = webrtcDetectedType === 'moz' && webrtcDetectedVersion > 30;
- var isPeerFirefox = peerBrowserAgent === 'firefox';
- var isPeerFirefoxInterop = peerBrowserAgent === 'firefox' &&
- ((peerBrowserVersion) ? (peerBrowserVersion > 30) : false);
-
- // Resends an updated version of constraints for MozDataChannel to work
- // If other userAgent is firefox and user is firefox, remove MozDataChannel
- if ((isLocalFirefox && isPeerFirefox) || (isLocalFirefoxInterop)) {
- try {
- delete constraints.mandatory.MozDontOfferDataChannel;
- } catch (error) {
- console.error('Failed deleting MozDontOfferDataChannel');
- console.error(error);
- }
- } else if ((isLocalFirefox && !isPeerFirefox)) {
- constraints.mandatory.MozDontOfferDataChannel = true;
- }
- if (!isLocalFirefox) {
- // temporary measure to remove Moz* constraints in non Firefox browsers
- for (var prop in constraints.mandatory) {
- if (constraints.mandatory.hasOwnProperty(prop)) {
- if (prop.indexOf('Moz') !== -1) {
- delete constraints.mandatory[prop];
- }
- }
- }
- }
- // Firefox (not interopable) cannot offer DataChannel as it will cause problems to the
- // interopability of the media stream
- if (isLocalFirefox && !isPeerFirefox && !isLocalFirefoxInterop) {
- beOfferer = false;
- }
- callback(beOfferer, constraints);
-};
-
-// Handles the differences for all browsers ice connection state output.
-// - Tested outcomes are:
-// - Chrome (offerer) : 'checking' > 'completed' > 'completed'
-// - Chrome (answerer) : 'checking' > 'connected'
-// - Firefox (offerer) : 'checking' > 'connected'
-// - Firefox (answerer): 'checking' > 'connected'
-checkIceConnectionState = function (peerId, iceConnectionState, callback) {
- if (typeof callback !== 'function') {
- console.warn('No callback specified in checkIceConnectionState. Aborted.');
- return;
- }
- peerId = (peerId) ? peerId : 'peer';
-
- if (!AdapterJS._iceConnectionFiredStates[peerId] ||
- iceConnectionState === AdapterJS._iceConnectionStates.disconnected ||
- iceConnectionState === AdapterJS._iceConnectionStates.failed ||
- iceConnectionState === AdapterJS._iceConnectionStates.closed) {
- AdapterJS._iceConnectionFiredStates[peerId] = [];
- }
- iceConnectionState = AdapterJS._iceConnectionStates[iceConnectionState];
- if (AdapterJS._iceConnectionFiredStates[peerId].indexOf(iceConnectionState) < 0) {
- AdapterJS._iceConnectionFiredStates[peerId].push(iceConnectionState);
- if (iceConnectionState === AdapterJS._iceConnectionStates.connected) {
- setTimeout(function () {
- AdapterJS._iceConnectionFiredStates[peerId]
- .push(AdapterJS._iceConnectionStates.done);
- callback(AdapterJS._iceConnectionStates.done);
- }, 1000);
- }
- callback(iceConnectionState);
- }
- return;
-};
-
-// Firefox:
-// - Creates iceServer from the url for Firefox.
-// - Create iceServer with stun url.
-// - Create iceServer with turn url.
-// - Ignore the transport parameter from TURN url for FF version <=27.
-// - Return null for createIceServer if transport=tcp.
-// - FF 27 and above supports transport parameters in TURN url,
-// - So passing in the full url to create iceServer.
-// Chrome:
-// - Creates iceServer from the url for Chrome M33 and earlier.
-// - Create iceServer with stun url.
-// - Chrome M28 & above uses below TURN format.
-// Plugin:
-// - Creates Ice Server for Plugin Browsers
-// - If Stun - Create iceServer with stun url.
-// - Else - Create iceServer with turn url
-// - This is a WebRTC Function
-createIceServer = null;
-
-// Firefox:
-// - Creates IceServers for Firefox
-// - Use .url for FireFox.
-// - Multiple Urls support
-// Chrome:
-// - Creates iceServers from the urls for Chrome M34 and above.
-// - .urls is supported since Chrome M34.
-// - Multiple Urls support
-// Plugin:
-// - Creates Ice Servers for Plugin Browsers
-// - Multiple Urls support
-// - This is a WebRTC Function
-createIceServers = null;
-//------------------------------------------------------------
-
-//The RTCPeerConnection object.
-RTCPeerConnection = null;
-
-// Creates RTCSessionDescription object for Plugin Browsers
-RTCSessionDescription = (typeof RTCSessionDescription === 'function') ?
- RTCSessionDescription : null;
-
-// Creates RTCIceCandidate object for Plugin Browsers
-RTCIceCandidate = (typeof RTCIceCandidate === 'function') ?
- RTCIceCandidate : null;
-
-// Get UserMedia (only difference is the prefix).
-// Code from Adam Barth.
-getUserMedia = null;
-
-// Attach a media stream to an element.
-attachMediaStream = null;
-
-// Re-attach a media stream to an element.
-reattachMediaStream = null;
-
-
-// Detected browser agent name. Types are:
-// - 'firefox': Firefox browser.
-// - 'chrome': Chrome browser.
-// - 'opera': Opera browser.
-// - 'safari': Safari browser.
-// - 'IE' - Internet Explorer browser.
-webrtcDetectedBrowser = null;
-
-// Detected browser version.
-webrtcDetectedVersion = null;
-
-// Check for browser types and react accordingly
-if (navigator.mozGetUserMedia) {
- webrtcDetectedBrowser = 'firefox';
- webrtcDetectedVersion = parseInt(navigator
- .userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
- webrtcDetectedType = 'moz';
- webrtcDetectedDCSupport = 'SCTP';
-
- RTCPeerConnection = function (pcConfig, pcConstraints) {
- AdapterJS.maybeFixConfiguration(pcConfig);
- return new mozRTCPeerConnection(pcConfig, pcConstraints);
- };
-
- // The RTCSessionDescription object.
- RTCSessionDescription = mozRTCSessionDescription;
- window.RTCSessionDescription = RTCSessionDescription;
-
- // The RTCIceCandidate object.
- RTCIceCandidate = mozRTCIceCandidate;
- window.RTCIceCandidate = RTCIceCandidate;
-
- window.getUserMedia = navigator.mozGetUserMedia.bind(navigator);
- navigator.getUserMedia = window.getUserMedia;
-
- // Shim for MediaStreamTrack.getSources.
- MediaStreamTrack.getSources = function(successCb) {
- setTimeout(function() {
- var infos = [
- { kind: 'audio', id: 'default', label:'', facing:'' },
- { kind: 'video', id: 'default', label:'', facing:'' }
- ];
- successCb(infos);
- }, 0);
- };
-
- createIceServer = function (url, username, password) {
- var iceServer = null;
- var url_parts = url.split(':');
- if (url_parts[0].indexOf('stun') === 0) {
- iceServer = { url : url };
- } else if (url_parts[0].indexOf('turn') === 0) {
- if (webrtcDetectedVersion < 27) {
- var turn_url_parts = url.split('?');
- if (turn_url_parts.length === 1 ||
- turn_url_parts[1].indexOf('transport=udp') === 0) {
- iceServer = {
- url : turn_url_parts[0],
- credential : password,
- username : username
- };
- }
- } else {
- iceServer = {
- url : url,
- credential : password,
- username : username
- };
- }
- }
- return iceServer;
- };
-
- createIceServers = function (urls, username, password) {
- var iceServers = [];
- for (i = 0; i < urls.length; i++) {
- var iceServer = createIceServer(urls[i], username, password);
- if (iceServer !== null) {
- iceServers.push(iceServer);
- }
- }
- return iceServers;
- };
-
- attachMediaStream = function (element, stream) {
- element.mozSrcObject = stream;
- if (stream !== null)
- element.play();
-
- return element;
- };
-
- reattachMediaStream = function (to, from) {
- to.mozSrcObject = from.mozSrcObject;
- to.play();
- return to;
- };
-
- MediaStreamTrack.getSources = MediaStreamTrack.getSources || function (callback) {
- if (!callback) {
- throw new TypeError('Failed to execute \'getSources\' on \'MediaStreamTrack\'' +
- ': 1 argument required, but only 0 present.');
- }
- return callback([]);
- };
-
- // Fake get{Video,Audio}Tracks
- if (!MediaStream.prototype.getVideoTracks) {
- MediaStream.prototype.getVideoTracks = function () {
- return [];
- };
- }
- if (!MediaStream.prototype.getAudioTracks) {
- MediaStream.prototype.getAudioTracks = function () {
- return [];
- };
- }
-
- AdapterJS.maybeThroughWebRTCReady();
-} else if (navigator.webkitGetUserMedia) {
- webrtcDetectedBrowser = 'chrome';
- webrtcDetectedType = 'webkit';
- webrtcDetectedVersion = parseInt(navigator
- .userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
- // check if browser is opera 20+
- var checkIfOpera = navigator.userAgent.match(/\bOPR\/(\d+)/);
- if (checkIfOpera !== null) {
- webrtcDetectedBrowser = 'opera';
- webrtcDetectedVersion = parseInt(checkIfOpera[1], 10);
- }
- // check browser datachannel support
- if ((webrtcDetectedBrowser === 'chrome' && webrtcDetectedVersion >= 31) ||
- (webrtcDetectedBrowser === 'opera' && webrtcDetectedVersion >= 20)) {
- webrtcDetectedDCSupport = 'SCTP';
- } else if (webrtcDetectedBrowser === 'chrome' && webrtcDetectedVersion < 30 &&
- webrtcDetectedVersion > 24) {
- webrtcDetectedDCSupport = 'RTP';
- } else {
- webrtcDetectedDCSupport = '';
- }
-
- createIceServer = function (url, username, password) {
- var iceServer = null;
- var url_parts = url.split(':');
- if (url_parts[0].indexOf('stun') === 0) {
- iceServer = { 'url' : url };
- } else if (url_parts[0].indexOf('turn') === 0) {
- iceServer = {
- 'url' : url,
- 'credential' : password,
- 'username' : username
- };
- }
- return iceServer;
- };
-
- createIceServers = function (urls, username, password) {
- var iceServers = [];
- if (webrtcDetectedVersion >= 34) {
- iceServers = {
- 'urls' : urls,
- 'credential' : password,
- 'username' : username
- };
- } else {
- for (i = 0; i < urls.length; i++) {
- var iceServer = createIceServer(urls[i], username, password);
- if (iceServer !== null) {
- iceServers.push(iceServer);
- }
- }
- }
- return iceServers;
- };
-
- RTCPeerConnection = function (pcConfig, pcConstraints) {
- if (webrtcDetectedVersion < 34) {
- AdapterJS.maybeFixConfiguration(pcConfig);
- }
- return new webkitRTCPeerConnection(pcConfig, pcConstraints);
- };
-
- window.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
- navigator.getUserMedia = window.getUserMedia;
-
- attachMediaStream = function (element, stream) {
- if (typeof element.srcObject !== 'undefined') {
- element.srcObject = stream;
- } else if (typeof element.mozSrcObject !== 'undefined') {
- element.mozSrcObject = stream;
- } else if (typeof element.src !== 'undefined') {
- element.src = (stream === null ? '' : URL.createObjectURL(stream));
- } else {
- console.log('Error attaching stream to element.');
- }
- return element;
- };
-
- reattachMediaStream = function (to, from) {
- to.src = from.src;
- return to;
- };
-
- AdapterJS.maybeThroughWebRTCReady();
-} else if (navigator.mediaDevices && navigator.userAgent.match(
- /Edge\/(\d+).(\d+)$/)) {
- webrtcDetectedBrowser = 'edge';
-
- webrtcDetectedVersion =
- parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2], 10);
-
- // the minimum version still supported by adapter.
- webrtcMinimumVersion = 12;
-
- window.getUserMedia = navigator.getUserMedia.bind(navigator);
-
- attachMediaStream = function(element, stream) {
- element.srcObject = stream;
- return element;
- };
- reattachMediaStream = function(to, from) {
- to.srcObject = from.srcObject;
- return to;
- };
-
- AdapterJS.maybeThroughWebRTCReady();
-} else { // TRY TO USE PLUGIN
- // IE 9 is not offering an implementation of console.log until you open a console
- if (typeof console !== 'object' || typeof console.log !== 'function') {
- /* jshint -W020 */
- console = {} || console;
- // Implemented based on console specs from MDN
- // You may override these functions
- console.log = function (arg) {};
- console.info = function (arg) {};
- console.error = function (arg) {};
- console.dir = function (arg) {};
- console.exception = function (arg) {};
- console.trace = function (arg) {};
- console.warn = function (arg) {};
- console.count = function (arg) {};
- console.debug = function (arg) {};
- console.count = function (arg) {};
- console.time = function (arg) {};
- console.timeEnd = function (arg) {};
- console.group = function (arg) {};
- console.groupCollapsed = function (arg) {};
- console.groupEnd = function (arg) {};
- /* jshint +W020 */
- }
- webrtcDetectedType = 'plugin';
- webrtcDetectedDCSupport = 'plugin';
- AdapterJS.parseWebrtcDetectedBrowser();
- isIE = webrtcDetectedBrowser === 'IE';
-
- /* jshint -W035 */
- AdapterJS.WebRTCPlugin.WaitForPluginReady = function() {
- while (AdapterJS.WebRTCPlugin.pluginState !== AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {
- /* empty because it needs to prevent the function from running. */
- }
- };
- /* jshint +W035 */
-
- AdapterJS.WebRTCPlugin.callWhenPluginReady = function (callback) {
- if (AdapterJS.WebRTCPlugin.pluginState === AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {
- // Call immediately if possible
- // Once the plugin is set, the code will always take this path
- callback();
- } else {
- // otherwise start a 100ms interval
- var checkPluginReadyState = setInterval(function () {
- if (AdapterJS.WebRTCPlugin.pluginState === AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {
- clearInterval(checkPluginReadyState);
- callback();
- }
- }, 100);
- }
- };
-
- AdapterJS.WebRTCPlugin.setLogLevel = function(logLevel) {
- AdapterJS.WebRTCPlugin.callWhenPluginReady(function() {
- AdapterJS.WebRTCPlugin.plugin.setLogLevel(logLevel);
- });
- };
-
- AdapterJS.WebRTCPlugin.injectPlugin = function () {
- // only inject once the page is ready
- if (document.readyState !== 'complete') {
- return;
- }
-
- // Prevent multiple injections
- if (AdapterJS.WebRTCPlugin.pluginState !== AdapterJS.WebRTCPlugin.PLUGIN_STATES.INITIALIZING) {
- return;
- }
-
- AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.INJECTING;
-
- if (webrtcDetectedBrowser === 'IE' && webrtcDetectedVersion <= 10) {
- var frag = document.createDocumentFragment();
- AdapterJS.WebRTCPlugin.plugin = document.createElement('div');
- AdapterJS.WebRTCPlugin.plugin.innerHTML = '';
- while (AdapterJS.WebRTCPlugin.plugin.firstChild) {
- frag.appendChild(AdapterJS.WebRTCPlugin.plugin.firstChild);
- }
- document.body.appendChild(frag);
-
- // Need to re-fetch the plugin
- AdapterJS.WebRTCPlugin.plugin =
- document.getElementById(AdapterJS.WebRTCPlugin.pluginInfo.pluginId);
- } else {
- // Load Plugin
- AdapterJS.WebRTCPlugin.plugin = document.createElement('object');
- AdapterJS.WebRTCPlugin.plugin.id =
- AdapterJS.WebRTCPlugin.pluginInfo.pluginId;
- // IE will only start the plugin if it's ACTUALLY visible
- if (isIE) {
- AdapterJS.WebRTCPlugin.plugin.width = '1px';
- AdapterJS.WebRTCPlugin.plugin.height = '1px';
- } else { // The size of the plugin on Safari should be 0x0px
- // so that the autorisation prompt is at the top
- AdapterJS.WebRTCPlugin.plugin.width = '0px';
- AdapterJS.WebRTCPlugin.plugin.height = '0px';
- }
- AdapterJS.WebRTCPlugin.plugin.type = AdapterJS.WebRTCPlugin.pluginInfo.type;
- AdapterJS.WebRTCPlugin.plugin.innerHTML = '' +
- '' +
- ' ' +
- (AdapterJS.options.getAllCams ? '':'') +
- '' +
- '';
- document.body.appendChild(AdapterJS.WebRTCPlugin.plugin);
- }
-
-
- AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.INJECTED;
- };
-
- AdapterJS.WebRTCPlugin.isPluginInstalled =
- function (comName, plugName, installedCb, notInstalledCb) {
- if (!isIE) {
- var pluginArray = navigator.plugins;
- for (var i = 0; i < pluginArray.length; i++) {
- if (pluginArray[i].name.indexOf(plugName) >= 0) {
- installedCb();
- return;
- }
- }
- notInstalledCb();
- } else {
- try {
- var axo = new ActiveXObject(comName + '.' + plugName);
- } catch (e) {
- notInstalledCb();
- return;
- }
- installedCb();
- }
- };
-
- AdapterJS.WebRTCPlugin.defineWebRTCInterface = function () {
- if (AdapterJS.WebRTCPlugin.pluginState ===
- AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {
- console.error("AdapterJS - WebRTC interface has already been defined");
- return;
- }
-
- AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.INITIALIZING;
-
- AdapterJS.isDefined = function (variable) {
- return variable !== null && variable !== undefined;
- };
-
- createIceServer = function (url, username, password) {
- var iceServer = null;
- var url_parts = url.split(':');
- if (url_parts[0].indexOf('stun') === 0) {
- iceServer = {
- 'url' : url,
- 'hasCredentials' : false
- };
- } else if (url_parts[0].indexOf('turn') === 0) {
- iceServer = {
- 'url' : url,
- 'hasCredentials' : true,
- 'credential' : password,
- 'username' : username
- };
- }
- return iceServer;
- };
-
- createIceServers = function (urls, username, password) {
- var iceServers = [];
- for (var i = 0; i < urls.length; ++i) {
- iceServers.push(createIceServer(urls[i], username, password));
- }
- return iceServers;
- };
-
- RTCSessionDescription = function (info) {
- AdapterJS.WebRTCPlugin.WaitForPluginReady();
- return AdapterJS.WebRTCPlugin.plugin.
- ConstructSessionDescription(info.type, info.sdp);
- };
-
- RTCPeerConnection = function (servers, constraints) {
- var iceServers = null;
- if (servers) {
- iceServers = servers.iceServers;
- for (var i = 0; i < iceServers.length; i++) {
- if (iceServers[i].urls && !iceServers[i].url) {
- iceServers[i].url = iceServers[i].urls;
- }
- iceServers[i].hasCredentials = AdapterJS.
- isDefined(iceServers[i].username) &&
- AdapterJS.isDefined(iceServers[i].credential);
- }
- }
- var mandatory = (constraints && constraints.mandatory) ?
- constraints.mandatory : null;
- var optional = (constraints && constraints.optional) ?
- constraints.optional : null;
-
- AdapterJS.WebRTCPlugin.WaitForPluginReady();
- return AdapterJS.WebRTCPlugin.plugin.
- PeerConnection(AdapterJS.WebRTCPlugin.pageId,
- iceServers, mandatory, optional);
- };
-
- MediaStreamTrack = {};
- MediaStreamTrack.getSources = function (callback) {
- AdapterJS.WebRTCPlugin.callWhenPluginReady(function() {
- AdapterJS.WebRTCPlugin.plugin.GetSources(callback);
- });
- };
-
- window.getUserMedia = function (constraints, successCallback, failureCallback) {
- constraints.audio = constraints.audio || false;
- constraints.video = constraints.video || false;
-
- AdapterJS.WebRTCPlugin.callWhenPluginReady(function() {
- AdapterJS.WebRTCPlugin.plugin.
- getUserMedia(constraints, successCallback, failureCallback);
- });
- };
- window.navigator.getUserMedia = window.getUserMedia;
-
- attachMediaStream = function (element, stream) {
- if (!element || !element.parentNode) {
- return;
- }
-
- var streamId
- if (stream === null) {
- streamId = '';
- }
- else {
- stream.enableSoundTracks(true); // TODO: remove on 0.12.0
- streamId = stream.id;
- }
-
- var elementId = element.id.length === 0 ? Math.random().toString(36).slice(2) : element.id;
- var nodeName = element.nodeName.toLowerCase();
- if (nodeName !== 'object') { // not a plugin