// globals.js if (typeof cordova !== 'undefined') { DetectRTC.isMobileDevice = true; DetectRTC.browser.name = 'Chrome'; } if (navigator && navigator.userAgent && navigator.userAgent.indexOf('Crosswalk') !== -1) { DetectRTC.isMobileDevice = true; DetectRTC.browser.name = 'Chrome'; } function fireEvent(obj, eventName, args) { if (typeof CustomEvent === 'undefined') { return; } var eventDetail = { arguments: args, __exposedProps__: args }; var event = new CustomEvent(eventName, eventDetail); obj.dispatchEvent(event); } function setHarkEvents(connection, streamEvent) { if (!streamEvent.stream || !streamEvent.stream.getAudioTracks || !streamEvent.stream.getAudioTracks().length) return; if (!connection || !streamEvent) { throw 'Both arguments are required.'; } if (!connection.onspeaking || !connection.onsilence) { return; } if (typeof hark === 'undefined') { throw 'hark.js not found.'; } hark(streamEvent.stream, { onspeaking: function() { connection.onspeaking(streamEvent); }, onsilence: function() { connection.onsilence(streamEvent); }, onvolumechange: function(volume, threshold) { if (!connection.onvolumechange) { return; } connection.onvolumechange(merge({ volume: volume, threshold: threshold }, streamEvent)); } }); } function setMuteHandlers(connection, streamEvent) { if (!streamEvent.stream || !streamEvent.stream || !streamEvent.stream.addEventListener) return; streamEvent.stream.addEventListener('mute', function(event) { event = connection.streamEvents[streamEvent.streamid]; event.session = { audio: event.muteType === 'audio', video: event.muteType === 'video' }; connection.onmute(event); }, false); streamEvent.stream.addEventListener('unmute', function(event) { event = connection.streamEvents[streamEvent.streamid]; event.session = { audio: event.unmuteType === 'audio', video: event.unmuteType === 'video' }; connection.onunmute(event); }, false); } function getRandomString() { if (window.crypto && window.crypto.getRandomValues && navigator.userAgent.indexOf('Safari') === -1) { var a = window.crypto.getRandomValues(new Uint32Array(3)), token = ''; for (var i = 0, l = a.length; i < l; i++) { token += a[i].toString(36); } return token; } else { return (Math.random() * new Date().getTime()).toString(36).replace(/\./g, ''); } } // Get HTMLAudioElement/HTMLVideoElement accordingly // todo: add API documentation for connection.autoCreateMediaElement function getRMCMediaElement(stream, callback, connection) { if (!connection.autoCreateMediaElement) { callback({}); return; } var isAudioOnly = false; if (!!stream.getVideoTracks && !stream.getVideoTracks().length && !stream.isVideo && !stream.isScreen) { isAudioOnly = true; } if (DetectRTC.browser.name === 'Firefox') { if (connection.session.video || connection.session.screen) { isAudioOnly = false; } } var mediaElement = document.createElement(isAudioOnly ? 'audio' : 'video'); mediaElement.srcObject = stream; try { mediaElement.setAttributeNode(document.createAttribute('autoplay')); mediaElement.setAttributeNode(document.createAttribute('playsinline')); mediaElement.setAttributeNode(document.createAttribute('controls')); } catch (e) { mediaElement.setAttribute('autoplay', true); mediaElement.setAttribute('playsinline', true); mediaElement.setAttribute('controls', true); } // http://goo.gl/WZ5nFl // Firefox don't yet support onended for any stream (remote/local) if (DetectRTC.browser.name === 'Firefox') { var streamEndedEvent = 'ended'; if ('oninactive' in mediaElement) { streamEndedEvent = 'inactive'; } mediaElement.addEventListener(streamEndedEvent, function() { // fireEvent(stream, streamEndedEvent, stream); currentUserMediaRequest.remove(stream.idInstance); if (stream.type === 'local') { streamEndedEvent = 'ended'; if ('oninactive' in stream) { streamEndedEvent = 'inactive'; } StreamsHandler.onSyncNeeded(stream.streamid, streamEndedEvent); connection.attachStreams.forEach(function(aStream, idx) { if (stream.streamid === aStream.streamid) { delete connection.attachStreams[idx]; } }); var newStreamsArray = []; connection.attachStreams.forEach(function(aStream) { if (aStream) { newStreamsArray.push(aStream); } }); connection.attachStreams = newStreamsArray; var streamEvent = connection.streamEvents[stream.streamid]; if (streamEvent) { connection.onstreamended(streamEvent); return; } if (this.parentNode) { this.parentNode.removeChild(this); } } }, false); } var played = mediaElement.play(); if (typeof played !== 'undefined') { var cbFired = false; setTimeout(function() { if (!cbFired) { cbFired = true; callback(mediaElement); } }, 1000); played.then(function() { if (cbFired) return; cbFired = true; callback(mediaElement); }).catch(function(error) { if (cbFired) return; cbFired = true; callback(mediaElement); }); } else { callback(mediaElement); } } // if IE if (!window.addEventListener) { window.addEventListener = function(el, eventName, eventHandler) { if (!el.attachEvent) { return; } el.attachEvent('on' + eventName, eventHandler); }; } function listenEventHandler(eventName, eventHandler) { window.removeEventListener(eventName, eventHandler); window.addEventListener(eventName, eventHandler, false); } window.attachEventListener = function(video, type, listener, useCapture) { video.addEventListener(type, listener, useCapture); }; function removeNullEntries(array) { var newArray = []; array.forEach(function(item) { if (item) { newArray.push(item); } }); return newArray; } function isData(session) { return !session.audio && !session.video && !session.screen && session.data; } function isNull(obj) { return typeof obj === 'undefined'; } function isString(obj) { return typeof obj === 'string'; } var MediaStream = window.MediaStream; if (typeof MediaStream === 'undefined' && typeof webkitMediaStream !== 'undefined') { MediaStream = webkitMediaStream; } /*global MediaStream:true */ if (typeof MediaStream !== 'undefined') { if (!('stop' in MediaStream.prototype)) { MediaStream.prototype.stop = function() { this.getTracks().forEach(function(track) { track.stop(); }); }; } } function isAudioPlusTab(connection, audioPlusTab) { if (connection.session.audio && connection.session.audio === 'two-way') { return false; } if (DetectRTC.browser.name === 'Firefox' && audioPlusTab !== false) { return true; } if (DetectRTC.browser.name !== 'Chrome' || DetectRTC.browser.version < 50) return false; if (typeof audioPlusTab === true) { return true; } if (typeof audioPlusTab === 'undefined' && connection.session.audio && connection.session.screen && !connection.session.video) { audioPlusTab = true; return true; } return false; } function getAudioScreenConstraints(screen_constraints) { if (DetectRTC.browser.name === 'Firefox') { return true; } if (DetectRTC.browser.name !== 'Chrome') return false; return { mandatory: { chromeMediaSource: screen_constraints.mandatory.chromeMediaSource, chromeMediaSourceId: screen_constraints.mandatory.chromeMediaSourceId } }; } window.iOSDefaultAudioOutputDevice = window.iOSDefaultAudioOutputDevice || 'speaker'; // earpiece or speaker if (typeof window.enableAdapter === 'undefined') { if (DetectRTC.browser.name === 'Firefox' && DetectRTC.browser.version >= 54) { window.enableAdapter = true; } if (DetectRTC.browser.name === 'Chrome' && DetectRTC.browser.version >= 60) { // window.enableAdapter = true; } if (typeof adapter !== 'undefined' && adapter.browserDetails && typeof adapter.browserDetails.browser === 'string') { window.enableAdapter = true; } } if (!window.enableAdapter) { if (typeof URL.createObjectURL === 'undefined') { URL.createObjectURL = function(stream) { return 'blob:https://' + document.domain + '/' + getRandomString(); }; } if (!('srcObject' in HTMLMediaElement.prototype)) { HTMLMediaElement.prototype.srcObject = function(stream) { if ('mozSrcObject' in this) { this.mozSrcObject = stream; return; } this.src = URL.createObjectURL(stream); }; } // need RTCPeerConnection shim here }