diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexFlashToSipTranscoderImp.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexFlashToSipTranscoderImp.java index 7a7371ec68..3c52546801 100755 --- a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexFlashToSipTranscoderImp.java +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexFlashToSipTranscoderImp.java @@ -19,6 +19,11 @@ package org.bigbluebutton.voiceconf.red5.media.transcoder; import java.util.Random; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; import org.bigbluebutton.voiceconf.red5.media.FlashToSipAudioStream.TranscodedAudioListener; import org.red5.app.sip.codecs.Codec; @@ -36,9 +41,16 @@ public class SpeexFlashToSipTranscoderImp implements FlashToSipTranscoder { private Codec audioCodec; private long timestamp = 0; private final static int TS_INCREMENT = 320; // Determined from PCAP traces. + + private final Executor exec = Executors.newSingleThreadExecutor(); + private Runnable audioDataProcessor; + private volatile boolean processAudioData = false; + private BlockingQueue audioDataQ; + private TranscodedAudioListener transcodedAudioListener; public SpeexFlashToSipTranscoderImp(Codec audioCodec) { + audioDataQ = new LinkedBlockingQueue(); this.audioCodec = audioCodec; Random rgen = new Random(); timestamp = rgen.nextInt(1000); @@ -49,7 +61,13 @@ public class SpeexFlashToSipTranscoderImp implements FlashToSipTranscoder { // Just copy the audio data removing the codec id which is the first-byte // represented by the startOffset var. System.arraycopy(audioData, startOffset, transcodedAudio, 0, length); - transcodedAudioListener.handleTranscodedAudioData(transcodedAudio, timestamp += TS_INCREMENT); + + SpeexRtpAudioData srad = new SpeexRtpAudioData(transcodedAudio, timestamp += TS_INCREMENT); + try { + audioDataQ.offer(srad, 100, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + log.warn("Failed to add speex audio data into queue."); + } } public int getCodecId() { @@ -73,14 +91,33 @@ public class SpeexFlashToSipTranscoderImp implements FlashToSipTranscoder { public void setTranscodedAudioListener(TranscodedAudioListener transcodedAudioListener) { this.transcodedAudioListener = transcodedAudioListener; } - - @Override - public void start() { - // do nothing. just implement the interface. + + private void processAudioData() { + while (processAudioData) { + SpeexRtpAudioData srad; + try { + srad = audioDataQ.take(); + transcodedAudioListener.handleTranscodedAudioData(srad.audioData, srad.timestamp); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } } + + @Override + public void start() { + processAudioData = true; + audioDataProcessor = new Runnable() { + public void run() { + processAudioData(); + } + }; + exec.execute(audioDataProcessor); + } @Override - public void stop() { - // do nothing. just implement the interface. - } + public void stop() { + processAudioData = false; + } } diff --git a/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexRtpAudioData.java b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexRtpAudioData.java new file mode 100755 index 0000000000..474bb37cb4 --- /dev/null +++ b/bbb-voice/src/main/java/org/bigbluebutton/voiceconf/red5/media/transcoder/SpeexRtpAudioData.java @@ -0,0 +1,12 @@ +package org.bigbluebutton.voiceconf.red5.media.transcoder; + +public class SpeexRtpAudioData { + + public final byte[] audioData; + public final long timestamp; + + public SpeexRtpAudioData(byte[] audioData, long timestamp) { + this.audioData = audioData; + this.timestamp = timestamp; + } +} diff --git a/bigbluebutton-client/locale/en_US/bbbResources.properties b/bigbluebutton-client/locale/en_US/bbbResources.properties index e4ac26e6f6..9c43e891ca 100755 --- a/bigbluebutton-client/locale/en_US/bbbResources.properties +++ b/bigbluebutton-client/locale/en_US/bbbResources.properties @@ -36,6 +36,7 @@ bbb.micSettings.comboMicList.toolTip = Select a microphone bbb.micSettings.micRecordVolume.label = Gain bbb.micSettings.micRecordVolume.toolTip = Set your microphone gain bbb.micSettings.nextButton = Next +bbb.micSettings.nextButton.toolTip = Start the echo test bbb.micSettings.join = Join Audio bbb.micSettings.join.toolTip = Join the audio conference bbb.micSettings.cancel = Cancel @@ -49,8 +50,8 @@ bbb.micSettings.webrtc.capableBrowser = Your browser supports WebRTC. bbb.micSettings.webrtc.capableBrowser.dontuseit = Click not to use WebRTC bbb.micSettings.webrtc.capableBrowser.dontuseit.toolTip = Click here if you don't want to use the WebRTC technology (recommended if you have problems using it). bbb.micSettings.webrtc.notCapableBrowser = WebRTC is not supported in your browser. Please use Google Chrome (version 32 or greater); or Mozilla Firefox (version 26 or greater). You will still be able to join the voice conference using the Adobe Flash Platform. -bbb.micSettings.webrtc.connectingtoecho = Connecting -bbb.micSettings.webrtc.connectingtocall = Connecting to conference +bbb.micSettings.webrtc.connecting = Calling +bbb.micSettings.webrtc.waitingforice = Connecting bbb.micSettings.webrtc.endingecho = Joining audio bbb.micSettings.webrtc.endedecho = Echo test ended. bbb.micPermissions.firefox.title = Firefox Microphone Permissions @@ -151,6 +152,7 @@ bbb.presentation.fitToWidth.toolTip = Fit Presentation To Width bbb.presentation.fitToPage.toolTip = Fit Presentation To Page bbb.presentation.uploadPresBtn.toolTip = Upload Presentation bbb.presentation.backBtn.toolTip = Previous slide +bbb.presentation.btnSlideNum.accessibilityName = Slide {0} of {1} bbb.presentation.btnSlideNum.toolTip = Select a slide bbb.presentation.forwardBtn.toolTip = Next slide bbb.presentation.maxUploadFileExceededAlert = Error: The file is bigger than what's allowed. diff --git a/bigbluebutton-client/resources/prod/lib/bbb_api_bridge.js b/bigbluebutton-client/resources/prod/lib/bbb_api_bridge.js index 01f8d93d46..a568a6d958 100755 --- a/bigbluebutton-client/resources/prod/lib/bbb_api_bridge.js +++ b/bigbluebutton-client/resources/prod/lib/bbb_api_bridge.js @@ -448,6 +448,13 @@ } } + BBB.webRTCConferenceCallWaitingForICE = function() { + var swfObj = getSwfObj(); + if (swfObj) { + swfObj.webRTCConferenceCallWaitingForICE(); + } + } + BBB.webRTCCallProgressCallback = function(progress) { var swfObj = getSwfObj(); if (swfObj) { @@ -475,6 +482,14 @@ swfObj.webRTCEchoTestFailed(reason); } } + + BBB.webRTCEchoTestWaitingForICE = function() { + var swfObj = getSwfObj(); + if (swfObj) { + swfObj.webRTCEchoTestWaitingForICE(); + } + } + BBB.webRTCEchoTestEnded = function() { var swfObj = getSwfObj(); diff --git a/bigbluebutton-client/resources/prod/lib/bbb_webrtc_bridge_sip.js b/bigbluebutton-client/resources/prod/lib/bbb_webrtc_bridge_sip.js index 74a050b25c..ea0356f549 100755 --- a/bigbluebutton-client/resources/prod/lib/bbb_webrtc_bridge_sip.js +++ b/bigbluebutton-client/resources/prod/lib/bbb_webrtc_bridge_sip.js @@ -1,5 +1,5 @@ -var callerIdName, conferenceVoiceBridge, userAgent, userMicMedia, userWebcamMedia, currentSession, callTimeout, callActive, callFailCounter, callPurposefullyEnded, uaConnected; +var callerIdName, conferenceVoiceBridge, userAgent, userMicMedia, userWebcamMedia, currentSession, callTimeout, callActive, callICEConnected, callFailCounter, callPurposefullyEnded, uaConnected; function callIntoConference(voiceBridge, callback) { if (!callerIdName) { @@ -38,6 +38,9 @@ function joinWebRTCVoiceConference() { case 'connecting': BBB.webRTCConferenceCallConnecting(); break; + case 'waitingforice': + BBB.webRTCConferenceCallWaitingForICE(); + break; case 'mediarequest': BBB.webRTCMediaRequest(); break; @@ -75,6 +78,9 @@ function startWebRTCAudioTest(){ case 'connecting': BBB.webRTCEchoTestConnecting(); break; + case 'waitingforice': + BBB.webRTCEchoTestWaitingForICE(); + break; case 'mediarequest': BBB.webRTCMediaRequest(); break; @@ -281,6 +287,7 @@ function make_call(username, voiceBridge, server, callback, recall) { }, 10000); callActive = false; + callICEConnected = false; callPurposefullyEnded = false; callFailCounter = 0; console.log("Calling to " + voiceBridge + "...."); @@ -340,9 +347,13 @@ function make_call(username, voiceBridge, server, callback, recall) { }); currentSession.on('accepted', function(data){ callActive = true; + console.log('BigBlueButton call accepted'); - console.log('BigBlueButton call started'); - callback({'status':'started'}); + if (callICEConnected === true) { + callback({'status':'started'}); + } else { + callback({'status':'waitingforice'}); + } clearTimeout(callTimeout); }); currentSession.mediaHandler.on('iceFailed', function() { @@ -355,6 +366,30 @@ function make_call(username, voiceBridge, server, callback, recall) { clearTimeout(callTimeout); }); + + // Some browsers use status of 'connected', others use 'completed', and a couple use both + + currentSession.mediaHandler.on('iceConnected', function() { + console.log('Received ICE status changed to connected'); + if (callICEConnected === false) { + callICEConnected = true; + if (callActive === true) { + callback({'status':'started'}); + } + clearTimeout(callTimeout); + } + }); + + currentSession.mediaHandler.on('iceCompleted', function() { + console.log('Received ICE status changed to completed'); + if (callICEConnected === false) { + callICEConnected = true; + if (callActive === true) { + callback({'status':'started'}); + } + clearTimeout(callTimeout); + } + }); } function webrtc_hangup(callback) { diff --git a/bigbluebutton-client/resources/prod/lib/sip.js b/bigbluebutton-client/resources/prod/lib/sip.js index 7925545263..8ff731e808 100755 --- a/bigbluebutton-client/resources/prod/lib/sip.js +++ b/bigbluebutton-client/resources/prod/lib/sip.js @@ -1,5 +1,5 @@ /* - * SIP version 0.6.2 + * SIP version 0.6.3 * Copyright (c) 2014-2014 Junction Networks, Inc * Homepage: http://sipjs.com * License: http://sipjs.com/license/ @@ -37,7 +37,7 @@ module.exports={ "name": "sip.js", "title": "SIP.js", "description": "A simple, intuitive, and powerful JavaScript signaling library", - "version": "0.6.2", + "version": "0.6.3", "main": "src/index.js", "browser": { "./src/Grammar/index.js": "./src/Grammar/dist/Grammar.js", @@ -2483,12 +2483,6 @@ var Hacks = module.exports = { return typeof mozRTCPeerConnection !== 'undefined'; }, - cannotHandleRelayCandidates: function (message) { - if (this.isFirefox() && message.body) { - message.body = message.body.replace(/relay/g, 'host generation 0'); - } - }, - cannotHandleExtraWhitespace: function (message) { if (this.isFirefox() && message.body) { message.body = message.body.replace(/ \r\n/g, "\r\n"); @@ -2532,6 +2526,15 @@ var Hacks = module.exports = { } } return sdp; + }, + + hackCLinInIP: function (sdp) { + /* Starting in Firefox 34 they have set the c line to 0.0.0.0 which + * means "hold" according to legacy SIP standards and Freeswitch + * interprets it according to the SIP standards. We replace the + * 0.0.0.0 with any other IP so that the call continues. + */ + return sdp.replace("c=IN IP4 0.0.0.0", "c=IN IP4 127.0.0.1"); } }, @@ -3524,7 +3527,7 @@ _dereq_('./EventEmitter')(SIP); SIP.C = _dereq_('./Constants')(SIP.name, SIP.version); SIP.Exceptions = _dereq_('./Exceptions'); SIP.Timers = _dereq_('./Timers')(environment.timers); -_dereq_('./Transport')(SIP, environment.WebSocket); +SIP.Transport = environment.Transport(SIP, environment.WebSocket); _dereq_('./Parser')(SIP); _dereq_('./SIPMessage')(SIP); _dereq_('./URI')(SIP); @@ -3548,7 +3551,7 @@ SIP.Grammar = _dereq_('./Grammar')(SIP); return SIP; }; -},{"../package.json":1,"./ClientContext":2,"./Constants":3,"./Dialogs":5,"./DigestAuthentication":6,"./EventEmitter":7,"./Exceptions":8,"./Grammar":9,"./Hacks":11,"./LoggerFactory":12,"./MediaHandler":13,"./NameAddrHeader":14,"./Parser":15,"./RegisterContext":16,"./RequestSender":17,"./SIPMessage":19,"./SanityCheck":20,"./ServerContext":21,"./Session":22,"./Subscription":24,"./Timers":25,"./Transactions":26,"./Transport":27,"./UA":28,"./URI":29,"./Utils":30,"./WebRTC":31}],19:[function(_dereq_,module,exports){ +},{"../package.json":1,"./ClientContext":2,"./Constants":3,"./Dialogs":5,"./DigestAuthentication":6,"./EventEmitter":7,"./Exceptions":8,"./Grammar":9,"./Hacks":11,"./LoggerFactory":12,"./MediaHandler":13,"./NameAddrHeader":14,"./Parser":15,"./RegisterContext":16,"./RequestSender":17,"./SIPMessage":19,"./SanityCheck":20,"./ServerContext":21,"./Session":22,"./Subscription":24,"./Timers":25,"./Transactions":26,"./UA":28,"./URI":29,"./Utils":30,"./WebRTC":31}],19:[function(_dereq_,module,exports){ /** * @fileoverview SIP Message */ @@ -5346,7 +5349,6 @@ InviteServerContext = function(ua, request) { } //TODO: move this into media handler - SIP.Hacks.Firefox.cannotHandleRelayCandidates(request); SIP.Hacks.Firefox.cannotHandleExtraWhitespace(request); SIP.Hacks.AllBrowsers.maskDtls(request); @@ -5811,7 +5813,6 @@ InviteServerContext.prototype = { if (!this.hasAnswer) { if(request.body && request.getHeader('content-type') === 'application/sdp') { // ACK contains answer to an INVITE w/o SDP negotiation - SIP.Hacks.Firefox.cannotHandleRelayCandidates(request); SIP.Hacks.Firefox.cannotHandleExtraWhitespace(request); SIP.Hacks.AllBrowsers.maskDtls(request); @@ -6044,6 +6045,9 @@ InviteClientContext.prototype = { if (self.isCanceled || self.status === C.STATUS_TERMINATED) { return; } + + offer = SIP.Hacks.Firefox.hackCLinInIP(offer); + self.hasOffer = true; self.request.body = offer; self.status = C.STATUS_INVITE_SENT; @@ -6170,7 +6174,6 @@ InviteClientContext.prototype = { return; } - SIP.Hacks.Firefox.cannotHandleRelayCandidates(response); SIP.Hacks.Firefox.cannotHandleExtraWhitespace(response); SIP.Hacks.AllBrowsers.maskDtls(response); @@ -6288,7 +6291,6 @@ InviteClientContext.prototype = { break; } - SIP.Hacks.Firefox.cannotHandleRelayCandidates(response); SIP.Hacks.Firefox.cannotHandleExtraWhitespace(response); SIP.Hacks.AllBrowsers.maskDtls(response); @@ -8011,7 +8013,7 @@ Transport.prototype = { }; Transport.C = C; -SIP.Transport = Transport; +return Transport; }; },{}],28:[function(_dereq_,module,exports){ @@ -8892,6 +8894,7 @@ UA.prototype.loadConfig = function(configuration) { // Hacks hackViaTcp: false, hackIpInContact: false, + hackWssInTransport: false, //autostarting autostart: true, @@ -9023,7 +9026,7 @@ UA.prototype.loadConfig = function(configuration) { this.contact = { pub_gruu: null, temp_gruu: null, - uri: new SIP.URI('sip', SIP.Utils.createRandomToken(8), settings.viaHost, null, {transport: 'ws'}), + uri: new SIP.URI('sip', SIP.Utils.createRandomToken(8), settings.viaHost, null, {transport: ((settings.hackWssInTransport)?'wss':'ws')}), toString: function(options){ options = options || {}; @@ -9033,7 +9036,7 @@ UA.prototype.loadConfig = function(configuration) { contact = '<'; if (anonymous) { - contact += (this.temp_gruu || 'sip:anonymous@anonymous.invalid;transport=ws').toString(); + contact += (this.temp_gruu || ('sip:anonymous@anonymous.invalid;transport='+(settings.hackWssInTransport)?'wss':'ws')).toString(); } else { contact += (this.pub_gruu || this.uri).toString(); } @@ -9103,6 +9106,7 @@ UA.configuration_skeleton = (function() { "displayName", "hackViaTcp", // false. "hackIpInContact", //false + "hackWssInTransport", //false "instanceId", "noAnswerTimeout", // 30 seconds. "password", @@ -9278,6 +9282,12 @@ UA.configuration_check = { } }, + hackWssInTransport: function(hackWssInTransport) { + if (typeof hackWssInTransport === 'boolean') { + return hackWssInTransport; + } + }, + instanceId: function(instanceId) { if(typeof instanceId !== 'string') { return; @@ -10247,6 +10257,8 @@ var MediaHandler = function(session, options) { 'userMediaFailed', 'iceGathering', 'iceComplete', + 'iceConnected', + 'iceCompleted', 'iceFailed', 'iceDisconnected', 'iceClosed', @@ -10285,7 +10297,9 @@ var MediaHandler = function(session, options) { /* Change 'url' to 'urls' whenever this issue is solved: * https://code.google.com/p/webrtc/issues/detail?id=2096 */ - servers.push({'url': stunServers}); + [].concat(stunServers).forEach(function (server) { + servers.push({'url': server}); + }); length = turnServers.length; for (idx = 0; idx < length; idx++) { @@ -10348,6 +10362,14 @@ var MediaHandler = function(session, options) { self.emit('iceClosed', this); } + if (this.iceConnectionState === 'connected') { + self.emit('iceConnected', this); + } + + if (this.iceConnectionState === 'completed') { + self.emit('iceCompleted', this); + } + //Bria state changes are always connected -> disconnected -> connected on accept, so session gets terminated //normal calls switch from failed to connected in some cases, so checking for failed and terminated /*if (this.iceConnectionState === 'failed') { @@ -10767,6 +10789,9 @@ MediaStreamManager.render = function render (streams, elements) { } function attachAndPlay (element, stream) { + if (typeof element === 'function') { + element = element(); + } (environment.attachMediaStream || attachMediaStream)(element, stream); ensureMediaPlaying(element); } @@ -10808,7 +10833,7 @@ MediaStreamManager.render = function render (streams, elements) { }; MediaStreamManager.prototype = Object.create(SIP.EventEmitter.prototype, { - 'acquire': {value: function acquire (mediaHint) { + 'acquire': {writable: true, value: function acquire (mediaHint) { mediaHint = Object.keys(mediaHint || {}).length ? mediaHint : this.mediaHint; var saveSuccess = function (isHintStream, streams) { @@ -10860,7 +10885,7 @@ MediaStreamManager.prototype = Object.create(SIP.EventEmitter.prototype, { } }}, - 'release': {value: function release (streams) { + 'release': {writable: true, value: function release (streams) { streams = [].concat(streams); streams.forEach(function (stream) { var streamId = MediaStreamManager.streamId(stream); @@ -10894,6 +10919,7 @@ function getPrefixedProperty (object, name) { module.exports = { WebSocket: global.WebSocket, + Transport: _dereq_('./Transport'), open: global.open, Promise: global.Promise, timers: global, @@ -10917,7 +10943,7 @@ module.exports = { }; }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],35:[function(_dereq_,module,exports){ +},{"./Transport":27}],35:[function(_dereq_,module,exports){ module.exports = _dereq_('./SIP')(_dereq_('./environment')); },{"./SIP":18,"./environment":34}]},{},[35]) diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/api/ExternalApiCallbacks.as b/bigbluebutton-client/src/org/bigbluebutton/main/api/ExternalApiCallbacks.as index 48f89f46c7..147fdb24a3 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/main/api/ExternalApiCallbacks.as +++ b/bigbluebutton-client/src/org/bigbluebutton/main/api/ExternalApiCallbacks.as @@ -99,10 +99,12 @@ package org.bigbluebutton.main.api ExternalInterface.addCallback("webRTCConferenceCallConnecting", handleWebRTCConferenceCallConnecting); ExternalInterface.addCallback("webRTCConferenceCallEnded", handleWebRTCConferenceCallEnded); ExternalInterface.addCallback("webRTCConferenceCallFailed", handleWebRTCConferenceCallFailed); + ExternalInterface.addCallback("webRTCConferenceCallWaitingForICE", handleWebRTCConferenceCallWaitingForICE); ExternalInterface.addCallback("webRTCEchoTestStarted", handleWebRTCEchoTestStarted); ExternalInterface.addCallback("webRTCEchoTestConnecting", handleWebRTCEchoTestConnecting); ExternalInterface.addCallback("webRTCEchoTestFailed", handleWebRTCEchoTestFailed); ExternalInterface.addCallback("webRTCEchoTestEnded", handleWebRTCEchoTestEnded); + ExternalInterface.addCallback("webRTCEchoTestWaitingForICE", handleWebRTCEchoTestWaitingForICE); ExternalInterface.addCallback("webRTCMediaRequest", handleWebRTCMediaRequest); ExternalInterface.addCallback("webRTCMediaSuccess", handleWebRTCMediaSuccess); ExternalInterface.addCallback("webRTCMediaFail", handleWebRTCMediaFail); @@ -418,6 +420,11 @@ package org.bigbluebutton.main.api trace(LOG + "handleWebRTCConferenceCallFailed: errorCode=[" + errorCode + "]"); _dispatcher.dispatchEvent(new WebRTCCallEvent(WebRTCCallEvent.WEBRTC_CALL_FAILED, errorCode)); } + + private function handleWebRTCConferenceCallWaitingForICE():void { + trace(LOG + "handleWebRTCConferenceCallWaitingForICE: received"); + _dispatcher.dispatchEvent(new WebRTCCallEvent(WebRTCCallEvent.WEBRTC_CALL_WAITING_FOR_ICE)); + } private function handleWebRTCEchoTestStarted():void { trace(LOG + "handleWebRTCEchoTestStarted: recieved"); @@ -438,6 +445,11 @@ package org.bigbluebutton.main.api trace(LOG + "handleWebRTCEchoTestEnded: received"); _dispatcher.dispatchEvent(new WebRTCEchoTestEvent(WebRTCEchoTestEvent.WEBRTC_ECHO_TEST_ENDED)); } + + private function handleWebRTCEchoTestWaitingForICE():void { + trace(LOG + "handleWebRTCEchoTestWaitingForICE: received"); + _dispatcher.dispatchEvent(new WebRTCEchoTestEvent(WebRTCEchoTestEvent.WEBRTC_ECHO_TEST_WAITING_FOR_ICE)); + } private function handleWebRTCMediaRequest():void { trace(LOG + "handleWebRTCMediaRequest: received"); diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/WebRTCEchoTest.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/WebRTCEchoTest.mxml index 37af7459ca..8171b1734c 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/main/views/WebRTCEchoTest.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/WebRTCEchoTest.mxml @@ -30,8 +30,10 @@ with BigBlueButton; if not, see . + + @@ -65,7 +67,7 @@ with BigBlueButton; if not, see . private function onCancelClicked():void { JSLog.debug(LOG + "onCancelClicked ."); - dotTimer.stop(); + if (dotTimer) dotTimer.stop(); PopUpManager.removePopUp(this); } @@ -75,7 +77,7 @@ with BigBlueButton; if not, see . private function onCreationComplete():void { setCurrentState("connecting"); - lblConnectMessage.text = ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.connectingtoecho'); + lblConnectMessage.text = lblConnectMessageMock.text = ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.connecting'); dotTimer = new Timer(200, 0); dotTimer.addEventListener(TimerEvent.TIMER, dotAnimate); dotTimer.start(); @@ -98,10 +100,11 @@ with BigBlueButton; if not, see . userClosed = true; trace(LOG + "Echo test passed."); JSLog.debug(LOG + "Echo test passed."); + setCurrentState("connecting"); + lblConnectMessage.text = lblConnectMessageMock.text = ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.endingecho'); + var dispatcher:Dispatcher = new Dispatcher(); dispatcher.dispatchEvent(new WebRTCEchoTestEvent(WebRTCEchoTestEvent.WEBRTC_ECHO_TEST_HAS_AUDIO)); - setCurrentState("connecting"); - lblConnectMessage.text = ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.endingecho'); } private function noButtonClicked():void { @@ -128,7 +131,7 @@ with BigBlueButton; if not, see . private function webRTCEchoTestEnded():void { setCurrentState("connecting"); - lblConnectMessage.text = ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.endedecho'); + lblConnectMessage.text = lblConnectMessageMock.text = ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.endedecho'); if (!dotTimer.running) dotTimer.start(); if (!userClosed) { @@ -142,15 +145,27 @@ with BigBlueButton; if not, see . onCancelClicked(); } + private function handleWebRTCEchoTestWaitingForICEEvent(e:WebRTCEchoTestEvent):void { + setCurrentState("connecting"); + lblConnectMessage.text = lblConnectMessageMock.text = ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.waitingforice'); + if (!dotTimer.running) dotTimer.start(); + } + private function handleWebRTCCallConnectingEvent(e:WebRTCCallEvent):void { setCurrentState("connecting"); - lblConnectMessage.text = ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.connectingtocall'); + lblConnectMessage.text = lblConnectMessageMock.text = ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.connecting'); if (!dotTimer.running) dotTimer.start(); } private function handleWebRTCCallFailedEvent(e:WebRTCCallEvent):void { onCancelClicked(); } + + private function handleWebRTCCallWaitingForICEEvent(e:WebRTCCallEvent):void { + setCurrentState("connecting"); + lblConnectMessage.text = lblConnectMessageMock.text = ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.waitingforice'); + if (!dotTimer.running) dotTimer.start(); + } private function webRTCCallStarted():void { JSLog.debug(LOG + "webRTCCallStarted."); @@ -193,7 +208,10 @@ with BigBlueButton; if not, see . - + + diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/events/WebRTCCallEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/events/WebRTCCallEvent.as index bf80bd2296..b6d6449e1d 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/events/WebRTCCallEvent.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/events/WebRTCCallEvent.as @@ -8,6 +8,7 @@ package org.bigbluebutton.modules.phone.events public static const WEBRTC_CALL_CONNECTING:String = "WEBRTC_CALL_CONNECTING"; public static const WEBRTC_CALL_ENDED:String = "WEBRTC_CALL_ENDED"; public static const WEBRTC_CALL_FAILED:String = "WEBRTC_CALL_FAILED"; + public static const WEBRTC_CALL_WAITING_FOR_ICE:String = "WEBRTC_CALL_WAITING_FOR_ICE"; public var errorCode:Number; diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/events/WebRTCEchoTestEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/events/WebRTCEchoTestEvent.as index f15b421c05..1ed7647dd5 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/events/WebRTCEchoTestEvent.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/events/WebRTCEchoTestEvent.as @@ -11,6 +11,7 @@ package org.bigbluebutton.modules.phone.events public static const WEBRTC_ECHO_TEST_HAS_AUDIO:String = "WEBRTC_ECHO_TEST_HAS_AUDIO"; public static const WEBRTC_ECHO_TEST_NO_AUDIO:String = "WEBRTC_ECHO_TEST_NO_AUDIO"; public static const WEBRTC_ECHO_TEST_ENDED_UNEXPECTEDLY:String = "WEBRTC_ECHO_TEST_ENDED_UNEXPECTEDLY"; + public static const WEBRTC_ECHO_TEST_WAITING_FOR_ICE:String = "WEBRTC_ECHO_TEST_WAITING_FOR_ICE"; public var errorCode:Number;