Merge branch 'master' into merge-polling-with-master

This commit is contained in:
Richard Alam 2014-02-10 21:49:36 +00:00
commit c77ddd76d3
25 changed files with 20280 additions and 388 deletions

View File

@ -47,7 +47,7 @@ Panel {
color: #e1e2e5;
}
Button, .logoutButtonStyle, .chatSendButtonStyle, .helpLinkButtonStyle, .cameraDisplaySettingsWindowChangeResolutionCombo, .languageSelectorStyle, .testJavaLinkButtonStyle, .recordButtonStyleNormal, .recordButtonStyleStart, .recordButtonStyleStop {
Button, .logoutButtonStyle, .chatSendButtonStyle, .helpLinkButtonStyle, .cameraDisplaySettingsWindowChangeResolutionCombo, .languageSelectorStyle, .testJavaLinkButtonStyle, .recordButtonStyleNormal, .recordButtonStyleStart, .recordButtonStyleStop, .micSettingsWindowHelpButtonStyle {
textIndent: 0;
paddingLeft: 10;
paddingRight: 10;
@ -479,7 +479,17 @@ DataGrid {
}
.micSettingsWindowHelpButtonStyle {
icon: Embed('assets/images/questionmark.png');
paddingLeft: 4;
paddingRight: 4;
paddingTop: 2;
paddingBottom: 2;
fontSize: 16;
rollOverColor: #cccccc;
selectionColor: #999999;
color: #504f3d;
textRollOverColor: #ffffff;
textSelectedColor: #ffffff;
fontWeight: bold;
}
MDIWindow { /*None of the following properties are overridden by the MDIWindow class*/

View File

@ -16,11 +16,24 @@ bbb.micSettings.hearFromHeadset = You should hear audio in your headset, not you
bbb.micSettings.speakIntoMic = Test or change your microphone (headset recommended).
bbb.micSettings.changeMic = Test or Change Microphone
bbb.micSettings.changeMic.toolTip = Open the Flash Player microphone settings dialog box
bbb.micSettings.comboMicList.toolTip = Select a microphone
bbb.micSettings.micRecordVolume.label = Gain
bbb.micSettings.micRecordVolume.toolTip = Set your microphone gain
bbb.micSettings.join = Join Audio
bbb.micSettings.join.toolTip = Join the audio conference
bbb.micSettings.cancel = Cancel
bbb.micSettings.cancel.toolTip = Cancel joining the audio conference
bbb.micSettings.access.helpButton = Open tutorial videos in a new page.
bbb.micSettings.access.title = Audio Settings. Focus will remain in this audio settings window until the window is closed.
bbb.micSettings.webrtc.title = WebRTC Support
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 = Currently this system only supports WebRTC on Google Chrome. You will still be able to join the voice conference using the Adobe Flash Platform.
bbb.micWarning.title = Audio Warning
bbb.micWarning.joinBtn.label = Join anyway
bbb.micWarning.testAgain.label = Test again
bbb.micWarning.message = Your microphone did not show any activity, others probably won't be able to hear you during the session.
bbb.mainToolbar.helpBtn = Help
bbb.mainToolbar.logoutBtn = Logout
bbb.mainToolbar.logoutBtn.toolTip = Log out

View File

@ -1,4 +1,4 @@
bbb.mainshell.locale.version = 0.8
bbb.mainshell.locale.version = 0.80
bbb.mainshell.statusProgress.connecting = Connessione alla conferenza in corso...
bbb.mainshell.statusProgress.loading = Caricamento {0}
bbb.mainshell.statusProgress.cannotConnectServer = Errore di connessione.

View File

@ -21,6 +21,11 @@ bbb.micSettings.cancel = Cancelar
bbb.micSettings.cancel.toolTip = Cancelar a entrada na conferência de voz
bbb.micSettings.access.helpButton = Abrir os vídeos tutoriais em uma nova janela.
bbb.micSettings.access.title = Configurações de som. O foco permanecerá na janela de configurações de som até que a janela seja fechada.
bbb.micSettings.webrtc.title = Suporte a WebRTC
bbb.micSettings.webrtc.capableBrowser = Seu navegador suporta WebRTC.
bbb.micSettings.webrtc.capableBrowser.dontuseit = Clique para não utilizar WebRTC
bbb.micSettings.webrtc.capableBrowser.dontuseit.toolTip = Clique aqui se não desejar utilizar a tecnologia WebRTC (recomendado se você tiver problemas ao utilizá-la).
bbb.micSettings.webrtc.notCapableBrowser = Atualmente este sistema suporta WebRTC apenas no Google Chrome. Você ainda será capaz de acionar seu áudio utilizando a plataforma Adobe Flash.
bbb.mainToolbar.helpBtn = Ajuda
bbb.mainToolbar.logoutBtn = Sair
bbb.mainToolbar.logoutBtn.toolTip = Sair da sessão

View File

@ -24,6 +24,7 @@
privateEnabled="true"
position="top-right"
baseTabIndex="701"
colorPickerIsVisible="false"
/>
<module name="UsersModule" url="http://HOST/client/UsersModule.swf?v=VERSION"
@ -50,6 +51,7 @@
skipCheck="false"
showButton="true"
enabledEchoCancel="true"
useWebrtcIfAvailable="true"
dependsOn="UsersModule"
/>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>BigBlueButton</title>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css" media="screen">
html, body, #content { height:100%; }
@ -43,6 +43,10 @@
<script src="lib/bbb_blinker.js" language="javascript"></script>
<script src="lib/bbb_deskshare.js" language="javascript"></script>
<script src="lib/bbb_api_bridge.js" language="javascript"></script>
<script src="lib/jssip-devel.js" language="javascript"></script>
<script src="lib/bbb_webrtc_bridge_jssip.js" language="javascript"></script>
<!-- <script src="lib/sipml5api.js" language="javascript"></script> -->
<!-- <script src="lib/bbb_webrtc_bridge_sipml5.js" language="javascript"></script> -->
<script>
window.chatLinkClicked = function(url) {
window.open(url, '_blank');
@ -50,7 +54,17 @@
}
</script>
</head>
<body>
<div>
<!-- <button onclick="hangUp()">Hang up</button>
<button onclick="callIntoConference()">Call</button>-->
<audio id="audio-remote" autoplay="autoplay" />
<audio id="local-media" autoplay="autoplay" />
<audio id="remote-media" autoplay="autoplay" />
</div>
<div id="content">
<div id="altFlash">
<a href="http://www.adobe.com/go/getflashplayer">
@ -58,8 +72,9 @@
</a>
</div>
</div>
<button id="enterFlash" type="button" class="visually-hidden" onclick="startFlashFocus();" value="Focus the client" >Focus the client</button>
<button id="enterFlash" type="button" class="visually-hidden" onclick="startFlashFocus();" value="Click to focus the client"/>
<div id="notifications" aria-live="polite" role="region" aria-label="Chat Notifications"></div>
</body>
<script type="text/javascript">
// Work around pixel alignment bug with Chrome 21 on Mac.
@ -82,5 +97,82 @@
}
});
</script>
</body>
</html>
<script type="text/javascript">
var fsServer = null;
var callIntoConference = function(callback) {
if (!isWebrtcCapable()) {
callback("Browser version not supported");
return;
}
BBB.getMyUserInfo(function(userInfo) {
console.log("User info callback [myUserID=" + userInfo.myUserID
+ ",myUsername=" + userInfo.myUsername + ",myAvatarURL=" + userInfo.myAvatarURL
+ ",myRole=" + userInfo.myRole + ",amIPresenter=" + userInfo.amIPresenter
+ ",dialNumber=" + userInfo.dialNumber + ",voiceBridge=" + userInfo.voiceBridge + "].");
var callerIdName = userInfo.myUserID + "-bbbID-" + userInfo.myUsername;
// setup a timer to call the error callback
var checkSuccessCallback = function(e) {
if (e.userID == userInfo.myUserID) {
console.info("Received the event from Flash that I've joined the voice conference");
BBB.unlisten('UserJoinedVoiceEvent', checkSuccessCallback);
}
}
BBB.listen('UserJoinedVoiceEvent', checkSuccessCallback);
console.log(callerIdName);
webrtc_call(callerIdName, userInfo.voiceBridge, fsServer, callback);
});
}
var joinWebRTCVoiceConference = function(){
console.log("Joining to the voice conference");
var callback = function(err) {
if (err) {
console.info("Failed to call: " + err);
} else {
console.info("Success to call");
}
BBB.joinWebRTCVoiceConferenceCallback(err);
}
callIntoConference(callback);
}
var leaveWebRTCVoiceConference = function(){
console.log("Leaving the voice conference");
var callback = function(err) {
if (err) {
console.info("Failed to hang up: " + err);
} else {
console.info("Success to hang up");
}
BBB.leaveWebRTCVoiceConferenceCallback(err);
}
webrtc_hangup(callback);
}
var startWebrtcAudioTest = function(){
console.log("Testing webrtc audio");
webrtc_call("tester", "9196", fsServer, function(message){
console.log("You should hear yourself talking");
});
}
var stopWebrtcAudioTest = function(){
console.log("Stopping webrtc audio test");
webrtc_hangup(function(){
console.log("Webrtc audio test stopped");
});
}
</script>

View File

@ -415,6 +415,24 @@
swfObj.deletePresentationRequest(presentationID);
}
}
/**
*
*/
BBB.joinWebRTCVoiceConferenceCallback = function(message) {
var swfObj = getSwfObj();
if (swfObj) {
swfObj.joinWebRTCVoiceConferenceCallback(message);
}
}
BBB.leaveWebRTCVoiceConferenceCallback = function(message) {
var swfObj = getSwfObj();
if (swfObj) {
swfObj.leaveWebRTCVoiceConferenceCallback(message);
}
}
// Third-party JS apps should use this to query if the BBB SWF file is ready to handle calls.
BBB.isSwfClientReady = function() {

View File

@ -0,0 +1,114 @@
var bbbAudioConference;
var currentSession;
// Hang Up webrtc call
function webrtc_hangup(callback) {
console.log("Terminating current session");
currentSession.terminate(); // allows calling multiple times
callback();
}
// Call
function webrtc_call(username, voiceBridge, server, callback) {
var sayswho = navigator.sayswho,
browser = sayswho[0],
version = +(sayswho[1].split('.')[0]);
console.log("Browser: " + browser + ", version: " + version);
if ( !( (browser == "Chrome" && version > 27) || (browser == "Firefox" && version > 26) ) ) {
callback("Browser version not supported");
return;
}
server = server || window.document.location.host;
console.log("user " + username + " calling to " + voiceBridge);
var configuration = {
uri: 'sip:' + username + '@' + server,
// password: freeswitchPassword,
// ws_servers: 'wss://' + server + ':7443',
ws_servers: 'ws://' + server + ':5066',
display_name: username,
// authorization_user: freeswitchUser,
register: false,
// register_expires: null,
// no_answer_timeout: null,
trace_sip: true,
stun_servers: "stun:74.125.134.127:19302",
// turn_servers: null,
// use_preloaded_route: null,
// connection_recovery_min_interval: null,
// connection_recovery_max_interval: null,
// hack_via_tcp: null,
// hack_ip_in_contact: null
};
bbbAudioConference = new JsSIP.UA(configuration);
bbbAudioConference.on('newRTCSession', function(e) {
console.log("New Webrtc session created!");
currentSession = e.data.session;
});
bbbAudioConference.start();
// Make an audio/video call:
// HTML5 <video> elements in which local and remote video will be shown
var selfView = document.getElementById('local-media');
var remoteView = document.getElementById('remote-media');
console.log("Registering callbacks to desired call events..");
var eventHandlers = {
'progress': function(e){
console.log('call is in progress');
},
'failed': function(e){
console.log('call failed with cause: '+ e.data.cause);
},
'ended': function(e){
console.log('call ended with cause: '+ e.data.cause);
},
'started': function(e){
var rtcSession = e.sender;
console.log('BigBlueButton call started');
// Attach local stream to selfView
if (rtcSession.getLocalStreams().length > 0) {
console.log("Got local stream");
}
// Attach remote stream to remoteView
if (rtcSession.getRemoteStreams().length > 0) {
console.log("Got remote stream");
remoteView.src = window.URL.createObjectURL(rtcSession.getRemoteStreams()[0]);
}
callback();
}
};
console.log("Setting options.. ");
var options = {
'eventHandlers': eventHandlers,
'mediaConstraints': {'audio': true, 'video': false}
};
console.log("Calling to " + voiceBridge + "....");
bbbAudioConference.call('sip:' + voiceBridge + '@' + server, options);
}
// http://stackoverflow.com/questions/5916900/detect-version-of-browser
navigator.sayswho= (function(){
var ua= navigator.userAgent,
N= navigator.appName,
tem,
M= ua.match(/(opera|chrome|safari|firefox|msie|trident)\/?\s*([\d\.]+)/i) || [];
M= M[2]? [M[1], M[2]]:[N, navigator.appVersion, '-?'];
if(M && (tem= ua.match(/version\/([\.\d]+)/i))!= null) M[2]= tem[1];
return M;
})();

View File

@ -0,0 +1,123 @@
// Create a SIP Stack
var sipStack;
var connected;
var voicebridge;
var connectingTS, connectedTS;
function createSipStack(caller, server, callback) {
console.log("...Creating sip stack..")
var eventsListener = function(e){
console.log("... SIPml.Stack event listener: " + e.type + "...")
if(e.type == 'started') {
// there's no need to login, call directly!
//login();
connected = true;
makeCall(callback);
} else if(e.type == 'i_new_message') { // incoming new SIP MESSAGE (SMS-like)
console.log("To accept the message, uncomment");
// acceptMessage(e);
} else if(e.type == 'i_new_call') { // incoming audio/video call
console.log("To accept call, uncomment.");
//acceptCall(e);
} else if (e.type == 'm_permission_requested') {
console.log("Waiting for user authorization to access the microphone");
} else if (e.type == 'm_permission_refused') {
callback("The user denied the access to the microphone");
} else if (e.type == 'm_permission_accepted') {
console.log("Permission accepted");
connectingTS = new Date().getTime();
} else if (e.type == 'stopped') {
}
}
sipStack = new SIPml.Stack({
realm: server, // mandatory: domain name
impi: 'bbbuser', // mandatory: authorization name (IMS Private Identity)
impu: [ 'sip:bbbuser@', server ].join(""), // mandatory: valid SIP Uri (IMS Public Identity)
password: 'secret', // optional
display_name: caller, // optional
websocket_proxy_url: [ 'ws://', server, ':5066' ].join(""), // optional
outbound_proxy_url: [ 'udp://', server, ':5060' ].join(""), // optional
//enable_rtcweb_breaker: true, // optional
events_listener: { events: '*', listener: eventsListener }, // optional: '*' means all events
sip_headers: [ // optional
{ name: 'User-Agent', value: 'IM-client/OMA1.0 sipML5-v1.0.0.0', session: true },
{ name: 'Organization', value: 'BigBlueButton', session: true }
],
sip_caps: [
{ name: '+g.oma.sip-im' },
{ name: '+sip.ice' },
{ name: 'language', value: '\"en,fr\"' },
{ name: 'bbbcap', value: 'HelloBBB' }
]
});
}
// Making a call
var callSession;
var makeCall = function(callback) {
var eventsListener = function(e) {
console.log("... call session event listener: " + e.type + "...");
if (e.type == 'connecting') {
} else if (e.type == 'connected') {
connectedTS = new Date().getTime();
callback();
console.info("This call was established in " + (connectedTS-connectingTS) + "ms");
} else if (e.type == 'terminated') {
}
}
console.log("... Making a call...");
//callSession = sipStack.newSession('call-audiovideo', {
callSession = sipStack.newSession('call-audio', {
//video_local: document.getElementById('video-local'),
//video_remote: document.getElementById('video-remote'),
audio_remote: document.getElementById('audio-remote'),
events_listener: { events: '*', listener: eventsListener } // optional: '*' means all events
});
//callSession.call(voicebridge + "-12345-Richard", {display_name: 'Guga'});
//callSession.call(voicebridge, {display_name: 'Guga'});
callSession.call(voicebridge);
}
// Hang Up
function webrtc_hangup(callback) {
if (sipStack) {
var onStoppedCallback = function(e) {
sipStack.removeEventListener('stopped', onStoppedCallback);
connected = false;
callback();
}
sipStack.addEventListener('stopped', onStoppedCallback);
sipStack.stop(); // shutdown all sessions
}
}
// Call
function webrtc_call(username, voiceBridge, server, callback) {
voicebridge = voiceBridge;
server = server || window.document.location.host;
console.log("user " + username + " calling to " + voicebridge);
// Initialize the engine.
console.log("... Initializing the engine ...")
var readyCallback = function(e){
createSipStack(username, server, callback);
};
var errorCallback = function(e){
console.error('Failed to initialize the engine: ' + e.message);
callback('Failed to initialize the engine: ' + e.message);
}
if (!SIPml.isInitialized) {
// You must call this function before any other
SIPml.init(readyCallback, errorCallback);
} else {
// restart the SIP stack just if it was the first time
readyCallback(null);
}
sipStack.start();
//makeCall(voicebridge);
}

View File

@ -32,4 +32,29 @@ function startFlashFocus() {
function stopFlashFocus() {
$('#enterFlash')[0].focus();
}
}
// http://stackoverflow.com/questions/5916900/detect-version-of-browser
navigator.sayswho= (function(){
var ua= navigator.userAgent,
N= navigator.appName,
tem,
M= ua.match(/(opera|chrome|safari|firefox|msie|trident)\/?\s*([\d\.]+)/i) || [];
M= M[2]? [M[1], M[2]]:[N, navigator.appVersion, '-?'];
if(M && (tem= ua.match(/version\/([\.\d]+)/i))!= null) M[2]= tem[1];
return M;
})();
var isWebrtcCapable = function() {
var sayswho = navigator.sayswho,
browser = sayswho[0],
version = +(sayswho[1].split('.')[0]);
console.log("Browser: " + browser + ", version: " + version);
// if (browser != "Chrome" || version < 28) {
if ((browser == "Chrome" && version >= 28) || (browser == "Firefox" && version >= 27)) {
return true;
} else {
return false;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -21,7 +21,7 @@ package org.bigbluebutton.main.api
import com.asfusion.mate.events.Dispatcher;
import flash.external.ExternalInterface;
import mx.controls.Alert;
import org.bigbluebutton.common.LogUtil;
@ -39,6 +39,8 @@ package org.bigbluebutton.main.api
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.main.model.users.events.RaiseHandEvent;
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
import org.bigbluebutton.modules.phone.events.CallConnectedEvent;
import org.bigbluebutton.modules.phone.events.CallDisconnectedEvent;
import org.bigbluebutton.modules.present.events.QueryPresentationsListEvent;
import org.bigbluebutton.modules.present.events.RemovePresentationEvent;
import org.bigbluebutton.modules.present.events.UploadEvent;
@ -90,6 +92,9 @@ package org.bigbluebutton.main.api
ExternalInterface.addCallback("displayPresentationRequest", handleDisplayPresentationRequest);
ExternalInterface.addCallback("deletePresentationRequest", handleDeletePresentationRequest);
ExternalInterface.addCallback("queryListsOfPresentationsRequest", handleQueryListsOfPresentationsRequest);
ExternalInterface.addCallback("joinWebRTCVoiceConferenceCallback", handleJoinWebRTCVoiceConferenceCallback);
ExternalInterface.addCallback("leaveWebRTCVoiceConferenceCallback", handleLeaveWebRTCVoiceConferenceCallback);
}
// Tell out JS counterpart that we are ready.
@ -380,5 +385,31 @@ package org.bigbluebutton.main.api
_dispatcher.dispatchEvent(event);
}
private function handleJoinWebRTCVoiceConferenceCallback(err:String=null):void {
trace("handleJoinWebRTCVoiceConferenceCallback: [" + err + "]");
if (err) {
// we cannot use webrtc to join the voice conference, so try to call again using Flash
var e:BBBEvent = new BBBEvent("CLICK_TO_JOIN_VOICE_CONFERENCE_EVENT");
e.payload['forceSkipCheck'] = true;
e.payload['webrtcCapable'] = false;
_dispatcher.dispatchEvent(e);
} else {
var connectedEvent:CallConnectedEvent = new CallConnectedEvent();
_dispatcher.dispatchEvent(connectedEvent);
}
}
private function handleLeaveWebRTCVoiceConferenceCallback(err:String=null):void {
trace("handleLeaveWebRTCVoiceConferenceCallback: [" + err + "]");
if (err) {
// do something if we cannot leave via webrtc
// var e:BBBEvent;
// e = new BBBEvent("JOIN_VOICE_CONFERENCE_EVENT");
} else {
var disconnectedEvent:CallDisconnectedEvent = new CallDisconnectedEvent();
_dispatcher.dispatchEvent(disconnectedEvent);
}
}
}
}

View File

@ -300,13 +300,22 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
private function showMicSettings(event:BBBEvent):void {
var micSettings:MicSettings = MicSettings(PopUpManager.createPopUp(mdiCanvas, MicSettings, true));
var point1:Point = new Point();
// Calculate position of TitleWindow in Application's coordinates.
point1.x = width/2;
point1.y = height/2;
micSettings.x = point1.x - (micSettings.width/2);
micSettings.y = point1.y - (micSettings.height/2);
var micSettings:MicSettings = PopUpManager.createPopUp(mdiCanvas, MicSettings, true) as MicSettings;
micSettings.addEventListener(FlexEvent.CREATION_COMPLETE, function(e:Event):void {
var point1:Point = new Point();
// Calculate position of TitleWindow in Application's coordinates.
point1.x = width/2;
point1.y = height/2;
micSettings.x = point1.x - (micSettings.width/2);
micSettings.y = point1.y - (micSettings.height/2);
});
if (event.payload != null && event.payload.hasOwnProperty('webrtcCapable')) {
micSettings.webrtcCapable = event.payload.webrtcCapable;
}
if (event.payload != null && event.payload.hasOwnProperty('useWebrtcIfAvailable')) {
micSettings.useWebrtcIfAvailable = event.payload.useWebrtcIfAvailable;
}
}
private function openVideoPreviewWindow(event:BBBEvent):void {

View File

@ -20,34 +20,32 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-->
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:mate="http://mate.asfusion.com/"
width="600" height="350"
width="500" height="240"
creationComplete="initDefaultMic()"
styleName="micSettingsWindowStyle"
showCloseButton="false"
close="onCancelClicked()"
keyDown="handleKeyDown(event)">
<mx:Script>
<![CDATA[
import flash.system.Security;
import flash.system.SecurityPanel;
import flash.ui.Keyboard;
import mx.events.CloseEvent;
import mx.events.ItemClickEvent;
import mx.managers.PopUpManager;
import mx.core.IFlexDisplayObject;
import mx.events.SliderEvent;
import mx.controls.sliderClasses.Slider;
import org.bigbluebutton.common.Images;
import org.bigbluebutton.common.LogUtil;
import org.bigbluebutton.core.BBB;
import org.bigbluebutton.main.events.BBBEvent;
import org.bigbluebutton.main.events.ShortcutEvent;
import org.bigbluebutton.util.i18n.ResourceUtil;
import flash.system.Security;
import flash.system.SecurityPanel;
import flash.ui.Keyboard;
import mx.controls.sliderClasses.Slider;
import mx.core.IFlexDisplayObject;
import mx.events.CloseEvent;
import mx.events.ItemClickEvent;
import mx.events.SliderEvent;
import mx.managers.PopUpManager;
import org.bigbluebutton.common.Images;
import org.bigbluebutton.common.LogUtil;
import org.bigbluebutton.core.BBB;
import org.bigbluebutton.main.events.BBBEvent;
import org.bigbluebutton.main.events.ShortcutEvent;
import org.bigbluebutton.util.i18n.ResourceUtil;
[Embed(source="assets/audio-test.mp3")]
[Bindable] private var soundClass:Class;
@ -60,94 +58,93 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
private var micName:String;
private var playingAudio:Boolean = false;
private var images:Images = new Images();
private var chromeAllow:ChromeAllow;
private var userBrowser:String;
[Bindable] private var _webrtcCapable:Boolean = false;
[Bindable] private var _useWebrtcIfAvailable:Boolean = true;
[Bindable] private var cancelIcon:Class = images.cancel;
[Bindable] private var microphoneList:Array;
[Bindable]private var baseIndex:int = 1;
override public function move(x:Number, y:Number):void
{
return;
}
private function selectMicrophone(event:Event):void {
LogUtil.debug("Changing microphone.");
//testMicBtn.selected = false;
if (mic != null){
mic.setLoopBack(false);
}
mic = Microphone.getMicrophone(comboMicList.selectedIndex);
testMicrophone();
}
private function testMicrophone():void{
micName = mic.name;
biggestMicLevel = 0;
LogUtil.debug("Testing microphone : " + micName);
if (mic != null) {
mic.setLoopBack(false);
if (mic.muted) {
LogUtil.debug("Microphone is muted.");
mic.addEventListener(StatusEvent.STATUS, micStatusEventHandler);
Security.showSettings(SecurityPanel.PRIVACY);
// Security.showSettings(SecurityPanel.MICROPHONE);
return;
} else {
// Update mic name
if (micName != mic.name ){
micName = mic.name;
}
//Parameters valid only for the mic settings
mic.setLoopBack(true);
mic.setUseEchoSuppression(true);
//http://stackoverflow.com/questions/2936925/no-mic-activity-with-setloopback-set-to-false-as3
//http://groups.yahoo.com/neo/groups/flexcoders/conversations/topics/144047
mic.codec = SoundCodec.NELLYMOSER
mic.soundTransform = new SoundTransform(0);
mic.gain = micRecordVolume.value;
timer = new Timer(0);
timer.addEventListener(TimerEvent.TIMER, updateMicLevel);
timer.start();
//Security.showSettings(SecurityPanel.MICROPHONE);
}
}else {
LogUtil.warn("Microphone is used by other application.");
}
}
private function initDefaultMic():void {
microphoneList = Microphone.names;
LogUtil.debug("Available microphones: " + microphoneList);
mic = Microphone.getMicrophone(comboMicList.selectedIndex);
testMicrophone();
showChromeAllow();
/* if (mic != null) {
if (mic.muted) {
// user has disallowed access to the mic
mic.addEventListener(StatusEvent.STATUS, micStatusEventHandler);
// when we open the window show the default acceptor first and then the custom one every other time
mic.setLoopBack(true);
mic.setLoopBack(false);
} else {
// user has allowed access to the mic
mic.setLoopBack(false);
mic.setUseEchoSuppression(true);
}
} else {
LogUtil.warn("Microphone is used by another application.");
}
*/
/*timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER, updateMicLevel);
//timer.start(); Commenting this out because the mic level has been removed
*/
[Bindable] private var microphoneList:Array;
[Bindable]private var baseIndex:int = 1;
override public function move(x:Number, y:Number):void
{
return;
}
private function selectMicrophone(event:Event):void {
LogUtil.debug("Changing microphone.");
//testMicBtn.selected = false;
if (mic != null){
mic.setLoopBack(false);
}
mic = Microphone.getMicrophone(comboMicList.selectedIndex);
testMicrophone();
}
private function testMicrophone():void{
micName = mic.name;
biggestMicLevel = 0;
LogUtil.debug("Testing microphone : " + micName);
if (mic != null) {
mic.setLoopBack(false);
if (mic.muted) {
LogUtil.debug("Microphone is muted.");
mic.addEventListener(StatusEvent.STATUS, micStatusEventHandler);
Security.showSettings(SecurityPanel.PRIVACY);
// Security.showSettings(SecurityPanel.MICROPHONE);
return;
} else {
// Update mic name
if (micName != mic.name ){
micName = mic.name;
}
//Parameters valid only for the mic settings
mic.setLoopBack(true);
mic.setUseEchoSuppression(true);
//http://stackoverflow.com/questions/2936925/no-mic-activity-with-setloopback-set-to-false-as3
//http://groups.yahoo.com/neo/groups/flexcoders/conversations/topics/144047
mic.codec = SoundCodec.NELLYMOSER
mic.soundTransform = new SoundTransform(0);
mic.gain = micRecordVolume.value;
timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER, updateMicLevel);
timer.start();
//Security.showSettings(SecurityPanel.MICROPHONE);
}
}else {
LogUtil.warn("Microphone is used by other application.");
}
}
private function initDefaultMic():void {
if (webrtcCapable && useWebrtcIfAvailable) {
settingBtn.addEventListener(MouseEvent.CLICK, webrtcTestCall);
} else {
microphoneList = Microphone.names;
LogUtil.debug("Available microphones: " + microphoneList);
mic = Microphone.getMicrophone(comboMicList.selectedIndex);
testMicrophone();
showChromeAllow();
var tempArr:Array = new Array();
tempArr.push("0%", ResourceUtil.getInstance().getString('bbb.micSettings.micRecordVolume.label'),"100%");
micRecordVolume.labels = tempArr;
}
}
private function webrtcTestCall(e:MouseEvent):void {
if (settingBtn.selected) {
ExternalInterface.call("startWebrtcAudioTest");
} else {
ExternalInterface.call("stopWebrtcAudioTest");
}
}
// Added by Chad to enable closing the window without clicking the X
private function handleKeyDown(event:KeyboardEvent):void {
if (event.charCode == Keyboard.ESCAPE) {
@ -161,25 +158,25 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
LogUtil.warn("Access to microphone has been denied.");
break;
case "Microphone.Unmuted":
// mic.setLoopBack(true);
// mic.setUseEchoSuppression(true);
// mic.setLoopBack(true);
// mic.setUseEchoSuppression(true);
LogUtil.debug("Access to the microphone has been allowed.");
testMicrophone();
break;
default:
LogUtil.debug("unknown micStatusHandler event: " + event);
}
}
}
private function updateMicLevel(e:TimerEvent):void{
if (mic != null) {
if (mic.activityLevel > biggestMicLevel) {
biggestMicLevel = mic.activityLevel;
}
if (chromeAllow && mic.activityLevel > 0){
PopUpManager.removePopUp(chromeAllow);
}
//LogUtil.debug("Mic level: " + mic.activityLevel);
if (mic.activityLevel > biggestMicLevel) {
biggestMicLevel = mic.activityLevel;
}
if (chromeAllow && mic.activityLevel > 0){
PopUpManager.removePopUp(chromeAllow);
}
//LogUtil.debug("Mic level: " + mic.activityLevel);
micLevel.setProgress(mic.activityLevel, 100);
}
}
@ -196,14 +193,18 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
private function showChromeAllow():void{
userBrowser = ExternalInterface.call("determineBrowser");
if (userBrowser == "Chrome"){
chromeAllow = new ChromeAllow();
PopUpManager.addPopUp(chromeAllow, this, false);
}
userBrowser = ExternalInterface.call("determineBrowser");
if (userBrowser == "Chrome"){
chromeAllow = new ChromeAllow();
PopUpManager.addPopUp(chromeAllow, this, false);
}
}
/*
public function hideChromeAllow():void{
PopUpManager.removePopUp(chromeAllow);
}
/*
private function showMicSettingsPanel():void {
if (settingBtn.selected) {
if (mic != null) {
@ -223,19 +224,15 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
*/
private function onJoinClicked():void {
private function onJoinClicked():void {
LogUtil.debug("Biggest activity level detected for " + micName + ": " + biggestMicLevel );
// Do one last check for if the mic has been allowed.
// This must come first because cleanUp() will destroy mic
if (mic != null && mic.muted) {
Security.showSettings(SecurityPanel.PRIVACY);
}
if (biggestMicLevel > 0){
if (biggestMicLevel > 0 || useWebrtcIfAvailable){
joinConference();
} else {
var micWarning:MicWarning = new MicWarning();
@ -243,141 +240,260 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
PopUpManager.addPopUp(micWarning, this, true);
PopUpManager.centerPopUp(micWarning);
}
}
public function joinConference():void{
var joinEvent:BBBEvent = new BBBEvent("JOIN_VOICE_CONFERENCE_EVENT");
joinEvent.payload['useMicrophone'] = true;
joinEvent.payload['microphoneIndex'] = mic.index;
joinEvent.payload['microphoneIndex'] = mic == null ? 0 : mic.index;
joinEvent.payload['useWebrtcIfAvailable'] = useWebrtcIfAvailable;
if (settingBtn.selected) {
ExternalInterface.call("stopWebrtcAudioTest");
}
dispatchEvent(joinEvent);
// Do one last check for if the mic has been allowed.
// This must come first because cleanUp() will destroy mic
if (mic != null && mic.muted) {
Security.showSettings(SecurityPanel.PRIVACY);
}
cleanUp();
PopUpManager.removePopUp(this);
}
private function onCancelClicked():void {
cleanUp();
var event:BBBEvent = new BBBEvent(BBBEvent.MIC_SETTINGS_CLOSED);
event.payload['clicked'] = "cancel";
hideChromeAllow();
dispatchEvent(event);
PopUpManager.removePopUp(this);
}
private function cleanUp():void {
hideChromeAllow();
if (timer) timer.stop();
mic.setLoopBack(false);
mic = null;
if (playingAudio) soundChannel.stop();
if (webrtcCapable) {
//ExternalInterface.call("stopWebrtcAudioTest");
}
if (mic) {
mic.setLoopBack(false);
mic = null;
}
settingBtn.removeEventListener(MouseEvent.CLICK, webrtcTestCall);
//settingBtn.removeEventListener(MouseEvent.CLICK, showMicSettingsPanel);
}
private function changeRecordVolume(event:SliderEvent):void {
var currentSlider:Slider=Slider(event.currentTarget);
mic.gain = currentSlider.value
}
var currentSlider:Slider=Slider(event.currentTarget);
mic.gain = currentSlider.value
}
private var DEFAULT_HELP_URL:String = "http://www.bigbluebutton.org/content/videos";
private function onHelpButtonClicked():void {
DEFAULT_HELP_URL = BBB.initConfigManager().config.help.url;
DEFAULT_HELP_URL = BBB.initConfigManager().config.help.url;
navigateToURL(new URLRequest(DEFAULT_HELP_URL));
}
private function dontUseWebrtc():void {
cleanUp();
if (settingBtn.selected) {
ExternalInterface.call("stopWebrtcAudioTest");
}
useWebrtcIfAvailable = false;
dontUseWebrtcBtn.enabled = false;
dontUseWebrtcBtn.label = "WebRTC won't be used";
dontUseWebrtcBtn.toolTip = "Close the dialog and open again to reactivate";
initDefaultMic();
}
public function set webrtcCapable(value:Boolean):void {
_webrtcCapable = value;
}
[Bindable]
public function get webrtcCapable():Boolean {
return _webrtcCapable;
}
public function set useWebrtcIfAvailable(value:Boolean):void {
_useWebrtcIfAvailable = value;
}
[Bindable]
public function get useWebrtcIfAvailable():Boolean {
return _useWebrtcIfAvailable;
}
]]>
</mx:Script>
<mx:VBox width="100%" height="100%" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5">
<mx:Canvas width="100%">
<!-- mx:Label text="Audio Settings" styleName="micSettingsWindowTitleStyle"/ -->
<mx:TextArea borderSkin="{null}" editable="false" text="{ResourceUtil.getInstance().getString('bbb.users.settings.audioSettings')}" styleName="micSettingsWindowTitleStyle"
tabIndex="{baseIndex}" width="400" left="0"/>
<!-- accessibilityName="{ResourceUtil.getInstance().getString('bbb.micSettings.access.title')} "/ -->
<mx:LinkButton fontSize="10" toolTip="{ResourceUtil.getInstance().getString('bbb.mainToolbar.helpBtn')}"
styleName="micSettingsWindowHelpButtonStyle" right="0"
click="onHelpButtonClicked()"
tabIndex="{baseIndex+1}"
accessibilityName="{ResourceUtil.getInstance().getString('bbb.micSettings.access.helpButton')}"/>
</mx:Canvas>
<!-- <mx:VBox width="100%" paddingTop="5">
<!-- Audio Settings Title and help button -->
<mx:Canvas width="100%">
<mx:TextArea borderSkin="{null}"
editable="false"
text="{ResourceUtil.getInstance().getString('bbb.users.settings.audioSettings')}"
styleName="micSettingsWindowTitleStyle"
tabIndex="{baseIndex}"
width="400"
left="0"/>
<!-- accessibilityName="{ResourceUtil.getInstance().getString('bbb.micSettings.access.title')} "/ -->
<mx:LinkButton toolTip="{ResourceUtil.getInstance().getString('bbb.mainToolbar.helpBtn')}"
label="?"
styleName="micSettingsWindowHelpButtonStyle"
right="0"
height="22"
click="onHelpButtonClicked()"
tabIndex="{baseIndex+1}"
accessibilityName="{ResourceUtil.getInstance().getString('bbb.micSettings.access.helpButton')}"/>
</mx:Canvas>
<!-- WebRTC microphone -->
<!-- <mx:VBox width="100%"
paddingTop="5"
visible="{useWebrtcIfAvailable}"
includeInLayout="{useWebrtcIfAvailable}">
<mx:HRule width="100%"/>
<mx:Label id="testMicLabel" text="{ResourceUtil.getInstance().getString('bbb.micSettings.microphone.header')}" styleName="micSettingsWindowTestMicrophoneLabelStyle" width="100%" tabIndex="{baseIndex+2}"/>
<mx:Label id="testMicLabel"
text="{ResourceUtil.getInstance().getString('bbb.micSettings.microphone.header')}"
styleName="micSettingsWindowTestMicrophoneLabelStyle"
width="100%"
tabIndex="{baseIndex+2}"/>
</mx:VBox>
<mx:HBox width="100%">
<mx:Text width="100%" text="{ResourceUtil.getInstance().getString('bbb.micSettings.speakIntoMic')}"
styleName="micSettingsWindowSpeakIntoMicLabelStyle" tabIndex="{baseIndex+3}"/>
<mx:Button id="settingBtn" label="{ResourceUtil.getInstance().getString('bbb.micSettings.changeMic')}"
styleName="micSettingsWindowChangeMicButtonStyle" toggle="true"
click="showMicSettingsPanel()" tabIndex="{baseIndex+4}"
toolTip="{ResourceUtil.getInstance().getString('bbb.micSettings.changeMic.toolTip')}"/>
<mx:HBox width="100%"
visible="{useWebrtcIfAvailable}"
includeInLayout="{useWebrtcIfAvailable}">
<mx:Text id="settingTxt"
width="100%"
text="{ResourceUtil.getInstance().getString('bbb.micSettings.speakIntoMic')}"
styleName="micSettingsWindowSpeakIntoMicLabelStyle"
tabIndex="{baseIndex+3}"/>
<mx:Button id="settingBtn"
label="{ResourceUtil.getInstance().getString('bbb.micSettings.changeMic')}"
styleName="micSettingsWindowChangeMicButtonStyle"
toggle="true"
tabIndex="{baseIndex+4}"
toolTip="{ResourceUtil.getInstance().getString('bbb.micSettings.changeMic.toolTip')}"/>
</mx:HBox>
-->
<mx:VBox width="100%" paddingTop="5">
<mx:HRule width="100%"/>
<mx:Label id="testMicLabel"
text="Microphone"
styleName="micSettingsWindowTestMicrophoneLabelStyle"
width="100%"
tabIndex="{baseIndex+2}"/>
<mx:Text width="100%"
text="Choose a microphone and check if the activity level increases its level when you talk" />
</mx:VBox>
-->
<mx:HBox width="100%">
<mx:ComboBox id="comboMicList"
dataProvider="{microphoneList}"
change="selectMicrophone(event)"
height="30" />
<!-- Flash Microphone -->
<mx:VBox width="100%"
visible="{!useWebrtcIfAvailable}"
includeInLayout="{!useWebrtcIfAvailable}">
<mx:HRule width="100%"/>
<mx:HBox>
<mx:ComboBox id="comboMicList"
dataProvider="{microphoneList}"
change="selectMicrophone(event)"
height="30"
tabIndex="{baseIndex+2}"
toolTip="{ResourceUtil.getInstance().getString('bbb.micSettings.comboMicList.toolTip')}" />
<mx:HSlider id="micRecordVolume"
maximum="100"
snapInterval="1"
labels="[0%,{ResourceUtil.getInstance().getString('bbb.micSettings.micRecordVolume.label')},100%]"
tickInterval="10"
liveDragging="true"
change="changeRecordVolume(event);"
showTrackHighlight="true"
trackColors="[ 0xEEEEEE, 0xFFFFFF ]"
value="60"
tabIndex="{baseIndex+3}"
toolTip="{ResourceUtil.getInstance().getString('bbb.micSettings.micRecordVolume.toolTip')}" />
</mx:HBox>
<mx:ProgressBar id="micLevel"
minimum="0"
maximum="100"
direction="right"
label=""
mode="manual"
visible="true"
width="450"
height="27"
trackHeight="25"
verticalGap="-20"
tabIndex="{baseIndex+4}" />
</mx:VBox>
<!-- Choose between WebRTC and Flash -->
<mx:VBox width="100%" visible="{useWebrtcIfAvailable}" includeInLayout="{useWebrtcIfAvailable}">
<!-- <mx:Label id="webrtcSupportLabel"
text="{ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.title')}"
styleName="micSettingsWindowTestSpeakersLabelStyle"
paddingTop="5"
tabIndex="{baseIndex+8}"/>
-->
<mx:HRule width="100%"/>
<mx:HBox width="100%">
<mx:VBox width="100%" visible="{webrtcCapable}" includeInLayout="{webrtcCapable}">
<mx:Label id="webrtcSupportLabel"
text="{ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.capableBrowser')}"
styleName="micSettingsWindowTestSpeakersLabelStyle"
paddingTop="5"
tabIndex="{baseIndex+8}"/>
<!-- <mx:Text width="100%"
text="{ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.capableBrowser')}"
styleName="micSettingsWindowHearFromHeadsetLabelStyle"
tabIndex="{baseIndex+9}"/>
-->
<mx:HBox width="100%">
<mx:Button id="settingBtn"
label="{ResourceUtil.getInstance().getString('bbb.micSettings.changeMic')}"
styleName="micSettingsWindowChangeMicButtonStyle"
toggle="true"
tabIndex="{baseIndex+4}"
toolTip="{ResourceUtil.getInstance().getString('bbb.micSettings.changeMic.toolTip')}"/>
<mx:Button id="dontUseWebrtcBtn"
label="{ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.capableBrowser.dontuseit')}"
click="dontUseWebrtc()"
styleName="micSettingsWindowPlaySoundButtonStyle"
toolTip="{ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.capableBrowser.dontuseit.toolTip')}"
tabIndex="{baseIndex+10}" />
</mx:HBox>
</mx:VBox>
<!-- Not webrtc capable browser message -->
<mx:HBox width="100%" visible="{!webrtcCapable}" includeInLayout="{!webrtcCapable}">
<mx:Text width="100%"
text="{ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.notCapableBrowser')}"
styleName="micSettingsWindowHearFromHeadsetLabelStyle"
tabIndex="{baseIndex+11}"/>
</mx:HBox>
</mx:HBox>
</mx:VBox>
<!-- Play Sound, Join and Cancel buttons -->
<mx:HRule width="100%"/>
<mx:Spacer height="10"/>
<mx:HBox width="100%" horizontalAlign="right" horizontalGap="18">
<mx:Button id="playButton" label="{ResourceUtil.getInstance().getString('bbb.micSettings.playSound')}"
click="playButtonClickHandler()" toggle="true" styleName="micSettingsWindowPlaySoundButtonStyle"
toolTip="{ResourceUtil.getInstance().getString('bbb.micSettings.playSound.toolTip')}"
tabIndex="{baseIndex+7}" />
<mx:Button id="okBtn"
label="{ResourceUtil.getInstance().getString('bbb.micSettings.join')}"
styleName="micSettingsWindowJoinButtonStyle"
click="onJoinClicked()" tabIndex="{baseIndex+8}"
toolTip="{ResourceUtil.getInstance().getString('bbb.micSettings.join.toolTip')}"/>
<mx:Button id="cancelBtn" label="{ResourceUtil.getInstance().getString('bbb.micSettings.cancel')}"
styleName="micSettingsWindowCancelButtonStyle"
click="onCancelClicked()" tabIndex="{baseIndex+9}"
toolTip="{ResourceUtil.getInstance().getString('bbb.micSettings.cancel.toolTip')}"/>
</mx:HBox>
</mx:VBox>
<mx:ProgressBar id="micLevel"
minimum="0"
maximum="100"
labelPlacement="top"
label=" Activity level "
direction="right"
mode="manual"
visible="true"
width="120" />
<mx:HSlider id="micRecordVolume"
maximum="100"
snapInterval="1"
labels="[0%,Record Volume,100%]"
tickInterval="10"
liveDragging="true"
change="changeRecordVolume(event);"
showTrackHighlight="true"
trackColors="[ 0xEEEEEE, 0xFFFFFF ]"
value="60"/>
</mx:HBox>
<mx:Label id="testSpeakersLabel"
text="{ResourceUtil.getInstance().getString('bbb.micSettings.speakers.header')}"
styleName="micSettingsWindowTestSpeakersLabelStyle"
paddingTop="5"
tabIndex="{baseIndex+5}"/>
<mx:HBox width="100%">
<mx:Text width="100%" text="{ResourceUtil.getInstance().getString('bbb.micSettings.hearFromHeadset')}"
styleName="micSettingsWindowHearFromHeadsetLabelStyle" tabIndex="{baseIndex+6}"/>
<mx:Button id="playButton" label="{ResourceUtil.getInstance().getString('bbb.micSettings.playSound')}"
click="playButtonClickHandler()" toggle="true" styleName="micSettingsWindowPlaySoundButtonStyle"
toolTip="{ResourceUtil.getInstance().getString('bbb.micSettings.playSound.toolTip')}"
tabIndex="{baseIndex+7}" />
</mx:HBox>
<mx:HRule width="100%"/>
<mx:Spacer height="20"/>
<mx:HBox width="100%" horizontalAlign="right" horizontalGap="18">
<mx:Button id="okBtn" label="{ResourceUtil.getInstance().getString('bbb.micSettings.join')}"
styleName="micSettingsWindowJoinButtonStyle"
click="onJoinClicked()" tabIndex="{baseIndex+8}"/>
<mx:Button id="cancelBtn" label="{ResourceUtil.getInstance().getString('bbb.micSettings.cancel')}"
styleName="micSettingsWindowCancelButtonStyle"
click="onCancelClicked()" tabIndex="{baseIndex+9}"
toolTip="{ResourceUtil.getInstance().getString('bbb.micSettings.cancel.toolTip')}"/>
</mx:HBox>
</mx:VBox>
</mx:TitleWindow>

View File

@ -1,26 +1,26 @@
<?xml version="1.0"?>
<!-- containers\layouts\myComponents\MyLoginForm.mxml -->
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:mate="http://mate.asfusion.com/"
width="600"
height="350"
styleName="micSettingsWindowStyle">
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
public var micsettings:MicSettings;
private function joinAnyway():void {
PopUpManager.removePopUp(this);
micsettings.joinConference();
}
]]>
</mx:Script>
<mx:Text width="100%" text="Your microphone did not show any activity, you won't be able to hear anything during the session." />
<mx:HBox>
<mx:Button click="joinAnyway();" label="Join anyway"/>
<mx:Button label="Test again" click="PopUpManager.removePopUp(this);"/>
</mx:HBox>
xmlns:mate="http://mate.asfusion.com/"
width="400"
horizontalAlign="center"
title="{ResourceUtil.getInstance().getString('bbb.micWarning.title')}" >
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import org.bigbluebutton.util.i18n.ResourceUtil;
public var micsettings:MicSettings;
private function joinAnyway():void {
PopUpManager.removePopUp(this);
micsettings.joinConference();
}
]]>
</mx:Script>
<mx:Text width="100%" textAlign="center" text="{ResourceUtil.getInstance().getString('bbb.micWarning.message')}" />
<mx:HBox>
<mx:Button label="{ResourceUtil.getInstance().getString('bbb.micWarning.joinBtn.label')}" click="joinAnyway();" />
<mx:Button label="{ResourceUtil.getInstance().getString('bbb.micWarning.testAgain.label')}" click="PopUpManager.removePopUp(this);"/>
</mx:HBox>
</mx:TitleWindow>

View File

@ -18,8 +18,8 @@
*/
package org.bigbluebutton.modules.chat.model
{
import org.bigbluebutton.core.BBB;
import org.bigbluebutton.common.LogUtil;
import org.bigbluebutton.core.BBB;
public class ChatOptions
{
@ -37,6 +37,9 @@ package org.bigbluebutton.modules.chat.model
[Bindable] public var baseTabIndex:int;
[Bindable]
public var colorPickerIsVisible:Boolean = false;
public function ChatOptions() {
var cxml:XML = BBB.getConfigForModule("ChatModule");
if (cxml != null) {
@ -52,6 +55,9 @@ package org.bigbluebutton.modules.chat.model
else{
baseTabIndex = 701;
}
if(cxml.@colorPickerIsVisible != undefined) {
colorPickerIsVisible = (cxml.@colorPickerIsVisible.toString().toUpperCase() == "TRUE") ? true : false;
}
}
}

View File

@ -58,9 +58,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<mate:Listener type="{ShortcutEvent.FOCUS_CHAT_INPUT}" method="focusChatInput" />
<mate:Listener type="{UserLeftEvent.LEFT}" method="handleUserLeftEvent"/>
<mate:Listener type="{ShortcutEvent.FOCUS_CHAT_BOX}" method="focusChatBox" />
<!--mate:Listener type="{ShortcutEvent.CHANGE_FONT_COLOUR}" method="focusColourPicker" /-->
<mate:Listener type="{ShortcutEvent.CHANGE_FONT_COLOUR}" method="focusColourPicker" />
<mate:Listener type="{ShortcutEvent.SEND_MESSAGE}" method="remoteSendMessage" />
<mate:Listener type="{ShortcutEvent.CHAT_DEBUG}" method="chatDebugInfo" />
<mate:Listener type="{LockControlEvent.CHANGED_LOCK_SETTINGS}" method="lockSettingsChanged" />
@ -68,14 +67,14 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<mx:Script>
<![CDATA[
import com.adobe.utils.StringUtil;
import com.asfusion.mate.events.Dispatcher;
import com.asfusion.mate.events.Dispatcher;
import flash.accessibility.AccessibilityProperties;
import flash.accessibility.AccessibilityProperties;
import mx.binding.utils.BindingUtils;
import mx.collections.ArrayCollection;
import mx.controls.Button;
import mx.core.ScrollPolicy;
import mx.core.ScrollPolicy;
import org.bigbluebutton.common.LogUtil;
import org.bigbluebutton.core.UsersUtil;
@ -96,9 +95,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.modules.chat.events.TranscriptEvent;
import org.bigbluebutton.modules.chat.model.ChatMessage;
import org.bigbluebutton.modules.chat.model.ChatMessages;
import org.bigbluebutton.modules.chat.model.ChatOptions;
import org.bigbluebutton.modules.chat.views.ChatMessageRenderer;
import org.bigbluebutton.modules.chat.vo.ChatMessageVO;
import org.bigbluebutton.util.i18n.ResourceUtil;
public var publicChat:Boolean = false;
public var chatWithUserID:String;
@ -145,6 +146,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
[Bindable]
private var chatListHeight:Number = 100;
[Bindable] public var chatOptions:ChatOptions = new ChatOptions();
private function onCreationComplete():void {
bindToHeightToDetermineHeightOfMessageList();
@ -190,9 +193,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
focusManager.setFocus(chatMessagesList);
}
/*private function focusColourPicker(e:ShortcutEvent):void{
private function focusColourPicker(e:ShortcutEvent):void{
focusManager.setFocus(cmpColorPicker);
}*/
}
private function remoteSendMessage(e:ShortcutEvent):void{
focusManager.setFocus(sendBtn);
@ -550,7 +553,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
cm.chatType = ChatConstants.PUBLIC_CHAT;
cm.fromUserID = UsersUtil.getMyUserID();
cm.fromUsername = UsersUtil.getMyUsername();
cm.fromColor = "0" //default the message colour to black now cmpColorPicker.selectedColor.toString();
// get the color value from ColorPicker
cm.fromColor = cmpColorPicker.selectedColor.toString();
cm.fromLang = ChatUtil.getUserLang();
// Get the current UTC time and the timezone for this sender.
// The receiver will have to convert this to local time.
@ -570,7 +574,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
cm.chatType = ChatConstants.PRIVATE_CHAT;
cm.fromUserID = UsersUtil.getMyUserID();
cm.fromUsername = UsersUtil.getMyUsername();
cm.fromColor = "0" //default the message colour to black now cmpColorPicker.selectedColor.toString();
// get the color value from ColorPicker
cm.fromColor = cmpColorPicker.selectedColor.toString();
cm.fromLang = ChatUtil.getUserLang();
// Get the current UTC time and the timezone for this sender.
@ -640,25 +645,24 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
accessibilityName="{ResourceUtil.getInstance().getString('bbb.chat.messageList')}" />
</mx:HBox>
<mx:HBox id="chatCtrlBar" width="100%" height="50" styleName="chatControlBarStyle" verticalScrollPolicy="off"
<mx:HBox id="chatCtrlBar" width="100%" height="60" styleName="chatControlBarStyle" verticalScrollPolicy="off"
paddingLeft="5" paddingRight="5">
<mx:TextArea id="txtMsgArea" width="100%"
<mx:TextArea id="txtMsgArea" width="100%" height="100%"
styleName="chatControlBarTextMsgStyle"
toolTip="{ResourceUtil.getInstance().getString('bbb.accessibility.chat.chatwindow.input')}"
tabIndex="{baseIndex+1}"
accessibilityName="{ResourceUtil.getInstance().getString('bbb.chat.input.accessibilityName')}"
/>
<mx:VBox verticalScrollPolicy="off">
<mx:Button label="{ResourceUtil.getInstance().getString('bbb.chat.sendBtn')}" id="sendBtn"
accessibilityName="{ResourceUtil.getInstance().getString('bbb.chat.input.accessibilityName')}" />
<mx:VBox verticalScrollPolicy="off" verticalAlign="middle" height="100%" >
<mx:Button label="{ResourceUtil.getInstance().getString('bbb.chat.sendBtn')}" id="sendBtn"
styleName="chatControlBarSendButtonStyle"
toolTip="{ResourceUtil.getInstance().getString('bbb.chat.sendBtn.toolTip')}"
click="sendMessages()"
tabIndex="{baseIndex+2}"
accessibilityName="{ResourceUtil.getInstance().getString('bbb.chat.sendBtn.accessibilityName')}"/>
<!--mx:ColorPicker id="cmpColorPicker" showTextField="false"
toolTip="{ResourceUtil.getInstance().getString('bbb.chat.cmpColorPicker.toolTip')}"
selectedColor="0x000000" dataProvider="{colorPickerColours}" swatchPanelStyleName="chatColorPickerStyle"
tabIndex="{baseIndex+3}"/-->
<mx:ColorPicker id="cmpColorPicker" showTextField="false" width="100%" visible="{chatOptions.colorPickerIsVisible}" includeInLayout="{chatOptions.colorPickerIsVisible}"
toolTip="{ResourceUtil.getInstance().getString('bbb.chat.cmpColorPicker.toolTip')}"
selectedColor="0x000000" dataProvider="{colorPickerColours}" swatchPanelStyleName="chatColorPickerStyle"
tabIndex="{baseIndex+3}" />
</mx:VBox>
</mx:HBox>
</mx:VBox>

View File

@ -18,6 +18,8 @@
*/
package org.bigbluebutton.modules.phone
{
import org.bigbluebutton.core.BBB;
public class PhoneOptions {
[Bindable]
public var showButton:Boolean = true;
@ -30,5 +32,33 @@ package org.bigbluebutton.modules.phone
[Bindable]
public var enabledEchoCancel:Boolean = false;
[Bindable]
public var useWebrtcIfAvailable:Boolean = true;
public function PhoneOptions() {
parseOptions();
}
public function parseOptions():void {
var vxml:XML = BBB.getConfigForModule("PhoneModule");
if (vxml != null) {
if (vxml.@showButton != undefined) {
showButton = (vxml.@showButton.toString().toUpperCase() == "TRUE") ? true : false;
}
if (vxml.@autoJoin != undefined) {
autoJoin = (vxml.@autoJoin.toString().toUpperCase() == "TRUE") ? true : false;
}
if (vxml.@skipCheck != undefined) {
skipCheck = (vxml.@skipCheck.toString().toUpperCase() == "TRUE") ? true : false;
}
if (vxml.@enabledEchoCancel != undefined) {
enabledEchoCancel = (vxml.@enabledEchoCancel.toString().toUpperCase() == "TRUE") ? true : false;
}
if (vxml.@useWebrtcIfAvailable != undefined) {
useWebrtcIfAvailable = (vxml.@useWebrtcIfAvailable.toString().toUpperCase() == "TRUE");
}
}
}
}
}

View File

@ -21,6 +21,7 @@ package org.bigbluebutton.modules.phone.managers {
import com.asfusion.mate.events.Dispatcher;
import flash.events.StatusEvent;
import flash.external.ExternalInterface;
import flash.media.Microphone;
import flash.system.Security;
import flash.system.SecurityPanel;
@ -32,13 +33,13 @@ package org.bigbluebutton.modules.phone.managers {
import org.bigbluebutton.main.events.BBBEvent;
import org.bigbluebutton.modules.phone.PhoneOptions;
import org.bigbluebutton.modules.phone.events.CallConnectedEvent;
public class PhoneManager {
private var connectionManager:ConnectionManager;
private var streamManager:StreamManager;
private var onCall:Boolean = false;
private var attributes:Object;
private var phoneOptions:PhoneOptions;
private var phoneOptions:PhoneOptions = new PhoneOptions();
// If we are joining with microphone or not
private var withMic:Boolean = false;
// If we are auto-rejoining the conference because we got disconnected.
@ -46,38 +47,27 @@ package org.bigbluebutton.modules.phone.managers {
// User has requested to leave the voice conference.
private var userHangup:Boolean = false;
private var mic:Microphone;
private var webrtcCapable:Boolean = false;
private var useWebrtcIfAvailable:Boolean = true;
public function PhoneManager() {
connectionManager = new ConnectionManager();
streamManager = new StreamManager();
webrtcCapable = initWebrtcFlag();
}
private function initWebrtcFlag():Boolean {
return (ExternalInterface.available && ExternalInterface.call("isWebrtcCapable"));
}
public function setModuleAttributes(attributes:Object):void {
this.attributes = attributes;
var vxml:XML = BBB.getConfigForModule("PhoneModule");
phoneOptions = new PhoneOptions();
if (vxml != null) {
phoneOptions.showButton = (vxml.@showButton.toString().toUpperCase() == "TRUE") ? true : false;
phoneOptions.autoJoin = (vxml.@autoJoin.toString().toUpperCase() == "TRUE") ? true : false;
phoneOptions.skipCheck = (vxml.@skipCheck.toString().toUpperCase() == "TRUE") ? true : false;
}
useWebrtcIfAvailable = phoneOptions.useWebrtcIfAvailable;
if (phoneOptions.autoJoin) {
if (phoneOptions.skipCheck || noMicrophone()) {
mic = Microphone.getMicrophone();
if (mic == null) {
joinVoice(false);
} else if (mic.muted) {
Security.showSettings(SecurityPanel.PRIVACY);
mic.addEventListener(StatusEvent.STATUS, micStatusEventHandler);
} else {
joinVoice(true);
}
} else {
var dispatcher:Dispatcher = new Dispatcher();
dispatcher.dispatchEvent(new BBBEvent("SHOW_MIC_SETTINGS"));
}
onClickToJoinVoiceConference();
}
}
@ -114,14 +104,26 @@ package org.bigbluebutton.modules.phone.managers {
}
public function joinVoice(autoJoin:Boolean, microphoneIndex:int = 0):void {
userHangup = false;
setupMic(autoJoin, microphoneIndex);
var uid:String = String(Math.floor(new Date().getTime()));
var uname:String = encodeURIComponent(UsersUtil.getMyExternalUserID() + "-bbbID-" + attributes.username);
connectionManager.connect(uid, attributes.internalUserID, uname , attributes.room, attributes.uri);
var dispatcher:Dispatcher = new Dispatcher();
dispatcher.dispatchEvent(new BBBEvent(BBBEvent.JOIN_VOICE_FOCUS_HEAD));
}
if (webrtcCapable && useWebrtcIfAvailable) {
var s:String = ExternalInterface.call("joinWebRTCVoiceConference()");
trace(s);
} else {
userHangup = false;
setupMic(autoJoin, microphoneIndex);
var uid:String = String(Math.floor(new Date().getTime()));
var uname:String = encodeURIComponent(UsersUtil.getMyExternalUserID() + "-bbbID-" + attributes.username);
connectionManager.connect(uid, attributes.internalUserID, uname , attributes.room, attributes.uri);
var dispatcher:Dispatcher = new Dispatcher();
dispatcher.dispatchEvent(new BBBEvent(BBBEvent.JOIN_VOICE_FOCUS_HEAD));
}
}
public function onJoinVoiceConferenceEvent(args:Object):void {
if (args != null && args.hasOwnProperty('useWebrtcIfAvailable')) {
useWebrtcIfAvailable = args.useWebrtcIfAvailable;
}
joinVoice(args.useMicrophone, args.microphoneIndex);
}
public function rejoin():void {
if (!rejoining && !userHangup) {
@ -138,8 +140,12 @@ package org.bigbluebutton.modules.phone.managers {
}
public function callConnected(event:CallConnectedEvent):void {
setupConnection();
streamManager.callConnected(event.playStreamName, event.publishStreamName, event.codec);
if (webrtcCapable && useWebrtcIfAvailable) {
} else {
setupConnection();
streamManager.callConnected(event.playStreamName, event.publishStreamName, event.codec);
}
onCall = true;
// We have joined the conference. Reset so that if and when we get disconnected, we
// can rejoin automatically.
@ -154,10 +160,55 @@ package org.bigbluebutton.modules.phone.managers {
public function hangup():void {
if (onCall) {
streamManager.stopStreams();
connectionManager.doHangUp();
onCall = false;
if (webrtcCapable && useWebrtcIfAvailable) {
var s:String = ExternalInterface.call("leaveWebRTCVoiceConference()");
trace(s);
} else {
streamManager.stopStreams();
connectionManager.doHangUp();
}
}
}
public function onClickToJoinVoiceConference(args:Object = null):void {
var forceSkipCheck:Boolean = (args != null && args.hasOwnProperty('forceSkipCheck')? args['forceSkipCheck']: false);
webrtcCapable = (args != null && args.hasOwnProperty('webrtcCapable')? args['webrtcCapable']: webrtcCapable);
if (phoneOptions.skipCheck || noMicrophone() || forceSkipCheck) {
if (webrtcCapable && phoneOptions.useWebrtcIfAvailable) {
joinVoice(true);
} else {
mic = Microphone.getMicrophone();
/*
* If the user had no mic, let her join but she'll just be listening.
* We should indicate a warning that the user is joining without mic
* so that he will know that others won't be able to hear him.
*/
if (mic == null) {
joinVoice(false);
} else if (mic.muted) {
// user has disallowed access to the mic
Security.showSettings(SecurityPanel.PRIVACY);
mic.addEventListener(StatusEvent.STATUS, micStatusEventHandler);
} else {
// user has allowed access to the mic already
joinVoice(true);
}
}
} else {
var dispatcher:Dispatcher = new Dispatcher();
var showMicSettings:BBBEvent = new BBBEvent("SHOW_MIC_SETTINGS");
showMicSettings.payload['webrtcCapable'] = webrtcCapable;
showMicSettings.payload['useWebrtcIfAvailable'] = phoneOptions.useWebrtcIfAvailable;
dispatcher.dispatchEvent(showMicSettings);
}
}
public function onClickToLeaveVoiceConference():void {
userRequestedHangup();
}
}
}

View File

@ -70,12 +70,8 @@ package org.bigbluebutton.modules.phone.managers {
}
private function setupMicrophone():void {
var vxml:XML = BBB.getConfigForModule("PhoneModule");
var phoneOptions:PhoneOptions = new PhoneOptions();
if (vxml != null) {
phoneOptions.enabledEchoCancel = (vxml.@enabledEchoCancel.toString().toUpperCase() == "TRUE") ? true : false;
}
if ((BBB.getFlashPlayerVersion() >= 10.3) && (phoneOptions.enabledEchoCancel)) {
LogUtil.debug("Using acoustic echo cancellation.");
mic = Microphone.getEnhancedMicrophone(micIndex);

View File

@ -59,13 +59,21 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<MethodInvoker generator="{PhoneEventMapDelegate}" method="removeToolbarButton"/>
<MethodInvoker generator="{PhoneManager}" method="userRequestedHangup"/>
</EventHandlers>
<EventHandlers type="CLICK_TO_JOIN_VOICE_CONFERENCE_EVENT">
<MethodInvoker generator="{PhoneManager}" method="onClickToJoinVoiceConference" arguments="{event.payload}"/>
</EventHandlers>
<EventHandlers type="CLICK_TO_LEAVE_VOICE_CONFERENCE_EVENT">
<MethodInvoker generator="{PhoneManager}" method="onClickToLeaveVoiceConference" />
</EventHandlers>
<EventHandlers type="LEAVE_VOICE_CONFERENCE_EVENT">
<MethodInvoker generator="{PhoneManager}" method="userRequestedHangup"/>
</EventHandlers>
<EventHandlers type="JOIN_VOICE_CONFERENCE_EVENT">
<MethodInvoker generator="{PhoneManager}" method="joinVoice" arguments="{[event.payload.useMicrophone, event.payload.microphoneIndex]}"/>
<MethodInvoker generator="{PhoneManager}" method="onJoinVoiceConferenceEvent" arguments="{event.payload}" />
</EventHandlers>
<EventHandlers type="{CallConnectedEvent.CALL_CONNECTED_EVENT}">

View File

@ -37,12 +37,6 @@ package org.bigbluebutton.modules.phone.maps
phoneButton = new ToolbarButton();
globalDispatcher = new Dispatcher();
phoneOptions = new PhoneOptions();
var vxml:XML = BBB.getConfigForModule("PhoneModule");
if (vxml != null) {
phoneOptions.showButton = (vxml.@showButton.toString().toUpperCase() == "TRUE") ? true : false;
phoneOptions.autoJoin = (vxml.@autoJoin.toString().toUpperCase() == "TRUE") ? true : false;
phoneOptions.skipCheck = (vxml.@skipCheck.toString().toUpperCase() == "TRUE") ? true : false;
}
}
public function addToolbarButton():void {

View File

@ -24,7 +24,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
icon="{phoneIcon}" click="startPhone()"
mouseOver = "mouseOverHandler(event)"
mouseOut = "mouseOutHandler(event)"
height="24"
toolTip="{ResourceUtil.getInstance().getString('bbb.toolbar.phone.toolTip.start')}"
implements="org.bigbluebutton.common.IBbbToolbarComponent">
@ -61,55 +60,20 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
private var _currentState:Number = DEFAULT_STATE;
[Bindable] public var phoneIcon:Class = images.headsetDefaultIcon;
[Bindable] public var phoneOptions:PhoneOptions = new PhoneOptions();
private function startPhone():void {
// Disable the button right away to prevent the user from clicking
// multiple times.
this.enabled = false;
if (this.selected) {
var vxml:XML = BBB.getConfigForModule("PhoneModule");
var phoneOptions:PhoneOptions = new PhoneOptions();
if (vxml != null) {
phoneOptions.showButton = (vxml.@showButton.toString().toUpperCase() == "TRUE") ? true : false;
phoneOptions.autoJoin = (vxml.@autoJoin.toString().toUpperCase() == "TRUE") ? true : false;
phoneOptions.skipCheck = (vxml.@skipCheck.toString().toUpperCase() == "TRUE") ? true : false;
}
var joinEvent:BBBEvent;
if (phoneOptions.skipCheck || noMicrophone()) {
// need to figure out if the user has a mic and if they do if it's muted ask for access
mic = Microphone.getMicrophone();
if (mic == null) {
/*
* If the user had no mic, let her join but she'll just be listening.
* We should indicate a warning that the user is joining without mic
* so that he will know that others won't be able to hear him.
*/
joinEvent = new BBBEvent("JOIN_VOICE_CONFERENCE_EVENT");
joinEvent.payload['useMicrophone'] = false;
dispatcher.dispatchEvent(joinEvent);
} else if (mic.muted) {
// user has disallowed access to the mic
mic.addEventListener(StatusEvent.STATUS, micStatusEventHandler);
Security.showSettings(SecurityPanel.PRIVACY);
} else {
// user has allowed access to the mic already
joinEvent = new BBBEvent("JOIN_VOICE_CONFERENCE_EVENT");
joinEvent.payload['useMicrophone'] = true;
dispatcher.dispatchEvent(joinEvent);
}
} else {
dispatcher.dispatchEvent(new BBBEvent("SHOW_MIC_SETTINGS"));
}
var event:BBBEvent;
if (this.selected) {
event = new BBBEvent("CLICK_TO_JOIN_VOICE_CONFERENCE_EVENT");
} else {
var leaveEvent:BBBEvent = new BBBEvent("LEAVE_VOICE_CONFERENCE_EVENT");
leaveEvent.payload["userRequested"] = true;
dispatcher.dispatchEvent(leaveEvent);
userJoinedConference(false);
event = new BBBEvent("CLICK_TO_LEAVE_VOICE_CONFERENCE_EVENT");
}
dispatcher.dispatchEvent(event);
}
public function remoteClick(event:ShortcutEvent):void{
@ -118,7 +82,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
private function micStatusEventHandler(event:StatusEvent):void {
var joinEvent:BBBEvent;
var joinEvent:BBBEvent;
switch(event.code) {
case "Microphone.Muted":
LogUtil.warn("Access to microphone has been denied.");
@ -208,16 +172,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
return "Audio button";
}
private function joinVoiceFocusHead(e:Event):void{
private function joinVoiceFocusHead(e:BBBEvent):void{
this.setFocus();
}
/* disabling this for new because it needs more work to work
private function loopToEnd(e:FocusEvent):void {
if (e.target == this && e.shiftKey)
dispatcher.dispatchEvent(new ShortcutEvent(ShortcutEvent.FOCUS_LOOP_END));
}
*/
]]>
</mx:Script>
</mx:Button>

View File

@ -60,7 +60,7 @@ fi
HOST="http://$HOST"
if ! wget $HOST/api -O - --quiet | grep -q SUCCESS; then
if ! wget $HOST/bigbluebutton/api -O - --quiet | grep -q SUCCESS; then
echo "Startup unsuccessful: could not connect to $HOST/api"
exit 1
fi