Merge branch 'master' of github.com:bigbluebutton/bigbluebutton into guest-mobile-access
This commit is contained in:
commit
7b2d2279f9
@ -10,6 +10,7 @@
|
||||
@namespace chat "org.bigbluebutton.lib.settings.views.chat.*";
|
||||
@namespace lock "org.bigbluebutton.lib.settings.views.lock.*";
|
||||
@namespace camera "org.bigbluebutton.lib.settings.views.camera.*";
|
||||
@namespace ex "http://flex.apache.org/experimental/ns";
|
||||
|
||||
@font-face {
|
||||
src : url("../../shared/assets/fonts/SourceSansPro/SourceSansPro-Regular.ttf");
|
||||
@ -84,7 +85,7 @@ global {
|
||||
/* Classes */
|
||||
|
||||
s|Application {
|
||||
backgroundColor : PropertyReference("bbbBlack");
|
||||
backgroundColor : PropertyReference("bbbBlack");
|
||||
}
|
||||
|
||||
s|Button {
|
||||
@ -93,7 +94,7 @@ s|Button {
|
||||
|
||||
/* Loading screen */
|
||||
main|LoadingScreen {
|
||||
color : PropertyReference("white");
|
||||
color : PropertyReference("white");
|
||||
backgroundColor : PropertyReference("bbbBlack");
|
||||
textAlign : center;
|
||||
}
|
||||
@ -101,7 +102,7 @@ main|LoadingScreen {
|
||||
/* Main view */
|
||||
|
||||
main|MainView {
|
||||
backgroundColor : PropertyReference("bbbBlack");
|
||||
backgroundColor : PropertyReference("bbbBlack");
|
||||
}
|
||||
|
||||
main|TopToolbarAIR {
|
||||
@ -110,7 +111,7 @@ main|TopToolbarAIR {
|
||||
|
||||
participants|ParticipantsViewBase, users|UsersViewBase {
|
||||
backgroundColor : PropertyReference("grey100");
|
||||
color : PropertyReference("blue900");
|
||||
color : PropertyReference("blue900");
|
||||
}
|
||||
|
||||
settings|SettingsViewBase, audio|AudioSettingsViewBase, chat|ChatSettingsViewBase, lock|LockSettingsViewBase, camera|CameraSettingsViewBase {
|
||||
@ -119,7 +120,7 @@ settings|SettingsViewBase, audio|AudioSettingsViewBase, chat|ChatSettingsViewBas
|
||||
separatorColor : PropertyReference("grey200");
|
||||
}
|
||||
|
||||
participants|ParticipantsViewBase s|List{
|
||||
participants|ParticipantsViewBase s|List {
|
||||
contentBackgroundColor : PropertyReference("white");
|
||||
}
|
||||
|
||||
@ -134,6 +135,14 @@ libChat|ChatViewBase {
|
||||
inputBorderColor : PropertyReference("grey300");
|
||||
}
|
||||
|
||||
ex|ProgressBar {
|
||||
skinClass : ClassReference("org.bigbluebutton.air.common.views.skins.ProgressBarSkin");
|
||||
fontFamily : SourceSansProMX;
|
||||
trackBackgroundColor : PropertyReference("grey100");
|
||||
barColor : PropertyReference("bbbBlue");
|
||||
percentColor : PropertyReference("white");
|
||||
}
|
||||
|
||||
s|ToggleSwitch {
|
||||
accentColor : PropertyReference("green500");
|
||||
color : PropertyReference("white");
|
||||
@ -142,7 +151,7 @@ s|ToggleSwitch {
|
||||
}
|
||||
|
||||
s|HSlider {
|
||||
skinClass : ClassReference("spark.skins.ios7.HSliderSkin");
|
||||
skinClass : ClassReference("spark.skins.ios7.HSliderSkin");
|
||||
}
|
||||
|
||||
s|CheckBox {
|
||||
@ -177,7 +186,7 @@ libChat|ChatItemRenderer {
|
||||
}
|
||||
|
||||
users|UserItemRenderer {
|
||||
color : PropertyReference("grey700");
|
||||
color : PropertyReference("grey700");
|
||||
}
|
||||
|
||||
settings|SettingsItemRenderer {
|
||||
@ -215,23 +224,27 @@ settings|SettingsItemRenderer {
|
||||
}
|
||||
|
||||
.settingsIcon {
|
||||
iconColor : PropertyReference("grey700");
|
||||
iconColor : PropertyReference("grey700");
|
||||
}
|
||||
|
||||
.chatIcon {
|
||||
color : PropertyReference("grey700");
|
||||
}
|
||||
|
||||
.menuButton {
|
||||
.menuButton, .menuButtonRed {
|
||||
fontFamily : SourceSansPro;
|
||||
backgroundColor : PropertyReference("bbbBlue");
|
||||
selectedBackgroundColor : PropertyReference("bbbGrey");
|
||||
color : PropertyReference("white");
|
||||
iconFont : BBBIcons;
|
||||
iconColor : PropertyReference("white");
|
||||
iconFont : BBBIcons;
|
||||
iconColor : PropertyReference("white");
|
||||
skinClass : ClassReference("org.bigbluebutton.lib.main.views.skins.MenuButtonSkin");
|
||||
}
|
||||
|
||||
.menuButtonRed {
|
||||
backgroundColor : PropertyReference("bbbRed");
|
||||
}
|
||||
|
||||
.participantIcon {
|
||||
color : PropertyReference("grey700");
|
||||
circleColor : PropertyReference("grey700");
|
||||
@ -262,3 +275,7 @@ settings|SettingsItemRenderer {
|
||||
.leaveLabel {
|
||||
color : PropertyReference("blue500");
|
||||
}
|
||||
|
||||
.micLevelProgressBar {
|
||||
showLabel : false;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
applicationComplete="applicationCompleteHandler(event)"
|
||||
preinitialize="preinitializeHandler(event)"
|
||||
styleName="mainshell"
|
||||
xmlns:main="org.bigbluebutton.air.main.views.*">
|
||||
xmlns:main="org.bigbluebutton.air.main.views.*" xmlns:setup="org.as3commons.logging.setup.*">
|
||||
<fx:Style source="../../shared/assets/css/common.css" />
|
||||
<fx:Style source="../../shared/assets/css/bbb-icons.css" />
|
||||
<fx:Style source="Default.css" />
|
||||
@ -107,6 +107,7 @@
|
||||
visible="false"
|
||||
gap="0"
|
||||
horizontalAlign="center">
|
||||
<main:BannerView id="bannerView" width="100%" height="30" visible="false" includeInLayout="false"/>
|
||||
<main:PagesNavigatorView id="pagesNavigatorView"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
@namespace camera "org.bigbluebutton.lib.settings.views.camera.*";
|
||||
|
||||
@namespace voice "org.bigbluebutton.lib.voice.views.*";
|
||||
|
||||
@media (application-dpi: 240) {
|
||||
main|LoadingScreen {
|
||||
fontSize: 25.50;
|
||||
@ -59,12 +61,12 @@
|
||||
}
|
||||
|
||||
libChat|ChatItemRenderer {
|
||||
padding: 10.50;
|
||||
gap: 6.00;
|
||||
leftIndent: 33.00;
|
||||
fontSize: 21.00;
|
||||
nameFontSize: 21.00;
|
||||
timeFontSize: 21.00;
|
||||
padding: 10.50;
|
||||
gap: 6.00;
|
||||
leftIndent: 33.00;
|
||||
fontSize: 21.00;
|
||||
nameFontSize: 21.00;
|
||||
timeFontSize: 21.00;
|
||||
}
|
||||
|
||||
settings|SettingsViewBase, camera|CameraSettingsViewBase {
|
||||
@ -74,10 +76,14 @@
|
||||
audio|AudioSettingsViewBase, chat|ChatSettingsViewBase, lock|LockSettingsViewBase {
|
||||
padding: 22.50;
|
||||
}
|
||||
|
||||
usersAIR|UserDetailsView {
|
||||
groupsPadding : 15.00;
|
||||
}
|
||||
|
||||
voice|EchoTestViewBase {
|
||||
padding: 22.50;
|
||||
}
|
||||
|
||||
usersAIR|UserDetailsView {
|
||||
groupsPadding: 15.00;
|
||||
}
|
||||
|
||||
settings|SettingsItemRenderer {
|
||||
fontSize: 25.50;
|
||||
@ -98,6 +104,10 @@
|
||||
iconSize: 33.00;
|
||||
}
|
||||
|
||||
voice|EchoTestViewBase {
|
||||
padding: 22.50;
|
||||
}
|
||||
|
||||
s|ToggleSwitch {
|
||||
fontSize: 18.00;
|
||||
}
|
||||
@ -179,4 +189,8 @@
|
||||
borderWeight: 1.50;
|
||||
cornerRadius: 3.00;
|
||||
}
|
||||
|
||||
.echoTestLabel {
|
||||
padding: 24.00;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
@namespace camera "org.bigbluebutton.lib.settings.views.camera.*";
|
||||
|
||||
@namespace voice "org.bigbluebutton.lib.voice.views.*";
|
||||
|
||||
@media (application-dpi: 120) {
|
||||
main|LoadingScreen {
|
||||
fontSize: 12.750;
|
||||
@ -59,12 +61,12 @@
|
||||
}
|
||||
|
||||
libChat|ChatItemRenderer {
|
||||
padding: 5.25;
|
||||
gap: 3.00;
|
||||
leftIndent: 16.50;
|
||||
fontSize: 10.50;
|
||||
nameFontSize: 10.50;
|
||||
timeFontSize: 10.50;
|
||||
padding: 5.250;
|
||||
gap: 3.000;
|
||||
leftIndent: 16.500;
|
||||
fontSize: 10.500;
|
||||
nameFontSize: 10.500;
|
||||
timeFontSize: 10.500;
|
||||
}
|
||||
|
||||
settings|SettingsViewBase, camera|CameraSettingsViewBase {
|
||||
@ -74,10 +76,14 @@
|
||||
audio|AudioSettingsViewBase, chat|ChatSettingsViewBase, lock|LockSettingsViewBase {
|
||||
padding: 11.250;
|
||||
}
|
||||
|
||||
usersAIR|UserDetailsView {
|
||||
groupsPadding : 7.500;
|
||||
}
|
||||
|
||||
voice|EchoTestViewBase {
|
||||
padding: 11.250;
|
||||
}
|
||||
|
||||
usersAIR|UserDetailsView {
|
||||
groupsPadding: 7.500;
|
||||
}
|
||||
|
||||
settings|SettingsItemRenderer {
|
||||
fontSize: 12.750;
|
||||
@ -98,6 +104,10 @@
|
||||
iconSize: 16.500;
|
||||
}
|
||||
|
||||
voice|EchoTestViewBase {
|
||||
padding: 11.250;
|
||||
}
|
||||
|
||||
s|ToggleSwitch {
|
||||
fontSize: 9.000;
|
||||
}
|
||||
@ -179,4 +189,8 @@
|
||||
borderWeight: .750;
|
||||
cornerRadius: 1.500;
|
||||
}
|
||||
|
||||
.echoTestLabel {
|
||||
padding: 12.000;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
@namespace camera "org.bigbluebutton.lib.settings.views.camera.*";
|
||||
|
||||
@namespace voice "org.bigbluebutton.lib.voice.views.*";
|
||||
|
||||
@media (application-dpi: 160) {
|
||||
main|LoadingScreen {
|
||||
fontSize: 17.0;
|
||||
@ -59,12 +61,12 @@
|
||||
}
|
||||
|
||||
libChat|ChatItemRenderer {
|
||||
padding: 7.00;
|
||||
gap: 4.00;
|
||||
leftIndent: 22.00;
|
||||
fontSize: 14.00;
|
||||
nameFontSize: 14.00;
|
||||
timeFontSize: 14.00;
|
||||
padding: 7.0;
|
||||
gap: 4.0;
|
||||
leftIndent: 22.0;
|
||||
fontSize: 14.0;
|
||||
nameFontSize: 14.0;
|
||||
timeFontSize: 14.0;
|
||||
}
|
||||
|
||||
settings|SettingsViewBase, camera|CameraSettingsViewBase {
|
||||
@ -74,10 +76,14 @@
|
||||
audio|AudioSettingsViewBase, chat|ChatSettingsViewBase, lock|LockSettingsViewBase {
|
||||
padding: 15.0;
|
||||
}
|
||||
|
||||
usersAIR|UserDetailsView {
|
||||
groupsPadding : 10;
|
||||
}
|
||||
|
||||
voice|EchoTestViewBase {
|
||||
padding: 15.0;
|
||||
}
|
||||
|
||||
usersAIR|UserDetailsView {
|
||||
groupsPadding: 10.0;
|
||||
}
|
||||
|
||||
settings|SettingsItemRenderer {
|
||||
fontSize: 17.0;
|
||||
@ -98,6 +104,10 @@
|
||||
iconSize: 22.0;
|
||||
}
|
||||
|
||||
voice|EchoTestViewBase {
|
||||
padding: 15.0;
|
||||
}
|
||||
|
||||
s|ToggleSwitch {
|
||||
fontSize: 12.0;
|
||||
}
|
||||
@ -179,4 +189,8 @@
|
||||
borderWeight: 1.0;
|
||||
cornerRadius: 2.0;
|
||||
}
|
||||
|
||||
.echoTestLabel {
|
||||
padding: 16.0;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
@namespace chat "org.bigbluebutton.lib.settings.views.chat.*";
|
||||
@namespace lock "org.bigbluebutton.lib.settings.views.lock.*";
|
||||
@namespace camera "org.bigbluebutton.lib.settings.views.camera.*";
|
||||
@namespace voice "org.bigbluebutton.lib.voice.views.*";
|
||||
|
||||
@media (application-dpi: 320) {
|
||||
main|LoadingScreen {
|
||||
@ -63,6 +64,10 @@
|
||||
padding: 30;
|
||||
}
|
||||
|
||||
voice|EchoTestViewBase {
|
||||
padding: 30;
|
||||
}
|
||||
|
||||
usersAIR|UserDetailsView {
|
||||
groupsPadding : 20;
|
||||
}
|
||||
@ -86,6 +91,10 @@
|
||||
iconSize : 44;
|
||||
}
|
||||
|
||||
voice|EchoTestViewBase {
|
||||
padding: 30;
|
||||
}
|
||||
|
||||
s|ToggleSwitch {
|
||||
fontSize : 24;
|
||||
}
|
||||
@ -167,4 +176,8 @@
|
||||
borderWeight : 2;
|
||||
cornerRadius : 4;
|
||||
}
|
||||
|
||||
.echoTestLabel {
|
||||
padding : 32;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
@namespace camera "org.bigbluebutton.lib.settings.views.camera.*";
|
||||
|
||||
@namespace voice "org.bigbluebutton.lib.voice.views.*";
|
||||
|
||||
@media (application-dpi: 480) {
|
||||
main|LoadingScreen {
|
||||
fontSize: 51.0;
|
||||
@ -59,12 +61,12 @@
|
||||
}
|
||||
|
||||
libChat|ChatItemRenderer {
|
||||
padding: 21.00;
|
||||
gap: 12.00;
|
||||
leftIndent: 66.00;
|
||||
fontSize: 42.00;
|
||||
nameFontSize: 42.00;
|
||||
timeFontSize: 42.00;
|
||||
padding: 21.0;
|
||||
gap: 12.0;
|
||||
leftIndent: 66.0;
|
||||
fontSize: 42.0;
|
||||
nameFontSize: 42.0;
|
||||
timeFontSize: 42.0;
|
||||
}
|
||||
|
||||
settings|SettingsViewBase, camera|CameraSettingsViewBase {
|
||||
@ -74,10 +76,14 @@
|
||||
audio|AudioSettingsViewBase, chat|ChatSettingsViewBase, lock|LockSettingsViewBase {
|
||||
padding: 45.0;
|
||||
}
|
||||
|
||||
usersAIR|UserDetailsView {
|
||||
groupsPadding : 30.0;
|
||||
}
|
||||
|
||||
voice|EchoTestViewBase {
|
||||
padding: 45.0;
|
||||
}
|
||||
|
||||
usersAIR|UserDetailsView {
|
||||
groupsPadding: 30.0;
|
||||
}
|
||||
|
||||
settings|SettingsItemRenderer {
|
||||
fontSize: 51.0;
|
||||
@ -98,6 +104,10 @@
|
||||
iconSize: 66.0;
|
||||
}
|
||||
|
||||
voice|EchoTestViewBase {
|
||||
padding: 45.0;
|
||||
}
|
||||
|
||||
s|ToggleSwitch {
|
||||
fontSize: 36.0;
|
||||
}
|
||||
@ -179,4 +189,8 @@
|
||||
borderWeight: 3.0;
|
||||
cornerRadius: 6.0;
|
||||
}
|
||||
|
||||
.echoTestLabel {
|
||||
padding: 48.0;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
@namespace camera "org.bigbluebutton.lib.settings.views.camera.*";
|
||||
|
||||
@namespace voice "org.bigbluebutton.lib.voice.views.*";
|
||||
|
||||
@media (application-dpi: 640) {
|
||||
main|LoadingScreen {
|
||||
fontSize: 68;
|
||||
@ -59,12 +61,12 @@
|
||||
}
|
||||
|
||||
libChat|ChatItemRenderer {
|
||||
padding: 28.00;
|
||||
gap: 16.00;
|
||||
leftIndent: 88.00;
|
||||
fontSize: 56.00;
|
||||
nameFontSize: 56.00;
|
||||
timeFontSize: 56.00;
|
||||
padding: 28;
|
||||
gap: 16;
|
||||
leftIndent: 88;
|
||||
fontSize: 56;
|
||||
nameFontSize: 56;
|
||||
timeFontSize: 56;
|
||||
}
|
||||
|
||||
settings|SettingsViewBase, camera|CameraSettingsViewBase {
|
||||
@ -74,10 +76,14 @@
|
||||
audio|AudioSettingsViewBase, chat|ChatSettingsViewBase, lock|LockSettingsViewBase {
|
||||
padding: 60;
|
||||
}
|
||||
|
||||
usersAIR|UserDetailsView {
|
||||
groupsPadding : 40;
|
||||
}
|
||||
|
||||
voice|EchoTestViewBase {
|
||||
padding: 60;
|
||||
}
|
||||
|
||||
usersAIR|UserDetailsView {
|
||||
groupsPadding: 40;
|
||||
}
|
||||
|
||||
settings|SettingsItemRenderer {
|
||||
fontSize: 68;
|
||||
@ -98,6 +104,10 @@
|
||||
iconSize: 88;
|
||||
}
|
||||
|
||||
voice|EchoTestViewBase {
|
||||
padding: 60;
|
||||
}
|
||||
|
||||
s|ToggleSwitch {
|
||||
fontSize: 48;
|
||||
}
|
||||
@ -179,4 +189,8 @@
|
||||
borderWeight: 4;
|
||||
cornerRadius: 8;
|
||||
}
|
||||
|
||||
.echoTestLabel {
|
||||
padding: 64;
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +42,6 @@ package org.bigbluebutton.air {
|
||||
import org.bigbluebutton.lib.video.services.VideoConnection;
|
||||
import org.bigbluebutton.lib.voice.services.IVoiceConnection;
|
||||
import org.bigbluebutton.lib.voice.services.VoiceConnection;
|
||||
import org.bigbluebutton.lib.whiteboard.services.IWhiteboardService;
|
||||
import org.bigbluebutton.lib.whiteboard.services.WhiteboardService;
|
||||
|
||||
import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap;
|
||||
import robotlegs.bender.framework.api.IConfig;
|
||||
|
@ -7,10 +7,11 @@ package org.bigbluebutton.air.common {
|
||||
import org.bigbluebutton.air.participants.views.ParticipantsView;
|
||||
import org.bigbluebutton.air.settings.views.SettingsView;
|
||||
import org.bigbluebutton.air.settings.views.audio.AudioSettingsView;
|
||||
import org.bigbluebutton.air.voice.views.EchoTestView;
|
||||
import org.bigbluebutton.air.settings.views.camera.CameraSettingsView;
|
||||
import org.bigbluebutton.air.settings.views.chat.ChatSettingsView;
|
||||
import org.bigbluebutton.air.settings.views.lock.LockSettingsView;
|
||||
import org.bigbluebutton.air.users.views.UserDetailsView;
|
||||
import org.bigbluebutton.air.users.views.UserDetailsView;
|
||||
|
||||
public class PageEnum {
|
||||
public static const MAIN:String = "main";
|
||||
@ -39,6 +40,8 @@ package org.bigbluebutton.air.common {
|
||||
|
||||
public static const SETTINGS:String = "Settings";
|
||||
|
||||
public static const ECHOTEST:String = "EchoTest";
|
||||
|
||||
public static const APPLICATION_SETTINGS:String = "ApplicationSettings";
|
||||
|
||||
/**
|
||||
@ -52,6 +55,7 @@ package org.bigbluebutton.air.common {
|
||||
dic[PARTICIPANTS] = ParticipantsView;
|
||||
dic[CHAT] = ChatRoomView;
|
||||
dic[SETTINGS] = SettingsView;
|
||||
dic[ECHOTEST] = EchoTestView;
|
||||
dic[AUDIOSETTINGS] = AudioSettingsView;
|
||||
dic[CAMERASETTINGS] = CameraSettingsView;
|
||||
dic[CHATSETTINGS] = ChatSettingsView;
|
||||
|
@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
// contributor license agreements. See the NOTICE file distributed with
|
||||
// this work for additional information regarding copyright ownership.
|
||||
// The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
// (the "License"); you may not use this file except in compliance with
|
||||
// the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
-->
|
||||
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
|
||||
xmlns:s="library://ns.adobe.com/flex/spark">
|
||||
|
||||
<!--
|
||||
Original file
|
||||
https://github.com/akamud/FlatSpark/blob/master/FlatSparkSkin/src/flatSpark/skins/ProgressBarSkin.mxml
|
||||
-->
|
||||
|
||||
<fx:Metadata>
|
||||
[HostComponent("spark.components.ProgressBar")]
|
||||
</fx:Metadata>
|
||||
|
||||
<fx:Script>
|
||||
<![CDATA[
|
||||
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
|
||||
bgColor.color = getStyle("trackBackgroundColor");
|
||||
bar.color = getStyle("barColor");
|
||||
percentDisplay.setStyle("color", getStyle("percentColor"));
|
||||
percentDisplay.visible = percentDisplay.includeInLayout = getStyle("showLabel");
|
||||
super.updateDisplayList(unscaledWidth, unscaledHeight);
|
||||
}
|
||||
]]>
|
||||
</fx:Script>
|
||||
<s:Rect left="0"
|
||||
minHeight="14"
|
||||
top="0"
|
||||
bottom="0"
|
||||
right="0"
|
||||
radiusX="4">
|
||||
<s:fill>
|
||||
<s:SolidColor id="bgColor" />
|
||||
</s:fill>
|
||||
</s:Rect>
|
||||
<s:Group id="progressGroup"
|
||||
top="0"
|
||||
bottom="0"
|
||||
left="{hostComponent.direction=='left' ? 0 : NaN}"
|
||||
right="{hostComponent.direction=='right' ? 0 : NaN}">
|
||||
<s:Rect left="0"
|
||||
top="0"
|
||||
bottom="0"
|
||||
right="0"
|
||||
radiusX="4">
|
||||
<s:fill>
|
||||
<s:SolidColor id="bar" />
|
||||
</s:fill>
|
||||
</s:Rect>
|
||||
<!--
|
||||
Variant #2 (looks nicer) - uncomment this and remove last Label declaration
|
||||
<s:Label id="percentDisplay"
|
||||
right="2" verticalCenter="0" verticalAlign="middle"
|
||||
visible="{progressBox.width > percentDisplay.width + 4}"
|
||||
includeInLayout="{progressBox.width > percentDisplay.width + 4}"/>
|
||||
-->
|
||||
</s:Group>
|
||||
<s:Label id="percentDisplay"
|
||||
left="2"
|
||||
right="2"
|
||||
verticalCenter="0"
|
||||
verticalAlign="middle"
|
||||
fontFamily="Lato"
|
||||
fontWeight="bold"
|
||||
fontSize="13"
|
||||
textAlign="center" />
|
||||
|
||||
</s:Skin>
|
@ -4,8 +4,11 @@ package org.bigbluebutton.air.main {
|
||||
import org.bigbluebutton.air.main.commands.JoinMeetingCommandAIR;
|
||||
import org.bigbluebutton.air.main.commands.NavigateToCommand;
|
||||
import org.bigbluebutton.air.main.commands.NavigateToSignal;
|
||||
import org.bigbluebutton.air.main.views.BannerView;
|
||||
import org.bigbluebutton.air.main.views.BannerViewMediator;
|
||||
import org.bigbluebutton.air.main.views.LoadingScreen;
|
||||
import org.bigbluebutton.air.main.views.LoadingScreenMediator;
|
||||
import org.bigbluebutton.air.main.views.MenuButtonsMediatorAIR;
|
||||
import org.bigbluebutton.air.main.views.PagesNavigatorView;
|
||||
import org.bigbluebutton.air.main.views.PagesNavigatorViewMediator;
|
||||
import org.bigbluebutton.air.main.views.TopToolbarAIR;
|
||||
@ -13,7 +16,6 @@ package org.bigbluebutton.air.main {
|
||||
import org.bigbluebutton.lib.main.commands.ConnectingFailedSignal;
|
||||
import org.bigbluebutton.lib.main.commands.JoinMeetingSignal;
|
||||
import org.bigbluebutton.lib.main.views.MenuButtonsBase;
|
||||
import org.bigbluebutton.lib.main.views.MenuButtonsMediatorBase;
|
||||
import org.bigbluebutton.lib.main.views.TopToolbarBase;
|
||||
|
||||
import robotlegs.bender.extensions.matching.TypeMatcher;
|
||||
@ -52,8 +54,9 @@ package org.bigbluebutton.air.main {
|
||||
*/
|
||||
mediatorMap.map(LoadingScreen).toMediator(LoadingScreenMediator);
|
||||
mediatorMap.map(PagesNavigatorView).toMediator(PagesNavigatorViewMediator);
|
||||
mediatorMap.map(BannerView).toMediator(BannerViewMediator);
|
||||
mediatorMap.mapMatcher(new TypeMatcher().allOf(TopToolbarBase, TopToolbarAIR)).toMediator(TopToolbarMediatorAIR);
|
||||
mediatorMap.map(MenuButtonsBase).toMediator(MenuButtonsMediatorBase);
|
||||
mediatorMap.map(MenuButtonsBase).toMediator(MenuButtonsMediatorAIR);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,4 @@
|
||||
package org.bigbluebutton.air.main.commands {
|
||||
import mx.core.FlexGlobals;
|
||||
|
||||
import org.bigbluebutton.air.common.PageEnum;
|
||||
import org.bigbluebutton.air.main.models.IUISession;
|
||||
import org.bigbluebutton.lib.main.models.IConferenceParameters;
|
||||
|
35
clients/flash/air-client/src/org/bigbluebutton/air/main/views/BannerView.as
Executable file
35
clients/flash/air-client/src/org/bigbluebutton/air/main/views/BannerView.as
Executable file
@ -0,0 +1,35 @@
|
||||
package org.bigbluebutton.air.main.views
|
||||
{
|
||||
import spark.components.Label;
|
||||
import spark.components.SkinnableContainer;
|
||||
import spark.layouts.HorizontalAlign;
|
||||
import spark.layouts.VerticalAlign;
|
||||
import spark.layouts.VerticalLayout;
|
||||
|
||||
public class BannerView extends SkinnableContainer
|
||||
{
|
||||
private var _stateLabel:Label;
|
||||
|
||||
public function get stateLabel():Label {
|
||||
return _stateLabel;
|
||||
}
|
||||
|
||||
public function BannerView()
|
||||
{
|
||||
super();
|
||||
|
||||
var layout:VerticalLayout = new VerticalLayout();
|
||||
layout.horizontalAlign = HorizontalAlign.CENTER;
|
||||
layout.verticalAlign = VerticalAlign.MIDDLE;
|
||||
this.layout = layout;
|
||||
|
||||
_stateLabel = new Label();
|
||||
_stateLabel.text = "";
|
||||
_stateLabel.percentWidth = 80;
|
||||
addElement(_stateLabel);
|
||||
}
|
||||
|
||||
public function dispose():void {
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package org.bigbluebutton.air.main.views
|
||||
{
|
||||
import org.bigbluebutton.lib.main.models.IConferenceParameters;
|
||||
|
||||
import robotlegs.bender.bundles.mvcs.Mediator;
|
||||
|
||||
public class BannerViewMediator extends Mediator
|
||||
{
|
||||
[Inject]
|
||||
public var view:BannerView;
|
||||
|
||||
[Inject]
|
||||
public var confParams:IConferenceParameters;
|
||||
|
||||
override public function initialize():void {
|
||||
confParams.confParamsLoadedSignal.add(onConfParameLoadedSignal);
|
||||
}
|
||||
|
||||
private function onConfParameLoadedSignal():void {
|
||||
if (confParams.bannerText != null) {
|
||||
view.visible = true;
|
||||
view.includeInLayout = true;
|
||||
view.stateLabel.text = confParams.bannerText;
|
||||
if (confParams.bannerColor != null) {
|
||||
view.setStyle('backgroundColor', confParams.bannerColor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package org.bigbluebutton.air.main.views {
|
||||
import flash.events.MouseEvent;
|
||||
|
||||
import org.bigbluebutton.air.common.PageEnum;
|
||||
import org.bigbluebutton.air.main.models.IUISession;
|
||||
import org.bigbluebutton.lib.main.views.MenuButtonsMediatorBase;
|
||||
|
||||
public class MenuButtonsMediatorAIR extends MenuButtonsMediatorBase {
|
||||
|
||||
[Inject]
|
||||
public var uiSession:IUISession;
|
||||
|
||||
override protected function audioOnOff(e:MouseEvent):void {
|
||||
if (!meetingData.users.me.voiceJoined) {
|
||||
uiSession.pushPage(PageEnum.ECHOTEST);
|
||||
} else {
|
||||
var audioOptions:Object = new Object();
|
||||
audioOptions.shareMic = !meetingData.users.me.voiceJoined;
|
||||
shareMicrophoneSignal.dispatch(audioOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ package org.bigbluebutton.air.main.views {
|
||||
import org.bigbluebutton.lib.chat.models.GroupChat;
|
||||
import org.bigbluebutton.lib.chat.models.IChatMessagesSession;
|
||||
import org.bigbluebutton.lib.main.views.TopToolbarMediatorBase;
|
||||
import org.bigbluebutton.lib.user.models.User2x;
|
||||
import org.bigbluebutton.lib.voice.commands.StopEchoTestSignal;
|
||||
|
||||
public class TopToolbarMediatorAIR extends TopToolbarMediatorBase {
|
||||
|
||||
@ -16,6 +16,9 @@ package org.bigbluebutton.air.main.views {
|
||||
[Inject]
|
||||
public var chatMessagesSession:IChatMessagesSession;
|
||||
|
||||
[Inject]
|
||||
public var stopEchoTestSignal : StopEchoTestSignal;
|
||||
|
||||
override protected function setTitle():void {
|
||||
if (uiSession.currentPage == PageEnum.CHAT) {
|
||||
var chatData:Object = uiSession.currentPageDetails;
|
||||
@ -32,6 +35,8 @@ package org.bigbluebutton.air.main.views {
|
||||
view.titleLabel.text = uiSession.currentPage.replace(/([A-Z])/g, ' $1');
|
||||
} else if (uiSession.currentPage == PageEnum.USER_DETAILS) {
|
||||
view.titleLabel.text = "User Details";
|
||||
} else if (uiSession.currentPage == PageEnum.ECHOTEST) {
|
||||
view.titleLabel.text = "Echo Test";
|
||||
} else {
|
||||
view.titleLabel.text = conferenceParameters.meetingName;
|
||||
}
|
||||
@ -40,6 +45,9 @@ package org.bigbluebutton.air.main.views {
|
||||
override protected function leftButtonClickHandler(e:MouseEvent):void {
|
||||
if (uiSession.currentPage == PageEnum.MAIN) {
|
||||
uiSession.pushPage(PageEnum.PARTICIPANTS);
|
||||
} else if (uiSession.currentPage == PageEnum.ECHOTEST) {
|
||||
stopEchoTestSignal.dispatch();
|
||||
uiSession.popPage();
|
||||
} else {
|
||||
uiSession.popPage();
|
||||
}
|
||||
|
@ -1,191 +1,192 @@
|
||||
package org.bigbluebutton.air.presentation.views.selectwebcam {
|
||||
|
||||
import flash.events.MouseEvent;
|
||||
|
||||
import mx.collections.ArrayCollection;
|
||||
import mx.events.FlexMouseEvent;
|
||||
import mx.resources.ResourceManager;
|
||||
|
||||
import spark.components.SkinnablePopUpContainer;
|
||||
|
||||
import org.bigbluebutton.air.main.models.IUISession;
|
||||
import org.bigbluebutton.lib.main.models.IUserSession;
|
||||
import org.bigbluebutton.lib.user.models.User;
|
||||
import org.bigbluebutton.lib.user.models.UserList;
|
||||
import org.bigbluebutton.lib.video.models.UserStreamName;
|
||||
|
||||
import robotlegs.bender.bundles.mvcs.Mediator;
|
||||
|
||||
public class SelectStreamPopUpMediator extends Mediator {
|
||||
|
||||
[Inject]
|
||||
public var view:ISelectStreamPopUp;
|
||||
|
||||
[Inject]
|
||||
public var userSession:IUserSession;
|
||||
|
||||
[Inject]
|
||||
public var userUISession:IUISession;
|
||||
|
||||
protected var dataProvider:ArrayCollection;
|
||||
|
||||
private var speaker:User = null;
|
||||
|
||||
private var selectedIndex:int = -1;
|
||||
|
||||
private var indexChange:Boolean = false;
|
||||
|
||||
private var displayWebcam:Boolean;
|
||||
|
||||
override public function initialize():void {
|
||||
userSession.userList.userRemovedSignal.add(userRemovedHandler);
|
||||
userSession.userList.userAddedSignal.add(userAddedHandler);
|
||||
userSession.userList.userChangeSignal.add(userChangeHandler);
|
||||
view.streamList.addEventListener(MouseEvent.CLICK, onSelectStream);
|
||||
view.actionButton.addEventListener(MouseEvent.CLICK, clickedActionButton);
|
||||
dataProvider = new ArrayCollection();
|
||||
view.streamList.dataProvider = dataProvider;
|
||||
var users:ArrayCollection = userSession.userList.users;
|
||||
for each (var u:User in users) {
|
||||
if (u.streamName && u.streamName != "" && !dataProvider.contains(u)) {
|
||||
addUserStreamNames(u);
|
||||
}
|
||||
}
|
||||
updateSelectedIndex();
|
||||
view.addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, closePopUp);
|
||||
}
|
||||
|
||||
private function closePopUp(e:FlexMouseEvent):void {
|
||||
view.close(false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateSelectedIndex():void {
|
||||
view.streamList.selectedIndex = selectedIndex;
|
||||
if (selectedIndex == -1) {
|
||||
view.actionButton.enabled = false;
|
||||
view.actionButton.skin.setCurrentState("disabled");
|
||||
view.actionButton.label = ResourceManager.getInstance().getString('resources', 'selectStream.viewWebcam');
|
||||
} else {
|
||||
view.actionButton.enabled = true
|
||||
view.actionButton.skin.setCurrentState("up");
|
||||
if (userUISession.currentStreamName == "" || indexChange) {
|
||||
displayWebcam = true;
|
||||
view.actionButton.label = ResourceManager.getInstance().getString('resources', 'selectStream.viewWebcam');
|
||||
} else {
|
||||
displayWebcam = false;
|
||||
view.actionButton.label = ResourceManager.getInstance().getString('resources', 'selectStream.hideWebcam');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function clickedActionButton(e:MouseEvent):void {
|
||||
var selectedStream:Object = null;
|
||||
if (displayWebcam) {
|
||||
selectedStream = dataProvider.getItemAt(view.streamList.selectedIndex);
|
||||
}
|
||||
(view as SkinnablePopUpContainer).close(true, selectedStream);
|
||||
}
|
||||
|
||||
private function addUserStreamNames(u:User):void {
|
||||
var existingStreamNames:Array = getUserStreamNamesByUserID(u.userID);
|
||||
var streamNames:Array = u.streamName.split("|");
|
||||
for each (var streamName:String in streamNames) {
|
||||
var addNew:Boolean = true;
|
||||
for each (var existingUserStreamName:UserStreamName in existingStreamNames) {
|
||||
if (streamName == existingUserStreamName.streamName) {
|
||||
addNew = false;
|
||||
}
|
||||
}
|
||||
if (addNew) {
|
||||
var userStreamName:UserStreamName = new UserStreamName(streamName, u);
|
||||
dataProvider.addItem(userStreamName);
|
||||
if (streamName == userUISession.currentStreamName) {
|
||||
selectedIndex = dataProvider.getItemIndex(userStreamName);
|
||||
}
|
||||
}
|
||||
}
|
||||
dataProvider.refresh();
|
||||
}
|
||||
|
||||
private function onSelectStream(event:MouseEvent):void {
|
||||
if (view.streamList.selectedIndex != selectedIndex) {
|
||||
indexChange = true;
|
||||
}
|
||||
selectedIndex = view.streamList.selectedIndex;
|
||||
updateSelectedIndex();
|
||||
}
|
||||
|
||||
override public function destroy():void {
|
||||
userSession.userList.userRemovedSignal.remove(userRemovedHandler);
|
||||
userSession.userList.userAddedSignal.remove(userAddedHandler);
|
||||
userSession.userList.userChangeSignal.remove(userChangeHandler);
|
||||
view.streamList.removeEventListener(MouseEvent.CLICK, onSelectStream);
|
||||
view.actionButton.removeEventListener(MouseEvent.CLICK, clickedActionButton);
|
||||
view.removeEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, closePopUp);
|
||||
view.dispose();
|
||||
view = null;
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
private function userAddedHandler(user:User):void {
|
||||
if (user.streamName && user.streamName != "") {
|
||||
var streamNames:Array = user.streamName.split("|");
|
||||
for each (var streamName:String in streamNames) {
|
||||
var userStreamName:UserStreamName = new UserStreamName(streamName, user);
|
||||
dataProvider.addItem(userStreamName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function removeUserFromDataProvider(userID:String):void {
|
||||
for (var item:int; item < dataProvider.length; item++) {
|
||||
if ((dataProvider.getItemAt(item).user as User).userID == userID) {
|
||||
// -- in the end. see: http://stackoverflow.com/questions/4255226/how-to-remove-an-item-while-iterating-over-collection
|
||||
dataProvider.removeItemAt(item--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function userRemovedHandler(userID:String):void {
|
||||
removeUserFromDataProvider(userID);
|
||||
}
|
||||
|
||||
private function getUserStreamNamesByUserID(userID:String):Array {
|
||||
var userStreamNames:Array = new Array();
|
||||
for each (var userStreamName:UserStreamName in dataProvider) {
|
||||
if (userStreamName.user.userID == userID) {
|
||||
userStreamNames.push(userStreamName);
|
||||
}
|
||||
}
|
||||
return userStreamNames;
|
||||
}
|
||||
|
||||
private function userChangeHandler(user:User, property:int):void {
|
||||
if (property == UserList.HAS_STREAM) {
|
||||
var userStreamNames:Array = getUserStreamNamesByUserID(user.userID);
|
||||
for each (var userStreamName:UserStreamName in userStreamNames) {
|
||||
if (!(userStreamName.user.streamName.indexOf(userStreamName.streamName) >= 0)) {
|
||||
dataProvider.removeItemAt(dataProvider.getItemIndex(userStreamName));
|
||||
}
|
||||
}
|
||||
if (user.streamName.split("|").length > userStreamNames.length && user.streamName.length > 0) {
|
||||
var camNumber:int = dataProvider.length;
|
||||
addUserStreamNames(user);
|
||||
}
|
||||
dataProvider.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private function getDisplayedUser():User {
|
||||
for each (var userStreamName:UserStreamName in dataProvider) {
|
||||
if (userStreamName.streamName == userUISession.currentStreamName) {
|
||||
return userStreamName.user;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.bigbluebutton.air.presentation.views.selectwebcam {
|
||||
|
||||
import flash.events.MouseEvent;
|
||||
|
||||
import mx.collections.ArrayCollection;
|
||||
import mx.events.FlexMouseEvent;
|
||||
import mx.resources.ResourceManager;
|
||||
|
||||
import spark.components.SkinnablePopUpContainer;
|
||||
|
||||
import org.bigbluebutton.air.main.models.IUISession;
|
||||
import org.bigbluebutton.lib.main.models.IUserSession;
|
||||
import org.bigbluebutton.lib.user.models.User;
|
||||
import org.bigbluebutton.lib.user.models.User2x;
|
||||
import org.bigbluebutton.lib.user.models.UserList;
|
||||
import org.bigbluebutton.lib.video.models.UserStreamName;
|
||||
|
||||
import robotlegs.bender.bundles.mvcs.Mediator;
|
||||
|
||||
public class SelectStreamPopUpMediator extends Mediator {
|
||||
|
||||
[Inject]
|
||||
public var view:ISelectStreamPopUp;
|
||||
|
||||
[Inject]
|
||||
public var userSession:IUserSession;
|
||||
|
||||
[Inject]
|
||||
public var userUISession:IUISession;
|
||||
|
||||
protected var dataProvider:ArrayCollection;
|
||||
|
||||
private var speaker:User = null;
|
||||
|
||||
private var selectedIndex:int = -1;
|
||||
|
||||
private var indexChange:Boolean = false;
|
||||
|
||||
private var displayWebcam:Boolean;
|
||||
|
||||
override public function initialize():void {
|
||||
userSession.userList.userRemovedSignal.add(userRemovedHandler);
|
||||
userSession.userList.userAddedSignal.add(userAddedHandler);
|
||||
userSession.userList.userChangeSignal.add(userChangeHandler);
|
||||
view.streamList.addEventListener(MouseEvent.CLICK, onSelectStream);
|
||||
view.actionButton.addEventListener(MouseEvent.CLICK, clickedActionButton);
|
||||
dataProvider = new ArrayCollection();
|
||||
view.streamList.dataProvider = dataProvider;
|
||||
var users:ArrayCollection = userSession.userList.users;
|
||||
for each (var u:User in users) {
|
||||
if (u.streamName && u.streamName != "" && !dataProvider.contains(u)) {
|
||||
addUserStreamNames(u);
|
||||
}
|
||||
}
|
||||
updateSelectedIndex();
|
||||
view.addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, closePopUp);
|
||||
}
|
||||
|
||||
private function closePopUp(e:FlexMouseEvent):void {
|
||||
view.close(false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function updateSelectedIndex():void {
|
||||
view.streamList.selectedIndex = selectedIndex;
|
||||
if (selectedIndex == -1) {
|
||||
view.actionButton.enabled = false;
|
||||
view.actionButton.skin.setCurrentState("disabled");
|
||||
view.actionButton.label = ResourceManager.getInstance().getString('resources', 'selectStream.viewWebcam');
|
||||
} else {
|
||||
view.actionButton.enabled = true
|
||||
view.actionButton.skin.setCurrentState("up");
|
||||
if (userUISession.currentStreamName == "" || indexChange) {
|
||||
displayWebcam = true;
|
||||
view.actionButton.label = ResourceManager.getInstance().getString('resources', 'selectStream.viewWebcam');
|
||||
} else {
|
||||
displayWebcam = false;
|
||||
view.actionButton.label = ResourceManager.getInstance().getString('resources', 'selectStream.hideWebcam');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function clickedActionButton(e:MouseEvent):void {
|
||||
var selectedStream:Object = null;
|
||||
if (displayWebcam) {
|
||||
selectedStream = dataProvider.getItemAt(view.streamList.selectedIndex);
|
||||
}
|
||||
(view as SkinnablePopUpContainer).close(true, selectedStream);
|
||||
}
|
||||
|
||||
private function addUserStreamNames(u:User):void {
|
||||
var existingStreamNames:Array = getUserStreamNamesByUserID(u.userID);
|
||||
var streamNames:Array = u.streamName.split("|");
|
||||
for each (var streamName:String in streamNames) {
|
||||
var addNew:Boolean = true;
|
||||
for each (var existingUserStreamName:UserStreamName in existingStreamNames) {
|
||||
if (streamName == existingUserStreamName.streamName) {
|
||||
addNew = false;
|
||||
}
|
||||
}
|
||||
if (addNew) {
|
||||
var userStreamName:UserStreamName = new UserStreamName(streamName, u);
|
||||
dataProvider.addItem(userStreamName);
|
||||
if (streamName == userUISession.currentStreamName) {
|
||||
selectedIndex = dataProvider.getItemIndex(userStreamName);
|
||||
}
|
||||
}
|
||||
}
|
||||
dataProvider.refresh();
|
||||
}
|
||||
|
||||
private function onSelectStream(event:MouseEvent):void {
|
||||
if (view.streamList.selectedIndex != selectedIndex) {
|
||||
indexChange = true;
|
||||
}
|
||||
selectedIndex = view.streamList.selectedIndex;
|
||||
updateSelectedIndex();
|
||||
}
|
||||
|
||||
override public function destroy():void {
|
||||
userSession.userList.userRemovedSignal.remove(userRemovedHandler);
|
||||
userSession.userList.userAddedSignal.remove(userAddedHandler);
|
||||
userSession.userList.userChangeSignal.remove(userChangeHandler);
|
||||
view.streamList.removeEventListener(MouseEvent.CLICK, onSelectStream);
|
||||
view.actionButton.removeEventListener(MouseEvent.CLICK, clickedActionButton);
|
||||
view.removeEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, closePopUp);
|
||||
view.dispose();
|
||||
view = null;
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
private function userAddedHandler(user:User):void {
|
||||
if (user.streamName && user.streamName != "") {
|
||||
var streamNames:Array = user.streamName.split("|");
|
||||
for each (var streamName:String in streamNames) {
|
||||
var userStreamName:UserStreamName = new UserStreamName(streamName, user);
|
||||
dataProvider.addItem(userStreamName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function removeUserFromDataProvider(userID:String):void {
|
||||
for (var item:int; item < dataProvider.length; item++) {
|
||||
if ((dataProvider.getItemAt(item).user as User).userID == userID) {
|
||||
// -- in the end. see: http://stackoverflow.com/questions/4255226/how-to-remove-an-item-while-iterating-over-collection
|
||||
dataProvider.removeItemAt(item--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function userRemovedHandler(userID:String):void {
|
||||
removeUserFromDataProvider(userID);
|
||||
}
|
||||
|
||||
private function getUserStreamNamesByUserID(userID:String):Array {
|
||||
var userStreamNames:Array = new Array();
|
||||
for each (var userStreamName:UserStreamName in dataProvider) {
|
||||
if (userStreamName.user.userID == userID) {
|
||||
userStreamNames.push(userStreamName);
|
||||
}
|
||||
}
|
||||
return userStreamNames;
|
||||
}
|
||||
|
||||
private function userChangeHandler(user:User2x, property:int):void {
|
||||
if (property == UserList.HAS_STREAM) {
|
||||
var userStreamNames:Array = getUserStreamNamesByUserID(user.userID);
|
||||
for each (var userStreamName:UserStreamName in userStreamNames) {
|
||||
if (!(userStreamName.user.streamName.indexOf(userStreamName.streamName) >= 0)) {
|
||||
dataProvider.removeItemAt(dataProvider.getItemIndex(userStreamName));
|
||||
}
|
||||
}
|
||||
if (user.streamName.split("|").length > userStreamNames.length && user.streamName.length > 0) {
|
||||
var camNumber:int = dataProvider.length;
|
||||
addUserStreamNames(user);
|
||||
}
|
||||
dataProvider.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private function getDisplayedUser():User {
|
||||
for each (var userStreamName:UserStreamName in dataProvider) {
|
||||
if (userStreamName.streamName == userUISession.currentStreamName) {
|
||||
return userStreamName.user;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,59 +1,59 @@
|
||||
package org.bigbluebutton.air.settings {
|
||||
|
||||
import org.bigbluebutton.air.settings.views.SettingsViewMediatorAIR;
|
||||
import org.bigbluebutton.air.settings.views.audio.AudioSettingsViewBaseAIR;
|
||||
import org.bigbluebutton.air.settings.views.audio.AudioSettingsViewMediatorAIR;
|
||||
import org.bigbluebutton.air.settings.views.camera.CameraSettingsViewBaseAIR;
|
||||
import org.bigbluebutton.air.settings.views.camera.CameraSettingsViewMediatorAIR;
|
||||
import org.bigbluebutton.air.settings.views.chat.ChatSettingsViewBaseAIR;
|
||||
import org.bigbluebutton.air.settings.views.lock.LockSettingsViewBaseAIR;
|
||||
import org.bigbluebutton.air.settings.views.lock.LockSettingsViewMediatorAIR;
|
||||
import org.bigbluebutton.lib.main.commands.SaveLockSettingsCommand;
|
||||
import org.bigbluebutton.lib.main.commands.SaveLockSettingsSignal;
|
||||
import org.bigbluebutton.lib.settings.views.SettingsViewBase;
|
||||
import org.bigbluebutton.lib.settings.views.audio.AudioSettingsViewBase;
|
||||
import org.bigbluebutton.lib.settings.views.camera.CameraSettingsViewBase;
|
||||
import org.bigbluebutton.lib.settings.views.chat.ChatSettingsViewBase;
|
||||
import org.bigbluebutton.lib.settings.views.chat.ChatSettingsViewMediatorBase;
|
||||
import org.bigbluebutton.lib.settings.views.lock.LockSettingsViewBase;
|
||||
import org.bigbluebutton.lib.video.commands.CameraQualityCommand;
|
||||
import org.bigbluebutton.lib.video.commands.CameraQualitySignal;
|
||||
|
||||
import robotlegs.bender.extensions.matching.TypeMatcher;
|
||||
import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
|
||||
import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap;
|
||||
import robotlegs.bender.framework.api.IConfig;
|
||||
|
||||
public class SettingsConfig implements IConfig {
|
||||
|
||||
[Inject]
|
||||
public var mediatorMap:IMediatorMap;
|
||||
|
||||
[Inject]
|
||||
public var signalCommandMap:ISignalCommandMap;
|
||||
|
||||
public function configure():void {
|
||||
mediators();
|
||||
signals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps view mediators to views.
|
||||
*/
|
||||
private function mediators():void {
|
||||
mediatorMap.map(SettingsViewBase).toMediator(SettingsViewMediatorAIR);
|
||||
mediatorMap.mapMatcher(new TypeMatcher().allOf(AudioSettingsViewBase, AudioSettingsViewBaseAIR)).toMediator(AudioSettingsViewMediatorAIR);
|
||||
mediatorMap.mapMatcher(new TypeMatcher().allOf(CameraSettingsViewBase, CameraSettingsViewBaseAIR)).toMediator(CameraSettingsViewMediatorAIR);
|
||||
mediatorMap.mapMatcher(new TypeMatcher().allOf(ChatSettingsViewBase, ChatSettingsViewBaseAIR)).toMediator(ChatSettingsViewMediatorBase);
|
||||
mediatorMap.mapMatcher(new TypeMatcher().allOf(LockSettingsViewBase, LockSettingsViewBaseAIR)).toMediator(LockSettingsViewMediatorAIR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps signals to commands using the signalCommandMap.
|
||||
*/
|
||||
private function signals():void {
|
||||
signalCommandMap.map(SaveLockSettingsSignal).toCommand(SaveLockSettingsCommand);
|
||||
signalCommandMap.map(CameraQualitySignal).toCommand(CameraQualityCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.bigbluebutton.air.settings {
|
||||
|
||||
import org.bigbluebutton.air.settings.views.SettingsViewMediatorAIR;
|
||||
import org.bigbluebutton.air.settings.views.audio.AudioSettingsViewBaseAIR;
|
||||
import org.bigbluebutton.air.settings.views.audio.AudioSettingsViewMediatorAIR;
|
||||
import org.bigbluebutton.air.settings.views.camera.CameraSettingsViewBaseAIR;
|
||||
import org.bigbluebutton.air.settings.views.camera.CameraSettingsViewMediatorAIR;
|
||||
import org.bigbluebutton.air.settings.views.chat.ChatSettingsViewBaseAIR;
|
||||
import org.bigbluebutton.air.settings.views.lock.LockSettingsViewBaseAIR;
|
||||
import org.bigbluebutton.air.settings.views.lock.LockSettingsViewMediatorAIR;
|
||||
import org.bigbluebutton.lib.main.commands.SaveLockSettingsCommand;
|
||||
import org.bigbluebutton.lib.main.commands.SaveLockSettingsSignal;
|
||||
import org.bigbluebutton.lib.settings.views.SettingsViewBase;
|
||||
import org.bigbluebutton.lib.settings.views.audio.AudioSettingsViewBase;
|
||||
import org.bigbluebutton.lib.settings.views.camera.CameraSettingsViewBase;
|
||||
import org.bigbluebutton.lib.settings.views.chat.ChatSettingsViewBase;
|
||||
import org.bigbluebutton.lib.settings.views.chat.ChatSettingsViewMediatorBase;
|
||||
import org.bigbluebutton.lib.settings.views.lock.LockSettingsViewBase;
|
||||
import org.bigbluebutton.lib.video.commands.CameraQualityCommand;
|
||||
import org.bigbluebutton.lib.video.commands.CameraQualitySignal;
|
||||
|
||||
import robotlegs.bender.extensions.matching.TypeMatcher;
|
||||
import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
|
||||
import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap;
|
||||
import robotlegs.bender.framework.api.IConfig;
|
||||
|
||||
public class SettingsConfig implements IConfig {
|
||||
|
||||
[Inject]
|
||||
public var mediatorMap:IMediatorMap;
|
||||
|
||||
[Inject]
|
||||
public var signalCommandMap:ISignalCommandMap;
|
||||
|
||||
public function configure():void {
|
||||
mediators();
|
||||
signals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps view mediators to views.
|
||||
*/
|
||||
private function mediators():void {
|
||||
mediatorMap.map(SettingsViewBase).toMediator(SettingsViewMediatorAIR);
|
||||
mediatorMap.mapMatcher(new TypeMatcher().allOf(AudioSettingsViewBase, AudioSettingsViewBaseAIR)).toMediator(AudioSettingsViewMediatorAIR);
|
||||
mediatorMap.mapMatcher(new TypeMatcher().allOf(CameraSettingsViewBase, CameraSettingsViewBaseAIR)).toMediator(CameraSettingsViewMediatorAIR);
|
||||
mediatorMap.mapMatcher(new TypeMatcher().allOf(ChatSettingsViewBase, ChatSettingsViewBaseAIR)).toMediator(ChatSettingsViewMediatorBase);
|
||||
mediatorMap.mapMatcher(new TypeMatcher().allOf(LockSettingsViewBase, LockSettingsViewBaseAIR)).toMediator(LockSettingsViewMediatorAIR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps signals to commands using the signalCommandMap.
|
||||
*/
|
||||
private function signals():void {
|
||||
signalCommandMap.map(SaveLockSettingsSignal).toCommand(SaveLockSettingsCommand);
|
||||
signalCommandMap.map(CameraQualitySignal).toCommand(CameraQualityCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,6 @@ package org.bigbluebutton.air.users.views {
|
||||
|
||||
import flash.events.MouseEvent;
|
||||
|
||||
import org.bigbluebutton.air.common.PageEnum;
|
||||
import org.bigbluebutton.air.common.TransitionAnimationEnum;
|
||||
import org.bigbluebutton.air.main.models.IUISession;
|
||||
import org.bigbluebutton.air.users.views.models.UserDetailsVM;
|
||||
import org.bigbluebutton.lib.chat.commands.StartPrivateChatSignal;
|
||||
|
@ -1,38 +1,50 @@
|
||||
package org.bigbluebutton.air.voice {
|
||||
|
||||
import org.bigbluebutton.lib.voice.commands.ShareMicrophoneCommand;
|
||||
import org.bigbluebutton.lib.voice.commands.ShareMicrophoneSignal;
|
||||
|
||||
import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
|
||||
import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap;
|
||||
import robotlegs.bender.framework.api.IConfig;
|
||||
|
||||
public class VoiceConfig implements IConfig {
|
||||
|
||||
[Inject]
|
||||
public var mediatorMap:IMediatorMap;
|
||||
|
||||
[Inject]
|
||||
public var signalCommandMap:ISignalCommandMap;
|
||||
|
||||
public function configure():void {
|
||||
mediators();
|
||||
signals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps view mediators to views.
|
||||
*/
|
||||
private function mediators():void {
|
||||
//mediatorMap.map(IMicButton).toMediator(MicButtonMediator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps signals to commands using the signalCommandMap.
|
||||
*/
|
||||
private function signals():void {
|
||||
signalCommandMap.map(ShareMicrophoneSignal).toCommand(ShareMicrophoneCommand);
|
||||
//signalCommandMap.map(MicrophoneMuteSignal).toCommand(MicrophoneMuteCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.bigbluebutton.air.voice {
|
||||
|
||||
import org.bigbluebutton.air.voice.views.EchoTestViewMediatorAIR;
|
||||
import org.bigbluebutton.lib.voice.commands.MicrophoneMuteCommand;
|
||||
import org.bigbluebutton.lib.voice.commands.MicrophoneMuteSignal;
|
||||
import org.bigbluebutton.lib.voice.commands.ShareMicrophoneCommand;
|
||||
import org.bigbluebutton.lib.voice.commands.ShareMicrophoneSignal;
|
||||
import org.bigbluebutton.lib.voice.commands.StartEchoTestCommand;
|
||||
import org.bigbluebutton.lib.voice.commands.StartEchoTestSignal;
|
||||
import org.bigbluebutton.lib.voice.commands.StopEchoTestCommand;
|
||||
import org.bigbluebutton.lib.voice.commands.StopEchoTestSignal;
|
||||
import org.bigbluebutton.lib.voice.views.EchoTestViewBase;
|
||||
|
||||
import robotlegs.bender.extensions.matching.TypeMatcher;
|
||||
import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
|
||||
import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap;
|
||||
import robotlegs.bender.framework.api.IConfig;
|
||||
|
||||
public class VoiceConfig implements IConfig {
|
||||
|
||||
[Inject]
|
||||
public var mediatorMap:IMediatorMap;
|
||||
|
||||
[Inject]
|
||||
public var signalCommandMap:ISignalCommandMap;
|
||||
|
||||
public function configure():void {
|
||||
mediators();
|
||||
signals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps view mediators to views.
|
||||
*/
|
||||
private function mediators():void {
|
||||
//mediatorMap.map(IMicButton).toMediator(MicButtonMediator);
|
||||
mediatorMap.mapMatcher(new TypeMatcher().allOf(EchoTestViewBase)).toMediator(EchoTestViewMediatorAIR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps signals to commands using the signalCommandMap.
|
||||
*/
|
||||
private function signals():void {
|
||||
signalCommandMap.map(ShareMicrophoneSignal).toCommand(ShareMicrophoneCommand);
|
||||
signalCommandMap.map(StartEchoTestSignal).toCommand(StartEchoTestCommand);
|
||||
signalCommandMap.map(StopEchoTestSignal).toCommand(StopEchoTestCommand);
|
||||
signalCommandMap.map(MicrophoneMuteSignal).toCommand(MicrophoneMuteCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
package org.bigbluebutton.air.voice.views {
|
||||
import spark.layouts.VerticalLayout;
|
||||
|
||||
import org.bigbluebutton.air.common.views.NoTabView;
|
||||
import org.bigbluebutton.air.main.views.TopToolbarAIR;
|
||||
import org.bigbluebutton.lib.voice.views.EchoTestViewBase;
|
||||
import org.osmf.layout.HorizontalAlign;
|
||||
|
||||
public class EchoTestView extends NoTabView {
|
||||
|
||||
private var _echoTestView:EchoTestViewBase;
|
||||
|
||||
public function EchoTestView() {
|
||||
super();
|
||||
|
||||
var vLayout:VerticalLayout = new VerticalLayout();
|
||||
vLayout.gap = 0;
|
||||
vLayout.horizontalAlign = HorizontalAlign.CENTER;
|
||||
layout = vLayout;
|
||||
|
||||
_echoTestView = new EchoTestViewBase();
|
||||
|
||||
addElement(_echoTestView);
|
||||
}
|
||||
|
||||
override protected function createToolbar():TopToolbarAIR {
|
||||
return new TopToolbarEchoTest();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package org.bigbluebutton.air.voice.views {
|
||||
import flash.events.MouseEvent;
|
||||
|
||||
import org.bigbluebutton.air.main.models.IUISession;
|
||||
import org.bigbluebutton.lib.voice.views.EchoTestViewMediator;
|
||||
|
||||
public class EchoTestViewMediatorAIR extends EchoTestViewMediator {
|
||||
|
||||
[Inject]
|
||||
public var uiSession:IUISession;
|
||||
|
||||
public function EchoTestViewMediatorAIR() {
|
||||
super();
|
||||
}
|
||||
|
||||
override protected function yesButtonHandler(e:MouseEvent):void {
|
||||
super.yesButtonHandler(e);
|
||||
uiSession.popPage();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package org.bigbluebutton.air.voice.views {
|
||||
import org.bigbluebutton.air.main.views.TopToolbarAIR;
|
||||
|
||||
public class TopToolbarEchoTest extends TopToolbarAIR {
|
||||
public function TopToolbarEchoTest() {
|
||||
leftButton.styleName = "icon-left-arrow topButton topLeftButton";
|
||||
rightButton.setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
BIN
clients/flash/common-library/libs/as3commons-lang-0.3.7.swc
Normal file
BIN
clients/flash/common-library/libs/as3commons-lang-0.3.7.swc
Normal file
Binary file not shown.
@ -6,7 +6,6 @@ package org.bigbluebutton.lib.chat.views {
|
||||
import mx.utils.StringUtil;
|
||||
|
||||
import spark.components.VScrollBar;
|
||||
import spark.core.NavigationUnit;
|
||||
|
||||
import org.bigbluebutton.lib.chat.models.ChatMessageVO;
|
||||
import org.bigbluebutton.lib.chat.models.GroupChat;
|
||||
|
@ -20,7 +20,7 @@ package org.bigbluebutton.lib.main.commands {
|
||||
import org.bigbluebutton.lib.voice.services.IVoiceConnection;
|
||||
import org.bigbluebutton.lib.whiteboard.services.IWhiteboardService;
|
||||
|
||||
import robotlegs.bender.bundles.mvcs.Command;
|
||||
import robotlegs.bender.bundles.mvcs.Command;
|
||||
|
||||
public class ConnectCommand extends Command {
|
||||
private const LOG:String = "ConnectCommand::";
|
||||
|
@ -12,6 +12,7 @@ package org.bigbluebutton.lib.main.models {
|
||||
*/
|
||||
public class ConferenceParameters implements IConferenceParameters {
|
||||
private var _changedSignal:Signal;
|
||||
private var _confParamsLoadedSignal:Signal = new Signal();
|
||||
|
||||
private var _meetingName:String;
|
||||
|
||||
@ -84,6 +85,9 @@ package org.bigbluebutton.lib.main.models {
|
||||
|
||||
private var _guest:Boolean;
|
||||
|
||||
private var _bannerText:String;
|
||||
private var _bannerColor:String;
|
||||
|
||||
public function ConferenceParameters(signal:Signal = null) {
|
||||
if (signal) {
|
||||
_changedSignal = signal;
|
||||
@ -100,6 +104,10 @@ package org.bigbluebutton.lib.main.models {
|
||||
return _changedSignal;
|
||||
}
|
||||
|
||||
public function get confParamsLoadedSignal():ISignal {
|
||||
return _confParamsLoadedSignal;
|
||||
}
|
||||
|
||||
public function get meetingName():String {
|
||||
return _meetingName;
|
||||
}
|
||||
@ -264,6 +272,9 @@ package org.bigbluebutton.lib.main.models {
|
||||
_avatarUrl = obj.avatarURL;
|
||||
_authToken = obj.authToken;
|
||||
_guest = obj.guest;
|
||||
_bannerColor = obj.bannerColor;
|
||||
_bannerText = obj.bannerText;
|
||||
|
||||
_changedSignal.dispatch();
|
||||
_metadata = new Object();
|
||||
for (var n:String in obj.metadata) {
|
||||
@ -280,6 +291,8 @@ package org.bigbluebutton.lib.main.models {
|
||||
var value:Object = obj[key];
|
||||
trace(key + " = " + value);
|
||||
}
|
||||
|
||||
_confParamsLoadedSignal.dispatch();
|
||||
}
|
||||
|
||||
public function set muteOnStart(mute:Boolean):void {
|
||||
@ -305,5 +318,21 @@ package org.bigbluebutton.lib.main.models {
|
||||
public function set guest(value:Boolean):void {
|
||||
_guest = value;
|
||||
}
|
||||
|
||||
public function get bannerColor():String {
|
||||
return _bannerColor;
|
||||
}
|
||||
|
||||
public function set bannerColor(value:String):void {
|
||||
_bannerColor = value;
|
||||
}
|
||||
|
||||
public function get bannerText():String {
|
||||
return _bannerText;
|
||||
}
|
||||
|
||||
public function set bannerText(value:String):void {
|
||||
_bannerText = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ package org.bigbluebutton.lib.main.models {
|
||||
|
||||
public interface IConferenceParameters {
|
||||
function get changedSignal():ISignal;
|
||||
function get confParamsLoadedSignal():ISignal;
|
||||
function get meetingName():String;
|
||||
function set meetingName(meetingName:String):void;
|
||||
function get externMeetingID():String;
|
||||
@ -46,5 +47,9 @@ package org.bigbluebutton.lib.main.models {
|
||||
function set avatarUrl(value:String):void;
|
||||
function get guest():Boolean;
|
||||
function set guest(v:Boolean):void;
|
||||
function get bannerColor():String;
|
||||
function set bannerColor(value:String):void;
|
||||
function get bannerText():String;
|
||||
function set bannerText(value:String):void;
|
||||
}
|
||||
}
|
||||
|
@ -12,12 +12,12 @@ package org.bigbluebutton.lib.main.models {
|
||||
//public var voiceUsers: VoiceUsers2x = new VoiceUsers2x();
|
||||
//public var guestsWaiting: GuestsApp = new GuestsApp();
|
||||
|
||||
private var _meetingStatus: MeetingStatus = new MeetingStatus();
|
||||
private var _meetingStatus:MeetingStatus = new MeetingStatus();
|
||||
|
||||
public function get meetingStatus():MeetingStatus {
|
||||
return _meetingStatus;
|
||||
}
|
||||
|
||||
|
||||
//public var meeting: Meeting = new Meeting();
|
||||
//public var config: Config;
|
||||
//public var sharedNotes: SharedNotes = new SharedNotes();
|
||||
|
@ -97,7 +97,17 @@ package org.bigbluebutton.lib.main.services {
|
||||
protected function afterEnter(result:Object):void {
|
||||
if (result.returncode == 'SUCCESS') {
|
||||
trace("Join SUCCESS");
|
||||
var user:Object = {username: result.fullname, conference: result.conference, conferenceName: result.confname, externMeetingID: result.externMeetingID, meetingID: result.meetingID, externUserID: result.externUserID, internalUserId: result.internalUserID, role: result.role, room: result.room, authToken: result.authToken, record: result.record, webvoiceconf: result.webvoiceconf, dialnumber: result.dialnumber, voicebridge: result.voicebridge, mode: result.mode, welcome: result.welcome, logoutUrl: result.logoutUrl, defaultLayout: result.defaultLayout, avatarURL: result.avatarURL};
|
||||
var user:Object = {username: result.fullname, conference: result.conference,
|
||||
conferenceName: result.confname, externMeetingID: result.externMeetingID,
|
||||
meetingID: result.meetingID, externUserID: result.externUserID,
|
||||
internalUserId: result.internalUserID, role: result.role, room: result.room,
|
||||
authToken: result.authToken, record: result.record, webvoiceconf: result.webvoiceconf,
|
||||
dialnumber: result.dialnumber, voicebridge: result.voicebridge,
|
||||
mode: result.mode, welcome: result.welcome, logoutUrl: result.logoutUrl,
|
||||
defaultLayout: result.defaultLayout, avatarURL: result.avatarURL,
|
||||
bannerColor: result.bannerColor,
|
||||
bannerText: result.bannerText};
|
||||
|
||||
user.customdata = new Object();
|
||||
if (result.customdata) {
|
||||
for (var key:String in result.customdata) {
|
||||
|
@ -6,7 +6,14 @@ package org.bigbluebutton.lib.main.views {
|
||||
[Style(name = "bottom", inherit = "no", type = "Number")]
|
||||
[Style(name = "gap", inherit = "no", type = "Number")]
|
||||
[Style(name = "top", inherit = "no", type = "Number")]
|
||||
|
||||
public class MenuButtonsBase extends HGroup {
|
||||
private var _audioButton:Button;
|
||||
|
||||
public function get audioButton():Button {
|
||||
return _audioButton;
|
||||
}
|
||||
|
||||
private var _micButton:Button;
|
||||
|
||||
public function get micButton():Button {
|
||||
@ -28,6 +35,12 @@ package org.bigbluebutton.lib.main.views {
|
||||
public function MenuButtonsBase() {
|
||||
super();
|
||||
|
||||
_audioButton = new Button();
|
||||
_audioButton.percentWidth = 100;
|
||||
_audioButton.percentHeight = 100;
|
||||
_audioButton.label = "Join";
|
||||
_audioButton.styleName = "icon-audio-on menuButton";
|
||||
addElement(_audioButton);
|
||||
|
||||
_micButton = new Button();
|
||||
_micButton.percentWidth = 100;
|
||||
|
@ -1,90 +1,119 @@
|
||||
package org.bigbluebutton.lib.main.views {
|
||||
|
||||
import flash.events.MouseEvent;
|
||||
|
||||
import org.bigbluebutton.lib.main.models.IUserSession;
|
||||
import org.bigbluebutton.lib.user.models.User;
|
||||
import org.bigbluebutton.lib.video.commands.ShareCameraSignal;
|
||||
import org.bigbluebutton.lib.voice.commands.ShareMicrophoneSignal;
|
||||
|
||||
import robotlegs.bender.bundles.mvcs.Mediator;
|
||||
|
||||
public class MenuButtonsMediatorBase extends Mediator {
|
||||
|
||||
[Inject]
|
||||
public var userSession:IUserSession;
|
||||
|
||||
[Inject]
|
||||
public var view:MenuButtonsBase;
|
||||
|
||||
[Inject]
|
||||
public var shareCameraSignal:ShareCameraSignal;
|
||||
|
||||
[Inject]
|
||||
public var shareMicrophoneSignal:ShareMicrophoneSignal;
|
||||
|
||||
public override function initialize():void {
|
||||
userSession.userList.userChangeSignal.add(userChanged);
|
||||
view.camButton.addEventListener(MouseEvent.CLICK, camOnOff);
|
||||
view.micButton.addEventListener(MouseEvent.CLICK, micOnOff);
|
||||
view.statusButton.addEventListener(MouseEvent.CLICK, changeStatus);
|
||||
}
|
||||
|
||||
private function changeStatus(e:MouseEvent):void {
|
||||
/*var changeStatusPopUp:ChangeStatusPopUp = new ChangeStatusPopUp();
|
||||
mediatorMap.mediate(changeStatusPopUp);
|
||||
changeStatusPopUp.width = view.width;
|
||||
changeStatusPopUp.height = view.height;
|
||||
changeStatusPopUp.open(view as DisplayObjectContainer, true);
|
||||
|
||||
if (FlexGlobals.topLevelApplication.aspectRatio == "landscape") {
|
||||
changeStatusPopUp.x = view.x + view.statusButton.x;
|
||||
changeStatusPopUp.y = view.y - changeStatusPopUp.height * 2;
|
||||
} else {
|
||||
changeStatusPopUp.x = -(view.width - view.statusButton.x - view.statusButton.width) / 2 - (view.statusButton.width - (view.statusButton.skin as PresentationButtonSkin).backgroundEllipse.width) / 2 + 6;
|
||||
changeStatusPopUp.y = view.y - changeStatusPopUp.height * changeStatusPopUp.statusList.dataProvider.length;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private function micOnOff(e:MouseEvent):void {
|
||||
var audioOptions:Object = new Object();
|
||||
audioOptions.shareMic = !userSession.userList.me.voiceJoined;
|
||||
audioOptions.listenOnly = false;
|
||||
shareMicrophoneSignal.dispatch(audioOptions);
|
||||
}
|
||||
|
||||
private function camOnOff(e:MouseEvent):void {
|
||||
shareCameraSignal.dispatch(!userSession.userList.me.hasStream, userSession.videoConnection.cameraPosition);
|
||||
}
|
||||
|
||||
private function userChanged(user:User, property:String = null):void {
|
||||
if (user && user.me) {
|
||||
if (user.hasStream) {
|
||||
view.camButton.label = "Cam off";// ResourceManager.getInstance().getString('resources', 'menuButtons.camOff');
|
||||
view.camButton.styleName = "icon-video-off menuButton"
|
||||
} else {
|
||||
view.camButton.label = "Cam on";// ResourceManager.getInstance().getString('resources', 'menuButtons.camOn');
|
||||
view.camButton.styleName = "icon-video menuButton"
|
||||
}
|
||||
if (userSession.userList.me.voiceJoined) {
|
||||
view.micButton.label = "Mic off";// ResourceManager.getInstance().getString('resources', 'menuButtons.micOff');
|
||||
view.micButton.styleName = "icon-mute menuButton"
|
||||
} else {
|
||||
view.micButton.label = "Mic on";// ResourceManager.getInstance().getString('resources', 'menuButtons.micOn');
|
||||
view.micButton.styleName = "icon-unmute menuButton"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override function destroy():void {
|
||||
userSession.userList.userChangeSignal.remove(userChanged);
|
||||
view.camButton.removeEventListener(MouseEvent.CLICK, camOnOff);
|
||||
view.micButton.removeEventListener(MouseEvent.CLICK, micOnOff);
|
||||
view.statusButton.removeEventListener(MouseEvent.CLICK, changeStatus);
|
||||
|
||||
super.destroy();
|
||||
view = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.bigbluebutton.lib.main.views {
|
||||
|
||||
import flash.events.MouseEvent;
|
||||
|
||||
import org.bigbluebutton.lib.main.models.IMeetingData;
|
||||
import org.bigbluebutton.lib.main.models.IUserSession;
|
||||
import org.bigbluebutton.lib.user.models.User2x;
|
||||
import org.bigbluebutton.lib.video.commands.ShareCameraSignal;
|
||||
import org.bigbluebutton.lib.voice.commands.MicrophoneMuteSignal;
|
||||
import org.bigbluebutton.lib.voice.commands.ShareMicrophoneSignal;
|
||||
|
||||
import robotlegs.bender.bundles.mvcs.Mediator;
|
||||
|
||||
public class MenuButtonsMediatorBase extends Mediator {
|
||||
|
||||
[Inject]
|
||||
public var userSession:IUserSession;
|
||||
|
||||
[Inject]
|
||||
public var view:MenuButtonsBase;
|
||||
|
||||
[Inject]
|
||||
public var microphoneMuteSignal:MicrophoneMuteSignal;
|
||||
|
||||
[Inject]
|
||||
public var shareCameraSignal:ShareCameraSignal;
|
||||
|
||||
[Inject]
|
||||
public var shareMicrophoneSignal:ShareMicrophoneSignal;
|
||||
|
||||
[Inject]
|
||||
public var meetingData:IMeetingData;
|
||||
|
||||
public override function initialize():void {
|
||||
meetingData.users.userChangeSignal.add(userChanged);
|
||||
view.audioButton.addEventListener(MouseEvent.CLICK, audioOnOff);
|
||||
view.camButton.addEventListener(MouseEvent.CLICK, camOnOff);
|
||||
view.micButton.addEventListener(MouseEvent.CLICK, micOnOff);
|
||||
view.statusButton.addEventListener(MouseEvent.CLICK, changeStatus);
|
||||
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
private function changeStatus(e:MouseEvent):void {
|
||||
/*var changeStatusPopUp:ChangeStatusPopUp = new ChangeStatusPopUp();
|
||||
mediatorMap.mediate(changeStatusPopUp);
|
||||
changeStatusPopUp.width = view.width;
|
||||
changeStatusPopUp.height = view.height;
|
||||
changeStatusPopUp.open(view as DisplayObjectContainer, true);
|
||||
|
||||
if (FlexGlobals.topLevelApplication.aspectRatio == "landscape") {
|
||||
changeStatusPopUp.x = view.x + view.statusButton.x;
|
||||
changeStatusPopUp.y = view.y - changeStatusPopUp.height * 2;
|
||||
} else {
|
||||
changeStatusPopUp.x = -(view.width - view.statusButton.x - view.statusButton.width) / 2 - (view.statusButton.width - (view.statusButton.skin as PresentationButtonSkin).backgroundEllipse.width) / 2 + 6;
|
||||
changeStatusPopUp.y = view.y - changeStatusPopUp.height * changeStatusPopUp.statusList.dataProvider.length;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
protected function micOnOff(e:MouseEvent):void {
|
||||
microphoneMuteSignal.dispatch(meetingData.users.me);
|
||||
}
|
||||
|
||||
protected function audioOnOff(e:MouseEvent):void {
|
||||
}
|
||||
|
||||
private function camOnOff(e:MouseEvent):void {
|
||||
shareCameraSignal.dispatch(!meetingData.users.me.hasStream, userSession.videoConnection.cameraPosition);
|
||||
}
|
||||
|
||||
private function updateButtons():void {
|
||||
if (!meetingData.users.me) {
|
||||
return;
|
||||
}
|
||||
if (meetingData.users.me.hasStream) {
|
||||
view.camButton.label = "Cam off"; // ResourceManager.getInstance().getString('resources', 'menuButtons.camOff');
|
||||
view.camButton.styleName = "icon-video-off menuButton"
|
||||
} else {
|
||||
view.camButton.label = "Cam on"; // ResourceManager.getInstance().getString('resources', 'menuButtons.camOn');
|
||||
view.camButton.styleName = "icon-video menuButton"
|
||||
}
|
||||
if (meetingData.users.me.voiceJoined) {
|
||||
view.micButton.visible = view.micButton.includeInLayout = true;
|
||||
view.audioButton.styleName = "icon-audio-off menuButtonRed";
|
||||
view.audioButton.label = "Hang Up";
|
||||
|
||||
if (!meetingData.users.me.muted) {
|
||||
view.micButton.label = "Mic on"; // ResourceManager.getInstance().getString('resources', 'menuButtons.micOn');
|
||||
view.micButton.styleName = "icon-unmute menuButton"
|
||||
} else {
|
||||
view.micButton.label = "Mic off"; // ResourceManager.getInstance().getString('resources', 'menuButtons.micOff');
|
||||
view.micButton.styleName = "icon-mute menuButton"
|
||||
}
|
||||
} else {
|
||||
view.audioButton.label = "Join";
|
||||
view.audioButton.styleName = "icon-audio-on menuButton";
|
||||
view.micButton.visible = view.micButton.includeInLayout = false;
|
||||
}
|
||||
}
|
||||
|
||||
private function userChanged(user:User2x, property:String = null):void {
|
||||
if (user && meetingData.users.me.intId == user.intId) {
|
||||
updateButtons();
|
||||
}
|
||||
}
|
||||
|
||||
public override function destroy():void {
|
||||
meetingData.users.userChangeSignal.remove(userChanged);
|
||||
view.audioButton.removeEventListener(MouseEvent.CLICK, audioOnOff);
|
||||
view.camButton.removeEventListener(MouseEvent.CLICK, camOnOff);
|
||||
view.micButton.removeEventListener(MouseEvent.CLICK, micOnOff);
|
||||
view.statusButton.removeEventListener(MouseEvent.CLICK, changeStatus);
|
||||
|
||||
super.destroy();
|
||||
view = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,6 +107,9 @@ package org.bigbluebutton.lib.settings.views.audio {
|
||||
|
||||
_gainSlider = new HSlider();
|
||||
_gainSlider.percentWidth = 100;
|
||||
_gainSlider.maximum = 100;
|
||||
_gainSlider.snapInterval = 1;
|
||||
_gainSlider.value = 60;
|
||||
gainSliderGroup.addElement(_gainSlider);
|
||||
|
||||
var fullMicGroup:VGroup = new VGroup();
|
||||
|
@ -1,16 +1,32 @@
|
||||
package org.bigbluebutton.lib.user.models {
|
||||
|
||||
public class User2x {
|
||||
public var intId: String;
|
||||
public var extId: String;
|
||||
public var name: String;
|
||||
public var role: String;
|
||||
public var guest: Boolean;
|
||||
public var authed: Boolean;
|
||||
public var waitingForAcceptance: Boolean;
|
||||
public var emoji: String;
|
||||
public var locked: Boolean;
|
||||
public var presenter: Boolean;
|
||||
public var avatar: String;
|
||||
public var intId:String;
|
||||
|
||||
public var extId:String;
|
||||
|
||||
public var name:String;
|
||||
|
||||
public var role:String;
|
||||
|
||||
public var guest:Boolean;
|
||||
|
||||
public var authed:Boolean;
|
||||
|
||||
public var waitingForAcceptance:Boolean;
|
||||
|
||||
public var emoji:String;
|
||||
|
||||
public var locked:Boolean;
|
||||
|
||||
public var presenter:Boolean;
|
||||
|
||||
public var avatar:String;
|
||||
|
||||
public var voiceJoined:Boolean;
|
||||
|
||||
public var muted:Boolean;
|
||||
|
||||
public var hasStream:Boolean = false;
|
||||
}
|
||||
}
|
||||
|
@ -12,5 +12,9 @@ package org.bigbluebutton.lib.user.models {
|
||||
public static const EMOJI:int = 4;
|
||||
|
||||
public static const ROLE:int = 5;
|
||||
|
||||
public static const AUDIO_JOIN:int = 6;
|
||||
|
||||
public static const AUDIO_LEAVE:int = 7;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ package org.bigbluebutton.lib.user.models {
|
||||
|
||||
public static const LISTEN_ONLY:int = 8;
|
||||
|
||||
public static const LEAVE_AUDIO:int = 9;
|
||||
|
||||
private var _users:ArrayCollection;
|
||||
|
||||
[Bindable]
|
||||
@ -325,7 +327,7 @@ package org.bigbluebutton.lib.user.models {
|
||||
if (user != null) {
|
||||
user.talking = false;
|
||||
user.voiceJoined = false;
|
||||
userChangeSignal.dispatch(user, JOIN_AUDIO);
|
||||
userChangeSignal.dispatch(user, LEAVE_AUDIO);
|
||||
} else {
|
||||
trace("UserList: User leave audio failed - user not found");
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.bigbluebutton.lib.user.models {
|
||||
import mx.collections.ArrayCollection;
|
||||
|
||||
import org.as3commons.lang.StringUtils;
|
||||
import org.osflash.signals.Signal;
|
||||
|
||||
public class Users2x {
|
||||
@ -8,7 +9,17 @@ package org.bigbluebutton.lib.user.models {
|
||||
|
||||
private var _userChangeSignal:Signal = new Signal();
|
||||
|
||||
public var me:User2x;
|
||||
private var _me:User2x;
|
||||
|
||||
public function get me():User2x {
|
||||
return _me;
|
||||
}
|
||||
|
||||
public function set me(value:User2x):void {
|
||||
if (StringUtils.isEmpty(_me.extId)) {
|
||||
_me = value;
|
||||
}
|
||||
}
|
||||
|
||||
public function get userChangeSignal():Signal {
|
||||
return _userChangeSignal;
|
||||
@ -16,6 +27,7 @@ package org.bigbluebutton.lib.user.models {
|
||||
|
||||
public function Users2x() {
|
||||
_users = new ArrayCollection();
|
||||
_me = new User2x();
|
||||
}
|
||||
|
||||
public function getUsers():Array {
|
||||
@ -78,6 +90,24 @@ package org.bigbluebutton.lib.user.models {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function joinAudioConference(intId:String, muted:Boolean):void {
|
||||
var user:User2x = getUser(intId);
|
||||
if (user) {
|
||||
user.muted = muted;
|
||||
user.voiceJoined = true;
|
||||
_userChangeSignal.dispatch(user, UserChangeEnum.AUDIO_JOIN);
|
||||
}
|
||||
}
|
||||
|
||||
public function leaveAudioConference(intId:String):void {
|
||||
var user:User2x = getUser(intId);
|
||||
if (user) {
|
||||
user.muted = false;
|
||||
user.voiceJoined = false;
|
||||
_userChangeSignal.dispatch(user, UserChangeEnum.AUDIO_LEAVE);
|
||||
}
|
||||
}
|
||||
|
||||
public function changeUserLocked(intId:String, locked:Boolean):void {
|
||||
var user:User2x = getUser(intId);
|
||||
if (user != null) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package org.bigbluebutton.lib.user.services {
|
||||
|
||||
import org.bigbluebutton.lib.user.models.User;
|
||||
import org.bigbluebutton.lib.user.models.User2x;
|
||||
|
||||
public interface IUsersService {
|
||||
function setupMessageSenderReceiver():void;
|
||||
@ -25,8 +25,8 @@ package org.bigbluebutton.lib.user.services {
|
||||
function saveLockSettings(newLockSettings:Object):void;
|
||||
function muteMe():void;
|
||||
function unmuteMe():void;
|
||||
function mute(user:User):void;
|
||||
function unmute(user:User):void;
|
||||
function mute(user:User2x):void;
|
||||
function unmute(user:User2x):void;
|
||||
function validateToken():void;
|
||||
function joinMeeting():void;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ package org.bigbluebutton.lib.user.services {
|
||||
import org.bigbluebutton.lib.main.models.IUserSession;
|
||||
import org.bigbluebutton.lib.main.models.LockSettings2x;
|
||||
import org.bigbluebutton.lib.main.utils.DisconnectEnum;
|
||||
import org.bigbluebutton.lib.user.models.User2x;
|
||||
import org.bigbluebutton.lib.user.models.User2x;
|
||||
|
||||
public class UsersMessageReceiver implements IMessageListener {
|
||||
private const LOG:String = "UsersMessageReceiver::";
|
||||
@ -29,12 +29,6 @@ package org.bigbluebutton.lib.user.services {
|
||||
case "voiceUserTalking":
|
||||
handleVoiceUserTalking(message);
|
||||
break;
|
||||
case "userJoinedVoice":
|
||||
handleUserJoinedVoice(message);
|
||||
break;
|
||||
case "userLeftVoice":
|
||||
handleUserLeftVoice(message);
|
||||
break;
|
||||
case "userSharedWebcam":
|
||||
handleUserSharedWebcam(message);
|
||||
break;
|
||||
@ -71,9 +65,12 @@ package org.bigbluebutton.lib.user.services {
|
||||
handleMeetingMuted(message);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
case "UserJoinedVoiceConfToClientEvtMsg":
|
||||
handleUserJoinedVoiceConfToClientEvtMsg(message);
|
||||
break;
|
||||
case "UserLeftVoiceConfToClientEvtMsg":
|
||||
handleUserLeftVoiceConfToClientEvtMsg(message);
|
||||
break;
|
||||
|
||||
case "GetUsersMeetingRespMsg":
|
||||
handleGetUsersMeetingRespMsg(message);
|
||||
@ -135,16 +132,7 @@ package org.bigbluebutton.lib.user.services {
|
||||
}
|
||||
|
||||
private function handleUserJoinedVoice(m:Object):void {
|
||||
var msg:Object = JSON.parse(m.msg);
|
||||
var voiceUser:Object = msg.user.voiceUser;
|
||||
trace(LOG + "handleUserJoinedVoice() -- user [" + msg.user.userId + "] has joined voice with voiceId [" + voiceUser.userId + "]");
|
||||
userSession.userList.userJoinAudio(msg.user.userId, voiceUser.userId, voiceUser.muted, voiceUser.talking, voiceUser.locked);
|
||||
}
|
||||
|
||||
private function handleUserLeftVoice(m:Object):void {
|
||||
var msg:Object = JSON.parse(m.msg);
|
||||
trace(LOG + "handleUserLeftVoice() -- user [" + msg.user.userId + "] has left voice");
|
||||
userSession.userList.userLeaveAudio(msg.user.userId);
|
||||
}
|
||||
|
||||
private function handleUserSharedWebcam(m:Object):void {
|
||||
@ -196,19 +184,24 @@ package org.bigbluebutton.lib.user.services {
|
||||
userSession.recordingStatusChanged(msg.recording);
|
||||
}
|
||||
|
||||
private function handleUserJoinedVoiceConfToClientEvtMsg(msg:Object):void {
|
||||
var user:Object = msg.body as Object;
|
||||
|
||||
// @todo : update lock value
|
||||
userSession.userList.userJoinAudio(user.intId, user.voiceUserId, user.muted, user.talking, false);
|
||||
|
||||
// @fixme : to be used later
|
||||
meetingData.users.joinAudioConference(user.intId, user.muted);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private function handleUserLeftVoiceConfToClientEvtMsg(msg:Object):void {
|
||||
trace(LOG + "handleUserLeftVoiceConfToClientEvtMsg() -- user [" + msg.body.intId + "] has left the voice conference");
|
||||
|
||||
userSession.userList.userLeaveAudio(msg.body.intId);
|
||||
|
||||
// @fixme : to be used later
|
||||
meetingData.users.leaveAudioConference(msg.body.intId);
|
||||
}
|
||||
|
||||
private function handleGetUsersMeetingRespMsg(msg:Object):void {
|
||||
var users:Array = msg.body.users as Array;
|
||||
@ -246,7 +239,7 @@ package org.bigbluebutton.lib.user.services {
|
||||
private function handleUserLeftMeetingEvtMsg(msg:Object):void {
|
||||
trace(LOG + "handleUserLeftMeetingEvtMsg() -- user [" + msg.body.intId + "] has left the meeting");
|
||||
meetingData.users.remove(msg.intId);
|
||||
}
|
||||
}
|
||||
|
||||
private function handleUserLockedInMeetingEvtMsg(msg:Object):void {
|
||||
trace(LOG + "handleUserLockedInMeetingEvtMsg: " + ObjectUtil.toString(msg));
|
||||
@ -293,6 +286,7 @@ package org.bigbluebutton.lib.user.services {
|
||||
private function handleValidateAuthTokenRespMsg(msg:Object):void {
|
||||
var tokenValid:Boolean = msg.body.valid as Boolean;
|
||||
trace(LOG + "handleValidateAuthTokenReply() valid=" + tokenValid);
|
||||
meetingData.users.me.intId = msg.body.userId;
|
||||
userSession.userId = msg.body.userId;
|
||||
userSession.authTokenSignal.dispatch(tokenValid);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ package org.bigbluebutton.lib.user.services {
|
||||
import org.bigbluebutton.lib.main.models.IMeetingData;
|
||||
import org.bigbluebutton.lib.main.models.IUserSession;
|
||||
import org.bigbluebutton.lib.user.models.EmojiStatus;
|
||||
import org.bigbluebutton.lib.user.models.User;
|
||||
import org.bigbluebutton.lib.user.models.User2x;
|
||||
|
||||
public class UsersService implements IUsersService {
|
||||
|
||||
@ -42,24 +42,24 @@ package org.bigbluebutton.lib.user.services {
|
||||
}
|
||||
|
||||
public function muteMe():void {
|
||||
mute(userSession.userList.me);
|
||||
mute(meetingData.users.me);
|
||||
}
|
||||
|
||||
public function unmuteMe():void {
|
||||
unmute(userSession.userList.me);
|
||||
unmute(meetingData.users.me);
|
||||
}
|
||||
|
||||
public function mute(user:User):void {
|
||||
public function mute(user:User2x):void {
|
||||
muteUnmute(user, true);
|
||||
}
|
||||
|
||||
public function unmute(user:User):void {
|
||||
public function unmute(user:User2x):void {
|
||||
muteUnmute(user, false);
|
||||
}
|
||||
|
||||
private function muteUnmute(user:User, mute:Boolean):void {
|
||||
private function muteUnmute(user:User2x, mute:Boolean):void {
|
||||
if (user.voiceJoined) {
|
||||
usersMessageSender.muteUnmuteUser(user.userId, mute);
|
||||
usersMessageSender.muteUnmuteUser(user.intId, mute);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,27 +1,27 @@
|
||||
package org.bigbluebutton.lib.voice.commands {
|
||||
|
||||
import org.bigbluebutton.lib.user.models.User;
|
||||
import org.bigbluebutton.lib.user.services.IUsersService;
|
||||
|
||||
import robotlegs.bender.bundles.mvcs.Command;
|
||||
|
||||
public class MicrophoneMuteCommand extends Command {
|
||||
|
||||
[Inject]
|
||||
public var user:User;
|
||||
|
||||
[Inject]
|
||||
public var userService:IUsersService;
|
||||
|
||||
override public function execute():void {
|
||||
trace("MicrophoneMuteCommand.execute() - user.muted = " + user.muted);
|
||||
if (user != null) {
|
||||
if (user.muted) {
|
||||
userService.unmute(user);
|
||||
} else {
|
||||
userService.mute(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.bigbluebutton.lib.voice.commands {
|
||||
|
||||
import org.bigbluebutton.lib.user.models.User2x;
|
||||
import org.bigbluebutton.lib.user.services.IUsersService;
|
||||
|
||||
import robotlegs.bender.bundles.mvcs.Command;
|
||||
|
||||
public class MicrophoneMuteCommand extends Command {
|
||||
|
||||
[Inject]
|
||||
public var user:User2x;
|
||||
|
||||
[Inject]
|
||||
public var userService:IUsersService;
|
||||
|
||||
override public function execute():void {
|
||||
trace("MicrophoneMuteCommand.execute() - user.muted = " + user.muted);
|
||||
if (user != null) {
|
||||
if (user.muted) {
|
||||
userService.unmute(user);
|
||||
} else {
|
||||
userService.mute(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
package org.bigbluebutton.lib.voice.commands {
|
||||
|
||||
import org.bigbluebutton.lib.user.models.User;
|
||||
import org.osflash.signals.Signal;
|
||||
|
||||
public class MicrophoneMuteSignal extends Signal {
|
||||
public function MicrophoneMuteSignal() {
|
||||
/**
|
||||
* @1 microphone enabled
|
||||
*/
|
||||
super(User);
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.bigbluebutton.lib.voice.commands {
|
||||
|
||||
import org.bigbluebutton.lib.user.models.User2x;
|
||||
import org.osflash.signals.Signal;
|
||||
|
||||
public class MicrophoneMuteSignal extends Signal {
|
||||
public function MicrophoneMuteSignal() {
|
||||
/**
|
||||
* @1 microphone enabled
|
||||
*/
|
||||
super(User2x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package org.bigbluebutton.lib.voice.commands {
|
||||
import org.bigbluebutton.lib.main.models.IUserSession;
|
||||
|
||||
import robotlegs.bender.bundles.mvcs.Command;
|
||||
|
||||
public class StartEchoTestCommand extends Command {
|
||||
private const LOG:String = "StartEchoTestCommand::";
|
||||
|
||||
[Inject]
|
||||
public var userSession:IUserSession;
|
||||
|
||||
override public function execute():void {
|
||||
userSession.voiceConnection.call(false, userSession.phoneOptions.echoTestApp);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package org.bigbluebutton.lib.voice.commands {
|
||||
import org.osflash.signals.Signal;
|
||||
|
||||
public class StartEchoTestSignal extends Signal {
|
||||
public function StartEchoTestSignal() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package org.bigbluebutton.lib.voice.commands {
|
||||
import org.bigbluebutton.lib.main.models.IUserSession;
|
||||
|
||||
import robotlegs.bender.bundles.mvcs.Command;
|
||||
|
||||
public class StopEchoTestCommand extends Command {
|
||||
private const LOG:String = "StopEchoTestCommand::";
|
||||
|
||||
[Inject]
|
||||
public var userSession:IUserSession;
|
||||
|
||||
override public function execute():void {
|
||||
userSession.voiceConnection.hangUp();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package org.bigbluebutton.lib.voice.commands {
|
||||
import org.osflash.signals.Signal;
|
||||
|
||||
public class StopEchoTestSignal extends Signal {
|
||||
public function StopEchoTestSignal() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +1,24 @@
|
||||
package org.bigbluebutton.lib.voice.services {
|
||||
|
||||
import flash.net.NetConnection;
|
||||
|
||||
import org.bigbluebutton.lib.main.models.IConferenceParameters;
|
||||
import org.osflash.signals.ISignal;
|
||||
|
||||
public interface IVoiceConnection {
|
||||
function get connectionFailureSignal():ISignal
|
||||
function get connectionSuccessSignal():ISignal
|
||||
function set uri(uri:String):void
|
||||
function get uri():String
|
||||
function get connection():NetConnection
|
||||
function get callActive():Boolean
|
||||
function get hangUpSuccessSignal():ISignal;
|
||||
function connect(confParams:IConferenceParameters, listenOnly:Boolean):void
|
||||
function disconnect(onUserCommand:Boolean):void
|
||||
function failedToJoinVoiceConferenceCallback(msg:String):*
|
||||
function disconnectedFromJoinVoiceConferenceCallback(msg:String):*
|
||||
function successfullyJoinedVoiceConferenceCallback(publishName:String, playName:String, codec:String):*
|
||||
function call(listenOnly:Boolean = false):void
|
||||
function hangUp():void
|
||||
}
|
||||
}
|
||||
package org.bigbluebutton.lib.voice.services {
|
||||
|
||||
import flash.net.NetConnection;
|
||||
|
||||
import org.bigbluebutton.lib.main.models.IConferenceParameters;
|
||||
import org.osflash.signals.ISignal;
|
||||
|
||||
public interface IVoiceConnection {
|
||||
function get connectionFailureSignal():ISignal
|
||||
function get connectionSuccessSignal():ISignal
|
||||
function set uri(uri:String):void
|
||||
function get uri():String
|
||||
function get connection():NetConnection
|
||||
function get callActive():Boolean
|
||||
function get hangUpSuccessSignal():ISignal;
|
||||
function connect(confParams:IConferenceParameters, listenOnly:Boolean):void
|
||||
function disconnect(onUserCommand:Boolean):void
|
||||
function failedToJoinVoiceConferenceCallback(msg:String):*
|
||||
function disconnectedFromJoinVoiceConferenceCallback(msg:String):*
|
||||
function successfullyJoinedVoiceConferenceCallback(publishName:String, playName:String, codec:String):*
|
||||
function call(listenOnly:Boolean = false, dialStr:String = null):void
|
||||
function hangUp():void
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,14 @@ package org.bigbluebutton.lib.voice.services {
|
||||
|
||||
import mx.utils.ObjectUtil;
|
||||
|
||||
import org.as3commons.lang.StringUtils;
|
||||
import org.bigbluebutton.lib.common.services.DefaultConnectionCallback;
|
||||
import org.bigbluebutton.lib.common.services.IBaseConnection;
|
||||
import org.bigbluebutton.lib.main.models.IConferenceParameters;
|
||||
import org.bigbluebutton.lib.main.models.IUserSession;
|
||||
import org.bigbluebutton.lib.voice.commands.ShareMicrophoneSignal;
|
||||
import org.osflash.signals.ISignal;
|
||||
import org.osflash.signals.Signal;
|
||||
import org.osflash.signals.Signal;
|
||||
|
||||
public class VoiceConnection extends DefaultConnectionCallback implements IVoiceConnection {
|
||||
public const LOG:String = "VoiceConnection::";
|
||||
@ -67,7 +68,7 @@ package org.bigbluebutton.lib.voice.services {
|
||||
|
||||
private function onConnectionSuccess():void {
|
||||
userSession.userList.me.listenOnly = _listenOnly;
|
||||
call(_listenOnly);
|
||||
// call(_listenOnly);
|
||||
}
|
||||
|
||||
public function get connectionFailureSignal():ISignal {
|
||||
@ -103,7 +104,7 @@ package org.bigbluebutton.lib.voice.services {
|
||||
_conferenceParameters = confParams;
|
||||
_listenOnly = listenOnly;
|
||||
_username = encodeURIComponent(confParams.internalUserID + "-bbbID-" + confParams.username);
|
||||
trace("Voice app connect");
|
||||
trace("Voice app connect");
|
||||
baseConnection.connect(_applicationURI, confParams.meetingID, confParams.externUserID, _username, confParams.authToken);
|
||||
}
|
||||
|
||||
@ -137,10 +138,13 @@ package org.bigbluebutton.lib.voice.services {
|
||||
// SIP Actions //
|
||||
// //
|
||||
//**********************************************//
|
||||
public function call(listenOnly:Boolean = false):void {
|
||||
public function call(listenOnly:Boolean = false, dialStr:String = null):void {
|
||||
if (!callActive) {
|
||||
trace(LOG + "call(): starting voice call");
|
||||
baseConnection.connection.call("voiceconf.call", new Responder(onCallSuccess, onCallFailure), "default", _username, _conferenceParameters.webvoiceconf, listenOnly.toString());
|
||||
if (StringUtils.isEmpty(dialStr)) {
|
||||
dialStr = _conferenceParameters.webvoiceconf;
|
||||
}
|
||||
baseConnection.connection.call("voiceconf.call", new Responder(onCallSuccess, onCallFailure), "default", _username, dialStr, listenOnly.toString());
|
||||
} else {
|
||||
trace(LOG + "call(): voice call already active");
|
||||
}
|
||||
|
@ -1,212 +1,232 @@
|
||||
package org.bigbluebutton.lib.voice.services {
|
||||
|
||||
import flash.events.AsyncErrorEvent;
|
||||
import flash.events.NetDataEvent;
|
||||
import flash.events.NetStatusEvent;
|
||||
import flash.events.StatusEvent;
|
||||
import flash.events.TimerEvent;
|
||||
import flash.media.Microphone;
|
||||
import flash.media.MicrophoneEnhancedMode;
|
||||
import flash.media.MicrophoneEnhancedOptions;
|
||||
import flash.media.SoundCodec;
|
||||
import flash.net.NetConnection;
|
||||
import flash.net.NetStream;
|
||||
import flash.utils.Timer;
|
||||
|
||||
import mx.utils.ObjectUtil;
|
||||
|
||||
public class VoiceStreamManager {
|
||||
protected var _incomingStream:NetStream = null;
|
||||
|
||||
protected var _outgoingStream:NetStream = null;
|
||||
|
||||
protected var _connection:NetConnection = null;
|
||||
|
||||
protected var _mic:Microphone = null;
|
||||
|
||||
protected var _defaultMicGain:Number = 50;
|
||||
|
||||
protected var _heartbeat:Timer = new Timer(2000);
|
||||
|
||||
public function setDefaultMicGain(value:Number):void {
|
||||
_defaultMicGain = value
|
||||
}
|
||||
|
||||
public function get mic():Microphone {
|
||||
return _mic;
|
||||
}
|
||||
|
||||
public function VoiceStreamManager() {
|
||||
_heartbeat.addEventListener(TimerEvent.TIMER, onHeartbeat);
|
||||
}
|
||||
|
||||
protected function onHeartbeat(event:TimerEvent):void {
|
||||
trace("+++ heartbeat +++");
|
||||
trace(ObjectUtil.toString(_incomingStream.audioCodec));
|
||||
}
|
||||
|
||||
public function muteMicGain(value:Boolean):void {
|
||||
if (_mic) {
|
||||
_mic.gain = value ? 0 : _defaultMicGain;
|
||||
}
|
||||
}
|
||||
|
||||
public function play(connection:NetConnection, streamName:String):void {
|
||||
_incomingStream = new NetStream(connection);
|
||||
_incomingStream.client = this;
|
||||
_incomingStream.addEventListener(NetDataEvent.MEDIA_TYPE_DATA, onNetDataEvent);
|
||||
_incomingStream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatusEvent);
|
||||
_incomingStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncErrorEvent);
|
||||
/*
|
||||
* Set the bufferTime to 0 (zero) for live stream as suggested in the doc.
|
||||
* http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/flash/net/NetStream.html#bufferTime
|
||||
* If we don't, we'll have a long audio delay when a momentary network congestion occurs. When the congestion
|
||||
* disappears, a flood of audio packets will arrive at the client and Flash will buffer them all and play them.
|
||||
* http://stackoverflow.com/questions/1079935/actionscript-netstream-stutters-after-buffering
|
||||
* ralam (Dec 13, 2010)
|
||||
*/
|
||||
_incomingStream.bufferTime = 0;
|
||||
_incomingStream.receiveAudio(true);
|
||||
_incomingStream.receiveVideo(false);
|
||||
_incomingStream.play(streamName);
|
||||
// _heartbeat.start();
|
||||
}
|
||||
|
||||
protected function onNetDataEvent(event:NetDataEvent):void {
|
||||
// trace(ObjectUtil.toString(event));
|
||||
}
|
||||
|
||||
public function publish(connection:NetConnection, streamName:String, codec:String, pushToTalk:Boolean):void {
|
||||
_outgoingStream = new NetStream(connection);
|
||||
_outgoingStream.client = this;
|
||||
_outgoingStream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatusEvent);
|
||||
_outgoingStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncErrorEvent);
|
||||
setupMicrophone(codec, pushToTalk);
|
||||
if (_mic) {
|
||||
_outgoingStream.attachAudio(_mic);
|
||||
_outgoingStream.publish(streamName, "live");
|
||||
}
|
||||
}
|
||||
|
||||
private function noMicrophone():Boolean {
|
||||
return ((Microphone.getMicrophone() == null) || (Microphone.names.length == 0) || ((Microphone.names.length == 1) && (Microphone.names[0] == "Unknown Microphone")));
|
||||
}
|
||||
|
||||
private function setupMicrophone(codec:String, pushToTalk:Boolean):void {
|
||||
if (noMicrophone()) {
|
||||
_mic = null;
|
||||
return;
|
||||
}
|
||||
_mic = getMicrophone(codec);
|
||||
_mic.gain = pushToTalk ? 0 : _defaultMicGain;
|
||||
}
|
||||
|
||||
/**
|
||||
* first try to use the enhanced microphone
|
||||
* if it doesn't work, get the regular one
|
||||
*/
|
||||
private function getMicrophone(codec:String):Microphone {
|
||||
var mic:Microphone = null;
|
||||
mic = Microphone.getEnhancedMicrophone();
|
||||
if (mic) {
|
||||
var options:MicrophoneEnhancedOptions = new MicrophoneEnhancedOptions();
|
||||
options.mode = MicrophoneEnhancedMode.FULL_DUPLEX;
|
||||
options.autoGain = false;
|
||||
options.echoPath = 128;
|
||||
options.nonLinearProcessing = true;
|
||||
mic['enhancedOptions'] = options;
|
||||
mic.setUseEchoSuppression(true);
|
||||
} else {
|
||||
mic = Microphone.getMicrophone();
|
||||
}
|
||||
if (mic == null) {
|
||||
trace("No microphone! <o>");
|
||||
} else {
|
||||
mic.addEventListener(StatusEvent.STATUS, onMicStatusEvent);
|
||||
mic.setLoopBack(false);
|
||||
mic.setSilenceLevel(0, 20000);
|
||||
mic.gain = 60;
|
||||
if (codec == "SPEEX") {
|
||||
mic.encodeQuality = 6;
|
||||
mic.codec = SoundCodec.SPEEX;
|
||||
mic.framesPerPacket = 1;
|
||||
mic.rate = 16;
|
||||
trace("Using SPEEX wideband codec");
|
||||
} else {
|
||||
mic.codec = SoundCodec.NELLYMOSER;
|
||||
mic.rate = 8;
|
||||
trace("Using Nellymoser codec");
|
||||
}
|
||||
}
|
||||
return mic;
|
||||
}
|
||||
|
||||
protected function onMicStatusEvent(event:StatusEvent):void {
|
||||
trace("New microphone status event");
|
||||
//trace(ObjectUtil.toString(event));
|
||||
switch (event.code) {
|
||||
case "Microphone.Muted":
|
||||
break;
|
||||
case "Microphone.Unmuted":
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function close():void {
|
||||
if (_incomingStream) {
|
||||
_incomingStream.removeEventListener(NetDataEvent.MEDIA_TYPE_DATA, onNetDataEvent);
|
||||
_incomingStream.removeEventListener(NetStatusEvent.NET_STATUS, onNetStatusEvent);
|
||||
_incomingStream.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncErrorEvent);
|
||||
_incomingStream.close();
|
||||
_incomingStream = null;
|
||||
}
|
||||
if (_outgoingStream) {
|
||||
_outgoingStream.removeEventListener(NetStatusEvent.NET_STATUS, onNetStatusEvent);
|
||||
_outgoingStream.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncErrorEvent);
|
||||
_outgoingStream.attachAudio(null);
|
||||
_outgoingStream.close();
|
||||
_outgoingStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected function onNetStatusEvent(event:NetStatusEvent):void {
|
||||
trace("VoiceStreamManager: onNetStatusEvent - " + event.info.code);
|
||||
switch (event.info.code) {
|
||||
case "NetStream.Play.Reset":
|
||||
break;
|
||||
case "NetStream.Play.StreamNotFound":
|
||||
break;
|
||||
case "NetStream.Play.Failed":
|
||||
break;
|
||||
case "NetStream.Play.Start":
|
||||
break;
|
||||
case "NetStream.Play.Stop":
|
||||
break;
|
||||
case "NetStream.Publish.Start":
|
||||
break;
|
||||
case "NetStream.Buffer.Full":
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected function onAsyncErrorEvent(event:AsyncErrorEvent):void {
|
||||
trace(ObjectUtil.toString(event));
|
||||
}
|
||||
|
||||
public function onPlayStatus(... rest):void {
|
||||
trace("onPlayStatus() " + ObjectUtil.toString(rest));
|
||||
}
|
||||
|
||||
public function onMetaData(... rest):void {
|
||||
trace("onMetaData() " + ObjectUtil.toString(rest));
|
||||
}
|
||||
|
||||
public function onHeaderData(... rest):void {
|
||||
trace("onHeaderData() " + ObjectUtil.toString(rest));
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.bigbluebutton.lib.voice.services {
|
||||
|
||||
import flash.events.AsyncErrorEvent;
|
||||
import flash.events.NetDataEvent;
|
||||
import flash.events.NetStatusEvent;
|
||||
import flash.events.StatusEvent;
|
||||
import flash.events.TimerEvent;
|
||||
import flash.media.Microphone;
|
||||
import flash.media.MicrophoneEnhancedMode;
|
||||
import flash.media.MicrophoneEnhancedOptions;
|
||||
import flash.media.SoundCodec;
|
||||
import flash.net.NetConnection;
|
||||
import flash.net.NetStream;
|
||||
import flash.utils.Timer;
|
||||
|
||||
import mx.utils.ObjectUtil;
|
||||
|
||||
public class VoiceStreamManager {
|
||||
protected var _incomingStream:NetStream = null;
|
||||
|
||||
protected var _outgoingStream:NetStream = null;
|
||||
|
||||
protected var _connection:NetConnection = null;
|
||||
|
||||
protected var _mic:Microphone = null;
|
||||
|
||||
protected var _defaultMicGain:Number = 50;
|
||||
|
||||
protected var _heartbeat:Timer = new Timer(2000);
|
||||
|
||||
public function setDefaultMicGain(value:Number):void {
|
||||
_defaultMicGain = value
|
||||
}
|
||||
|
||||
public function get mic():Microphone {
|
||||
return _mic;
|
||||
}
|
||||
|
||||
public function VoiceStreamManager() {
|
||||
_heartbeat.addEventListener(TimerEvent.TIMER, onHeartbeat);
|
||||
}
|
||||
|
||||
protected function onHeartbeat(event:TimerEvent):void {
|
||||
trace("+++ heartbeat +++");
|
||||
trace(ObjectUtil.toString(_incomingStream.audioCodec));
|
||||
}
|
||||
|
||||
public function muteMicGain(value:Boolean):void {
|
||||
if (_mic) {
|
||||
_mic.gain = value ? 0 : _defaultMicGain;
|
||||
}
|
||||
}
|
||||
|
||||
public function play(connection:NetConnection, streamName:String):void {
|
||||
_incomingStream = new NetStream(connection);
|
||||
_incomingStream.client = this;
|
||||
_incomingStream.addEventListener(NetDataEvent.MEDIA_TYPE_DATA, onNetDataEvent);
|
||||
_incomingStream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatusEvent);
|
||||
_incomingStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncErrorEvent);
|
||||
/*
|
||||
* Set the bufferTime to 0 (zero) for live stream as suggested in the doc.
|
||||
* http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/flash/net/NetStream.html#bufferTime
|
||||
* If we don't, we'll have a long audio delay when a momentary network congestion occurs. When the congestion
|
||||
* disappears, a flood of audio packets will arrive at the client and Flash will buffer them all and play them.
|
||||
* http://stackoverflow.com/questions/1079935/actionscript-netstream-stutters-after-buffering
|
||||
* ralam (Dec 13, 2010)
|
||||
*/
|
||||
_incomingStream.bufferTime = 0;
|
||||
_incomingStream.receiveAudio(true);
|
||||
_incomingStream.receiveVideo(false);
|
||||
_incomingStream.play(streamName);
|
||||
// _heartbeat.start();
|
||||
}
|
||||
|
||||
protected function onNetDataEvent(event:NetDataEvent):void {
|
||||
// trace(ObjectUtil.toString(event));
|
||||
}
|
||||
|
||||
public function publish(connection:NetConnection, streamName:String, codec:String, pushToTalk:Boolean):void {
|
||||
_outgoingStream = new NetStream(connection);
|
||||
_outgoingStream.client = this;
|
||||
_outgoingStream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatusEvent);
|
||||
_outgoingStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncErrorEvent);
|
||||
setupMicrophone(codec, pushToTalk);
|
||||
if (_mic) {
|
||||
_outgoingStream.attachAudio(_mic);
|
||||
_outgoingStream.publish(streamName, "live");
|
||||
}
|
||||
}
|
||||
|
||||
private function noMicrophone():Boolean {
|
||||
return ((Microphone.getMicrophone() == null) || (Microphone.names.length == 0) || ((Microphone.names.length == 1) && (Microphone.names[0] == "Unknown Microphone")));
|
||||
}
|
||||
|
||||
private function setupMicrophone(codec:String, pushToTalk:Boolean):void {
|
||||
if (noMicrophone()) {
|
||||
_mic = null;
|
||||
return;
|
||||
}
|
||||
_mic = getMicrophone(codec);
|
||||
_mic.gain = pushToTalk ? 0 : _defaultMicGain;
|
||||
}
|
||||
|
||||
/**
|
||||
* first try to use the enhanced microphone
|
||||
* if it doesn't work, get the regular one
|
||||
*/
|
||||
private function getMicrophone(codec:String):Microphone {
|
||||
var mic:Microphone = null;
|
||||
mic = Microphone.getEnhancedMicrophone();
|
||||
if (mic) {
|
||||
var options:MicrophoneEnhancedOptions = new MicrophoneEnhancedOptions();
|
||||
options.mode = MicrophoneEnhancedMode.FULL_DUPLEX;
|
||||
options.autoGain = false;
|
||||
options.echoPath = 128;
|
||||
options.nonLinearProcessing = true;
|
||||
mic['enhancedOptions'] = options;
|
||||
mic.setUseEchoSuppression(true);
|
||||
} else {
|
||||
mic = Microphone.getMicrophone();
|
||||
}
|
||||
if (mic == null) {
|
||||
trace("No microphone! <o>");
|
||||
} else {
|
||||
mic.addEventListener(StatusEvent.STATUS, onMicStatusEvent);
|
||||
mic.setLoopBack(false);
|
||||
mic.setSilenceLevel(0, 20000);
|
||||
mic.gain = 60;
|
||||
if (codec == "SPEEX") {
|
||||
mic.encodeQuality = 6;
|
||||
mic.codec = SoundCodec.SPEEX;
|
||||
mic.framesPerPacket = 1;
|
||||
mic.rate = 16;
|
||||
trace("Using SPEEX wideband codec");
|
||||
} else {
|
||||
mic.codec = SoundCodec.NELLYMOSER;
|
||||
mic.rate = 8;
|
||||
trace("Using Nellymoser codec");
|
||||
}
|
||||
}
|
||||
return mic;
|
||||
}
|
||||
|
||||
protected function onMicStatusEvent(event:StatusEvent):void {
|
||||
trace("New microphone status event");
|
||||
//trace(ObjectUtil.toString(event));
|
||||
switch (event.code) {
|
||||
case "Microphone.Muted":
|
||||
break;
|
||||
case "Microphone.Unmuted":
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function callIntoEchoTest():void {
|
||||
/*
|
||||
if (isConnected()) {
|
||||
var destination:String = options.echoTestApp;
|
||||
if (destination != null && destination != "") {
|
||||
LOGGER.debug("Calling into echo test =[{0}]", [destination]);
|
||||
state = CALLING_INTO_ECHO_TEST;
|
||||
VoiceConnection.doCall(destination);
|
||||
} else {
|
||||
LOGGER.debug("Invalid echo test destination [{0}]", [destination]);
|
||||
dispatcher.dispatchEvent(new FlashErrorEvent(FlashErrorEvent.INVALID_ECHO_TEST_DESTINATION));
|
||||
}
|
||||
} else {
|
||||
LOGGER.debug("Need to connect before we can call into echo test.");
|
||||
state = DO_ECHO_TEST;
|
||||
connect();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public function close():void {
|
||||
if (_incomingStream) {
|
||||
_incomingStream.removeEventListener(NetDataEvent.MEDIA_TYPE_DATA, onNetDataEvent);
|
||||
_incomingStream.removeEventListener(NetStatusEvent.NET_STATUS, onNetStatusEvent);
|
||||
_incomingStream.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncErrorEvent);
|
||||
_incomingStream.close();
|
||||
_incomingStream = null;
|
||||
}
|
||||
if (_outgoingStream) {
|
||||
_outgoingStream.removeEventListener(NetStatusEvent.NET_STATUS, onNetStatusEvent);
|
||||
_outgoingStream.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncErrorEvent);
|
||||
_outgoingStream.attachAudio(null);
|
||||
_outgoingStream.close();
|
||||
_outgoingStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected function onNetStatusEvent(event:NetStatusEvent):void {
|
||||
trace("VoiceStreamManager: onNetStatusEvent - " + event.info.code);
|
||||
switch (event.info.code) {
|
||||
case "NetStream.Play.Reset":
|
||||
break;
|
||||
case "NetStream.Play.StreamNotFound":
|
||||
break;
|
||||
case "NetStream.Play.Failed":
|
||||
break;
|
||||
case "NetStream.Play.Start":
|
||||
break;
|
||||
case "NetStream.Play.Stop":
|
||||
break;
|
||||
case "NetStream.Publish.Start":
|
||||
break;
|
||||
case "NetStream.Buffer.Full":
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected function onAsyncErrorEvent(event:AsyncErrorEvent):void {
|
||||
trace(ObjectUtil.toString(event));
|
||||
}
|
||||
|
||||
public function onPlayStatus(... rest):void {
|
||||
trace("onPlayStatus() " + ObjectUtil.toString(rest));
|
||||
}
|
||||
|
||||
public function onMetaData(... rest):void {
|
||||
trace("onMetaData() " + ObjectUtil.toString(rest));
|
||||
}
|
||||
|
||||
public function onHeaderData(... rest):void {
|
||||
trace("onHeaderData() " + ObjectUtil.toString(rest));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,85 @@
|
||||
package org.bigbluebutton.lib.voice.views {
|
||||
|
||||
import spark.components.Button;
|
||||
import spark.components.Label;
|
||||
import spark.components.ProgressBar;
|
||||
import spark.components.VGroup;
|
||||
import spark.layouts.HorizontalAlign;
|
||||
|
||||
public class EchoTestViewBase extends VGroup {
|
||||
|
||||
[Bindable]
|
||||
public var echoTestButton:Button;
|
||||
|
||||
[Bindable]
|
||||
public var micLevelProgressBar:ProgressBar;
|
||||
|
||||
[Bindable]
|
||||
public var yesButton:Button;
|
||||
|
||||
[Bindable]
|
||||
public var noButton:Button;
|
||||
|
||||
public var echoLabel:Label;
|
||||
|
||||
private var echoValidationGroup:VGroup;
|
||||
|
||||
private var echoButtonGroup:VGroup;
|
||||
|
||||
public function EchoTestViewBase() {
|
||||
super();
|
||||
|
||||
// Echo Button Group
|
||||
echoButtonGroup = new VGroup();
|
||||
echoButtonGroup.percentWidth = 100;
|
||||
echoButtonGroup.horizontalAlign = HorizontalAlign.CENTER;
|
||||
addElement(echoButtonGroup);
|
||||
|
||||
micLevelProgressBar = new ProgressBar();
|
||||
micLevelProgressBar.percentWidth = 80;
|
||||
micLevelProgressBar.height = 40;
|
||||
micLevelProgressBar.styleName = "micLevelProgressBar";
|
||||
echoButtonGroup.addElement(micLevelProgressBar);
|
||||
|
||||
echoTestButton = new Button();
|
||||
echoTestButton.label = "Start Echo Test";
|
||||
echoButtonGroup.addElement(echoTestButton);
|
||||
|
||||
// Echo Validation Group
|
||||
echoValidationGroup = new VGroup();
|
||||
echoValidationGroup.percentWidth = 100;
|
||||
echoValidationGroup.horizontalAlign = HorizontalAlign.CENTER;
|
||||
addElement(echoValidationGroup);
|
||||
|
||||
echoValidationGroup.visible = echoValidationGroup.includeInLayout = false;
|
||||
|
||||
echoLabel = new Label();
|
||||
echoLabel.maxDisplayedLines = 5;
|
||||
echoLabel.percentWidth = 80;
|
||||
echoLabel.styleName = "echoTestLabel";
|
||||
echoLabel.text = "This is a private echo test. Speak a few words. Did you hear audio?";
|
||||
//echoLabel.maxWidth = echoValidationGroup.width - 40;
|
||||
echoValidationGroup.addElement(echoLabel);
|
||||
|
||||
yesButton = new Button();
|
||||
yesButton.label = "Yes";
|
||||
echoValidationGroup.addElement(yesButton);
|
||||
|
||||
noButton = new Button();
|
||||
noButton.label = "No";
|
||||
echoValidationGroup.addElement(noButton);
|
||||
}
|
||||
|
||||
public function setTestingState(connected:Boolean):void {
|
||||
echoButtonGroup.visible = echoButtonGroup.includeInLayout = !connected;
|
||||
echoValidationGroup.visible = echoValidationGroup.includeInLayout = connected;
|
||||
}
|
||||
|
||||
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
|
||||
super.updateDisplayList(unscaledWidth, unscaledHeight);
|
||||
|
||||
this.padding = getStyle("padding");
|
||||
echoButtonGroup.padding = getStyle("padding");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,170 @@
|
||||
package org.bigbluebutton.lib.voice.views {
|
||||
import flash.events.MouseEvent;
|
||||
import flash.events.StatusEvent;
|
||||
import flash.events.TimerEvent;
|
||||
import flash.media.Microphone;
|
||||
import flash.net.NetConnection;
|
||||
import flash.net.NetStream;
|
||||
import flash.net.ObjectEncoding;
|
||||
import flash.utils.Timer;
|
||||
|
||||
import org.bigbluebutton.lib.main.models.IMeetingData;
|
||||
import org.bigbluebutton.lib.voice.commands.ShareMicrophoneSignal;
|
||||
import org.bigbluebutton.lib.voice.commands.StartEchoTestSignal;
|
||||
import org.bigbluebutton.lib.voice.commands.StopEchoTestSignal;
|
||||
|
||||
import robotlegs.bender.bundles.mvcs.Mediator;
|
||||
|
||||
public class EchoTestViewMediator extends Mediator {
|
||||
|
||||
[Inject]
|
||||
public var view:EchoTestViewBase;
|
||||
|
||||
[Inject]
|
||||
public var startEchoTestSignal:StartEchoTestSignal;
|
||||
|
||||
[Inject]
|
||||
public var shareMicrophoneSignal:ShareMicrophoneSignal;
|
||||
|
||||
[Inject]
|
||||
public var stopEchoTestSignal:StopEchoTestSignal;
|
||||
|
||||
[Inject]
|
||||
public var meetingData:IMeetingData;
|
||||
|
||||
private var selectedMicrophone:Microphone;
|
||||
|
||||
private var micActivityTimer:Timer;
|
||||
|
||||
private var microphoneNetConnection:NetConnection;
|
||||
|
||||
private var netStream:NetStream;
|
||||
|
||||
private var audioMicLevelDetected:int = 0;
|
||||
|
||||
private var doingEchoTest:Boolean = false;
|
||||
|
||||
public override function initialize():void {
|
||||
view.echoTestButton.addEventListener(MouseEvent.CLICK, echoTestButtonHandler);
|
||||
view.yesButton.addEventListener(MouseEvent.CLICK, yesButtonHandler);
|
||||
view.noButton.addEventListener(MouseEvent.CLICK, noButtonHandler);
|
||||
testMicrophoneLoopback();
|
||||
}
|
||||
|
||||
private function testMicrophoneLoopback():void {
|
||||
reInitialize();
|
||||
|
||||
selectedMicrophone = Microphone.getMicrophone(0);
|
||||
if (selectedMicrophone != null) {
|
||||
view.echoTestButton.enabled = true;
|
||||
selectedMicrophone.addEventListener(StatusEvent.STATUS, micStatusEventHandler)
|
||||
netStream.attachAudio(selectedMicrophone);
|
||||
|
||||
startMicLevelListener();
|
||||
|
||||
audioMicLevelDetected = 0;
|
||||
} else {
|
||||
view.echoTestButton.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
private function startMicLevelListener():void {
|
||||
micActivityTimer = new Timer(100);
|
||||
micActivityTimer.addEventListener(TimerEvent.TIMER, updateMicLevel);
|
||||
micActivityTimer.start();
|
||||
}
|
||||
|
||||
private function updateMicLevel(e:TimerEvent):void {
|
||||
if (selectedMicrophone != null) {
|
||||
if (selectedMicrophone.activityLevel > audioMicLevelDetected) {
|
||||
audioMicLevelDetected = selectedMicrophone.activityLevel;
|
||||
}
|
||||
view.micLevelProgressBar.currentProgress = selectedMicrophone.activityLevel;
|
||||
view.micLevelProgressBar.totalProgress = 100;
|
||||
}
|
||||
}
|
||||
|
||||
private function reInitialize():void {
|
||||
if (microphoneNetConnection) {
|
||||
microphoneNetConnection.close();
|
||||
}
|
||||
if (netStream) {
|
||||
netStream.close();
|
||||
}
|
||||
microphoneNetConnection = new NetConnection();
|
||||
microphoneNetConnection.objectEncoding = ObjectEncoding.AMF3;
|
||||
microphoneNetConnection.proxyType = "best";
|
||||
microphoneNetConnection.connect(null);
|
||||
netStream = new NetStream(microphoneNetConnection);
|
||||
if (selectedMicrophone != null && !selectedMicrophone.hasEventListener(StatusEvent.STATUS)) {
|
||||
selectedMicrophone.removeEventListener(StatusEvent.STATUS, micStatusEventHandler);
|
||||
}
|
||||
|
||||
if (micActivityTimer != null && micActivityTimer.running) {
|
||||
micActivityTimer.stop();
|
||||
}
|
||||
|
||||
selectedMicrophone = null;
|
||||
}
|
||||
|
||||
private function micStatusEventHandler(event:StatusEvent):void {
|
||||
switch (event.code) {
|
||||
case "Microphone.Muted":
|
||||
view.echoLabel.text = "You did not allow Flash to access your mic.";
|
||||
break;
|
||||
case "Microphone.Unmuted":
|
||||
// @fixme : use => saveData.read("micGain") as Number; later
|
||||
selectedMicrophone.gain = 60;
|
||||
break;
|
||||
default:
|
||||
// LOGGER.debug("unknown micStatusHandler event: {0}", [event]);
|
||||
}
|
||||
}
|
||||
|
||||
private function echoTestButtonHandler(e:MouseEvent):void {
|
||||
micActivityTimer.stop();
|
||||
doingEchoTest = true;
|
||||
view.setTestingState(true);
|
||||
startEchoTestSignal.dispatch();
|
||||
}
|
||||
|
||||
protected function yesButtonHandler(e:MouseEvent):void {
|
||||
stopEchoTest();
|
||||
|
||||
var audioOptions:Object = new Object();
|
||||
audioOptions.shareMic = !meetingData.users.me.voiceJoined;
|
||||
audioOptions.listenOnly = false;
|
||||
shareMicrophoneSignal.dispatch(audioOptions);
|
||||
}
|
||||
|
||||
private function stopEchoTest():void {
|
||||
if (doingEchoTest) {
|
||||
doingEchoTest = false;
|
||||
stopEchoTestSignal.dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
private function noButtonHandler(e:MouseEvent):void {
|
||||
stopEchoTest();
|
||||
view.setTestingState(false);
|
||||
testMicrophoneLoopback();
|
||||
}
|
||||
|
||||
override public function destroy():void {
|
||||
super.destroy();
|
||||
|
||||
microphoneNetConnection.close();
|
||||
netStream.close();
|
||||
|
||||
view.echoTestButton.removeEventListener(MouseEvent.CLICK, echoTestButtonHandler);
|
||||
view.yesButton.removeEventListener(MouseEvent.CLICK, yesButtonHandler);
|
||||
view.noButton.removeEventListener(MouseEvent.CLICK, noButtonHandler);
|
||||
|
||||
if (selectedMicrophone && selectedMicrophone.hasEventListener(StatusEvent.STATUS)) {
|
||||
selectedMicrophone.removeEventListener(StatusEvent.STATUS, micStatusEventHandler)
|
||||
}
|
||||
|
||||
micActivityTimer.removeEventListener(TimerEvent.TIMER, updateMicLevel);
|
||||
}
|
||||
}
|
||||
}
|
@ -175,3 +175,96 @@
|
||||
.icon-mute {
|
||||
icon: "\ue932";
|
||||
}
|
||||
.icon-about {
|
||||
content: "\ue933";
|
||||
}
|
||||
.icon-send {
|
||||
content: "\ue934";
|
||||
}
|
||||
.icon-exit-fullscreen {
|
||||
content: "\ue935";
|
||||
}
|
||||
.icon-delete {
|
||||
content: "\ue936";
|
||||
}
|
||||
.icon-unmute-filled {
|
||||
content: "\ue937";
|
||||
}
|
||||
.icon-mute-filled {
|
||||
content: "\ue938";
|
||||
}
|
||||
.icon-listen_filled {
|
||||
content: "\ue939";
|
||||
}
|
||||
.icon-template-upload {
|
||||
content: "\ue93a";
|
||||
}
|
||||
.icon-template-download {
|
||||
content: "\ue93b";
|
||||
}
|
||||
.icon-save-notes {
|
||||
content: "\ue93c";
|
||||
}
|
||||
.icon-multi-whiteboard {
|
||||
content: "\ue93d";
|
||||
}
|
||||
.icon-whiteboard {
|
||||
content: "\ue93e";
|
||||
}
|
||||
.icon-rooms {
|
||||
content: "\ue93f";
|
||||
}
|
||||
.icon-unlock {
|
||||
content: "\ue940";
|
||||
}
|
||||
.icon-record {
|
||||
content: "\ue941";
|
||||
}
|
||||
.icon-network {
|
||||
content: "\ue942";
|
||||
}
|
||||
.icon-redo {
|
||||
content: "\ue943";
|
||||
}
|
||||
.icon-thumbs-down-filled {
|
||||
content: "\ue944";
|
||||
}
|
||||
.icon-thumbs-up-filled {
|
||||
content: "\ue945";
|
||||
}
|
||||
.icon-checkmark {
|
||||
content: "\ue946";
|
||||
}
|
||||
.icon-speak-louder {
|
||||
content: "\ue947";
|
||||
}
|
||||
.icon-help {
|
||||
content: "\ue940";
|
||||
}
|
||||
.icon-unlock {
|
||||
content: "\ue948";
|
||||
}
|
||||
.icon-refresh {
|
||||
content: "\ue949";
|
||||
}
|
||||
.icon-copy {
|
||||
content: "\ue94a";
|
||||
}
|
||||
.icon-shortcuts {
|
||||
content: "\ue94b";
|
||||
}
|
||||
.icon-warning {
|
||||
content: "\ue94c";
|
||||
}
|
||||
.icon-transfer-audio {
|
||||
content: "\ue94d";
|
||||
}
|
||||
.icon-room {
|
||||
content: "\ue94e";
|
||||
}
|
||||
.icon-new_file {
|
||||
content: "\ue94f";
|
||||
}
|
||||
.icon-pointer {
|
||||
content: "\ue950";
|
||||
}
|
@ -6,3 +6,7 @@
|
||||
views|TopToolbarBase {
|
||||
textAlign : center;
|
||||
}
|
||||
|
||||
.echoTestLabel {
|
||||
textAlign : center;
|
||||
}
|
||||
|
Binary file not shown.
BIN
clients/flash/web-client/libs/as3commons-lang-0.3.7.swc
Normal file
BIN
clients/flash/web-client/libs/as3commons-lang-0.3.7.swc
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user