Merge branch 'master' of github.com:bigbluebutton/bigbluebutton into mobile-screenshare

This commit is contained in:
Richard Alam 2018-03-16 11:36:53 -07:00
commit b94b30677b
33 changed files with 366 additions and 312 deletions

View File

@ -40,8 +40,6 @@
}
main|MenuButtons {
bottom: 26.25;
top: 10.50;
gap: 33.75;
}

View File

@ -40,8 +40,6 @@
}
main|MenuButtons {
bottom: 13.125;
top: 5.250;
gap: 16.875;
}

View File

@ -40,8 +40,6 @@
}
main|MenuButtons {
bottom: 17.5;
top: 7.0;
gap: 22.5;
}

View File

@ -29,8 +29,6 @@
}
main|MenuButtons {
bottom : 35;
top : 14;
gap : 45;
}

View File

@ -40,8 +40,6 @@
}
main|MenuButtons {
bottom: 52.5;
top: 21.0;
gap: 67.5;
}

View File

@ -40,8 +40,6 @@
}
main|MenuButtons {
bottom: 70;
top: 28;
gap: 90;
}

View File

@ -9,50 +9,44 @@ package org.bigbluebutton.air.common.views {
import mx.core.UIComponent;
import spark.components.Group;
import spark.components.Group;
public class VideoView extends UIComponent {
protected var ns:NetStream;
protected var video:Video;
protected var aspectRatio:Number = 0;
protected var _video:Video;
protected var connection:NetConnection;
public var userID:String;
public var userId:String;
public var userName:String;
public var streamName:String;
protected var aspectRatio:Number = 0;
protected var originalVideoWidth:Number;
protected var originalVideoHeight:Number;
protected var screenWidth:Number;
protected var screenHeight:Number;
protected var topMenuBarHeight:Number;
protected var bottomMenuBarHeight:Number;
public function VideoView():void {
video = new Video();
_video = new Video();
addChild(_video);
}
public function startStream(connection:NetConnection, name:String, streamName:String, userID:String):void {
public function startStream(connection:NetConnection, name:String, streamName:String, userId:String, oWidth:Number, oHeight:Number):void {
if (ns) {
close();
}
if (connection.uri.indexOf("/video/") != -1 && Capabilities.version.indexOf("IOS") >= 0) {
streamName = "h263/" + streamName;
}
this.userName = name;
this.userID = userID;
this.userId = userId;
this.streamName = streamName;
this.connection = connection;
this.originalVideoWidth = oWidth;
this.originalVideoHeight = oHeight;
ns = new NetStream(connection);
ns.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
@ -60,25 +54,22 @@ package org.bigbluebutton.air.common.views {
ns.bufferTime = 0;
ns.receiveVideo(true);
ns.receiveAudio(false);
video.smoothing = true;
video.attachNetStream(ns);
_video.smoothing = true;
_video.attachNetStream(ns);
ns.play(streamName);
}
public function get videoViewVideo():Video {
return video;
}
private function onNetStatus(e:NetStatusEvent):void {
switch (e.info.code) {
case "NetStream.Publish.Start":
trace("NetStream.Publish.Start for broadcast stream " + streamName);
break;
case "NetStream.Play.UnpublishNotify":
this.close();
close();
break;
case "NetStream.Play.Start":
trace("Netstatus: " + e.info.code);
invalidateDisplayList();
break;
case "NetStream.Play.FileStructureInvalid":
trace("The MP4's file structure is invalid.");
@ -93,11 +84,13 @@ package org.bigbluebutton.air.common.views {
trace("VideoWindow::asyncerror " + e.toString());
}
public function onMetaData(info:Object):void {
trace("width={0} height={1}", [info.width, info.height]);
}
public function close():void {
if (video && video.parent) {
video = null;
}
if (ns) {
_video.attachCamera(null);
ns.removeEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
ns.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
ns.close();
@ -105,95 +98,97 @@ package org.bigbluebutton.air.common.views {
}
}
public function initializeScreenSizeValues(originalVideoWidth0:Number, originalVideoHeight0:Number, screenHeight0:Number, screenWidth0:Number, topMenuBarHeight0:Number, bottomMenuBarHeight0:Number):void {
this.screenHeight = screenHeight0;
this.screenWidth = screenWidth0;
this.topMenuBarHeight = topMenuBarHeight0;
this.bottomMenuBarHeight = bottomMenuBarHeight0;
this.originalVideoWidth = originalVideoWidth0;
this.originalVideoHeight = originalVideoHeight0;
override protected function updateDisplayList(w:Number, h:Number):void {
super.updateDisplayList(w, h);
if (ns) {
resizeForPortrait();
}
}
public function resizeForPortrait():void {
// if we have device where screen width less than screen height e.g. phone
if (screenWidth < screenHeight) {
if (width < height) {
// make the video width full width of the screen
video.width = screenWidth;
_video.width = width;
// calculate height based on a video width, it order to keep the same aspect ratio
video.height = (video.width / originalVideoWidth) * originalVideoHeight;
_video.height = (_video.width / originalVideoWidth) * originalVideoHeight;
// if calculated height appeared to be bigger than screen height, recalculuate the video size based on width
if (screenHeight < video.height) {
if (height < _video.height) {
// make the video height full height of the screen
video.height = screenHeight;
_video.height = height;
// calculate width based on a video height, it order to keep the same aspect ratio
video.width = ((originalVideoWidth * video.height) / originalVideoHeight);
_video.width = ((originalVideoWidth * _video.height) / originalVideoHeight);
}
} // if we have device where screen height less than screen width e.g. tablet
else {
// make the video height full height of the screen
video.height = screenHeight;
_video.height = height;
// calculate width based on a video height, it order to keep the same aspect ratio
video.width = ((originalVideoWidth * video.height) / originalVideoHeight);
_video.width = ((originalVideoWidth * _video.height) / originalVideoHeight);
// if calculated width appeared to be bigger than screen width, recalculuate the video size based on height
if (screenWidth < video.width) {
if (width < _video.width) {
// make the video width full width of the screen
video.width = screenWidth;
_video.width = width;
// calculate height based on a video width, it order to keep the same aspect ratio
video.height = (video.width / originalVideoWidth) * originalVideoHeight;
_video.height = (_video.width / originalVideoWidth) * originalVideoHeight;
}
}
_video.x = width - _video.width;
_video.y = height - _video.height;
}
public function resizeForLandscape():void {
if (screenHeight < screenWidth) {
video.height = screenWidth;
video.width = ((originalVideoWidth * video.height) / originalVideoHeight);
if (screenWidth < video.width) {
video.width = screenHeight;
video.height = (video.width / originalVideoWidth) * originalVideoHeight;
if (height < width) {
_video.height = width;
_video.width = ((originalVideoWidth * _video.height) / originalVideoHeight);
if (width < _video.width) {
_video.width = height;
_video.height = (_video.width / originalVideoWidth) * originalVideoHeight;
}
} else {
video.width = screenHeight;
video.height = (video.width / originalVideoWidth) * originalVideoHeight;
if (screenHeight < video.height) {
video.height = screenWidth;
video.width = ((originalVideoWidth * video.height) / originalVideoHeight);
_video.width = height;
_video.height = (_video.width / originalVideoWidth) * originalVideoHeight;
if (height < _video.height) {
_video.height = width;
_video.width = ((originalVideoWidth * _video.height) / originalVideoHeight);
}
}
}
public function rotateVideo(rotation:Number):void {
if (video && stage.contains(video)) {
stage.removeChild(video);
if (_video && stage.contains(_video)) {
stage.removeChild(_video);
}
video = new Video();
video.attachNetStream(ns);
_video = new Video();
_video.attachNetStream(ns);
switch (rotation) {
case 0:
resizeForPortrait();
video.x = screenWidth / 2 - video.width / 2;
video.y = screenHeight / 2 - video.height / 2 + topMenuBarHeight;
_video.x = width / 2 - _video.width / 2;
_video.y = height / 2 - _video.height / 2; // + topMenuBarHeight;
break;
case -90:
resizeForLandscape();
video.x = (screenWidth / 2) - (video.height / 2);
video.y = (screenHeight / 2) + (video.width / 2) + topMenuBarHeight;
_video.x = (width / 2) - (_video.height / 2);
_video.y = (height / 2) + (_video.width / 2); // + topMenuBarHeight;
break;
case 90:
resizeForLandscape();
video.x = (screenWidth / 2) + (video.height / 2);
video.y = (screenHeight / 2) - (video.width / 2) + topMenuBarHeight;
_video.x = (width / 2) + (_video.height / 2);
_video.y = (height / 2) - (_video.width / 2); // + topMenuBarHeight;
break;
case 180:
resizeForPortrait();
video.x = screenWidth / 2 + video.width / 2;
video.y = (screenHeight / 2) + (video.height / 2) + topMenuBarHeight
_video.x = width / 2 + _video.width / 2;
_video.y = (height / 2) + (_video.height / 2); // + topMenuBarHeight
break;
default:
break;
}
video.rotation = rotation;
this.stage.addChild(video);
_video.rotation = rotation;
this.stage.addChild(_video);
}
}
}

View File

@ -14,6 +14,8 @@ package org.bigbluebutton.air.main {
import org.bigbluebutton.air.main.views.ExitViewMediator;
import org.bigbluebutton.air.main.views.LoadingScreen;
import org.bigbluebutton.air.main.views.LoadingScreenMediator;
import org.bigbluebutton.air.main.views.MainView;
import org.bigbluebutton.air.main.views.MainViewMediator;
import org.bigbluebutton.air.main.views.MenuButtons;
import org.bigbluebutton.air.main.views.MenuButtonsMediator;
import org.bigbluebutton.air.main.views.PagesNavigatorView;
@ -62,6 +64,7 @@ package org.bigbluebutton.air.main {
mediatorMap.map(MenuButtons).toMediator(MenuButtonsMediator);
mediatorMap.map(ExitView).toMediator(ExitViewMediator);
mediatorMap.map(DisconnectView).toMediator(DisconnectViewMediator);
mediatorMap.map(MainView).toMediator(MainViewMediator);
}
/**

View File

@ -12,6 +12,7 @@ package org.bigbluebutton.air.main.commands {
import org.bigbluebutton.air.presentation.services.IPresentationService;
import org.bigbluebutton.air.screenshare.services.IScreenshareConnection;
import org.bigbluebutton.air.user.models.User2x;
import org.bigbluebutton.air.user.models.UserChangeEnum;
import org.bigbluebutton.air.user.services.IUsersService;
import org.bigbluebutton.air.video.commands.ShareCameraSignal;
import org.bigbluebutton.air.video.services.IVideoConnection;
@ -21,7 +22,7 @@ package org.bigbluebutton.air.main.commands {
import org.bigbluebutton.air.voice.services.IVoiceService;
import org.bigbluebutton.air.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::";
@ -82,6 +83,8 @@ package org.bigbluebutton.air.main.commands {
private var authTokenTimeout:Timer;
private var joinMeetingTimeout:Timer;
override public function execute():void {
loadConfigOptions();
connection.uri = uri;
@ -149,9 +152,9 @@ package org.bigbluebutton.air.main.commands {
var audioOptions:Object = new Object();
if (userSession.phoneOptions.autoJoin && userSession.phoneOptions.skipCheck) {
var forceListenOnly:Boolean = (userSession.config.getConfigFor("PhoneModule").@forceListenOnly.toString().toUpperCase() == "TRUE") ? true : false;
//audioOptions.shareMic = userSession.userList.me.voiceJoined = !forceListenOnly;
//audioOptions.listenOnly = userSession.userList.me.listenOnly = forceListenOnly;
//shareMicrophoneSignal.dispatch(audioOptions);
//audioOptions.shareMic = userSession.userList.me.voiceJoined = !forceListenOnly;
//audioOptions.listenOnly = userSession.userList.me.listenOnly = forceListenOnly;
//shareMicrophoneSignal.dispatch(audioOptions);
} else {
//audioOptions.shareMic = userSession.userList.me.voiceJoined = false;
//audioOptions.listenOnly = userSession.userList.me.listenOnly = true;
@ -175,17 +178,44 @@ package org.bigbluebutton.air.main.commands {
userSession.successJoiningMeetingSignal.remove(joiningMeetingSuccess);
userSession.failureJoiningMeetingSignal.remove(joiningMeetingFailure);
usersService.getRoomLockState();
meetingData.users.userChangeSignal.add(userChangeListener);
joinMeetingTimeout = new Timer(5000, 1);
joinMeetingTimeout.addEventListener(TimerEvent.TIMER, onJoinMeetingTimeout);
joinMeetingTimeout.start();
}
// reason is one of the DisconnectEnum types
private function joiningMeetingFailure(reason:int):void {
trace(LOG + "joiningMeetingFailure() -- Failed to join the meeting!!!");
userSession.successJoiningMeetingSignal.remove(joiningMeetingSuccess);
userSession.failureJoiningMeetingSignal.remove(joiningMeetingFailure);
disconnectUserSignal.dispatch(reason);
}
private function userChangeListener(user:User2x, enum:int):void {
// If we fetch data before the server has recognized the join we can get disconnected. Need
// to delay the fetch until after the join is received back.
if (user.me && enum == UserChangeEnum.JOIN) {
meetingData.users.userChangeSignal.remove(userChangeListener);
joinMeetingTimeout.stop();
// Query the server for chat, users, and presentation info
chatService.getGroupChats();
presentationService.getPresentationPods();
meetingData.users.userChangeSignal.add(successUsersAdded);
usersService.queryForParticipants();
usersService.getLockSettings();
usersService.getRoomLockState();
videoConnection.loadCameraSettings();
}
}
private function onJoinMeetingTimeout(e:TimerEvent):void {
trace(LOG + "onJoinMeetingTimeout - timeout hit");
meetingData.users.userChangeSignal.remove(userChangeListener);
joiningMeetingFailure(DisconnectEnum.JOIN_MEETING_TIMEOUT);
}
protected function successUsersAdded(user:User2x, property:int):void {
meetingData.users.userChangeSignal.remove(successUsersAdded);
connectingFinishedSignal.dispatch();
@ -200,10 +230,6 @@ package org.bigbluebutton.air.main.commands {
private function videoConnectedSuccess():void {
trace(LOG + "successVideoConnected()");
if (userSession.videoAutoStart && userSession.skipCamSettingsCheck) {
trace("TODO: Need to implement auto start cam still");
//shareCameraSignal.dispatch(!userSession.userList.me.hasStream, userSession.videoConnection.cameraPosition);
}
videoConnection.connectionSuccessSignal.remove(videoConnectedSuccess);
videoConnection.connectionFailureSignal.remove(videoConnectionFailure);
}

View File

@ -34,11 +34,8 @@ package org.bigbluebutton.air.main.models {
function get screenshareConnection():IScreenshareConnection;
function set screenshareConnection(value:IScreenshareConnection):void;
function get presentationList():PresentationList;
function get successJoiningMeetingSignal():ISignal;
function get failureJoiningMeetingSignal():ISignal;
function get assignedDeskshareSignal():ISignal;
function get logoutSignal():Signal;
function joinMeetingResponse(msg:Object):void;
function get videoProfileManager():VideoProfileManager
function set videoProfileManager(value:VideoProfileManager):void;
function get authTokenSignal():ISignal

View File

@ -42,10 +42,6 @@ package org.bigbluebutton.air.main.models {
protected var _pushToTalk:Boolean;
protected var _successJoiningMeetingSignal:ISignal = new Signal();
protected var _failureJoiningMeetingSignal:ISignal = new Signal();
protected var _assignedDeskshareSignal:ISignal = new Signal();
protected var _logoutSignal:Signal = new Signal();
@ -175,26 +171,10 @@ package org.bigbluebutton.air.main.models {
return _presentationList;
}
public function get successJoiningMeetingSignal():ISignal {
return _successJoiningMeetingSignal;
}
public function get failureJoiningMeetingSignal():ISignal {
return _failureJoiningMeetingSignal;
}
public function get assignedDeskshareSignal():ISignal {
return _assignedDeskshareSignal;
}
public function joinMeetingResponse(msg:Object):void {
if (msg.user) {
_successJoiningMeetingSignal.dispatch();
} else {
_failureJoiningMeetingSignal.dispatch();
}
}
public function get logoutSignal():Signal {
return _logoutSignal;
}

View File

@ -12,5 +12,7 @@ package org.bigbluebutton.air.main.utils {
public static const AUTH_TOKEN_TIMEOUT:int = 5;
public static const AUTH_TOKEN_INVALID:int = 6;
public static const JOIN_MEETING_TIMEOUT:int = 7;
}
}

View File

@ -42,7 +42,7 @@ package org.bigbluebutton.air.main.views {
view.messageText.text = "Current meeting has been ended";
break;
case DisconnectEnum.CONNECTION_STATUS_CONNECTION_DROPPED:
view.messageText.text = "Meeting connection was dropped!";
view.messageText.text = "Meeting connection was dropped";
break;
case DisconnectEnum.CONNECTION_STATUS_USER_KICKED_OUT:
view.messageText.text = "You have been kicked out of the meeting";
@ -50,6 +50,15 @@ package org.bigbluebutton.air.main.views {
case DisconnectEnum.CONNECTION_STATUS_USER_LOGGED_OUT:
view.messageText.text = "You have logged out of the meeting";
break;
case DisconnectEnum.AUTH_TOKEN_INVALID:
view.messageText.text = "Your authorization token is invalid";
break;
case DisconnectEnum.AUTH_TOKEN_TIMEOUT:
view.messageText.text = "A timeout triggered while validating your authorization token";
break;
case DisconnectEnum.JOIN_MEETING_TIMEOUT:
view.messageText.text = "A timeout triggered while trying to join the meeting";
break;
}
}

View File

@ -40,7 +40,10 @@ package org.bigbluebutton.air.main.views {
// If we are in the Flash Builder debugger the InvokeEvent will never be fired
if (Capabilities.isDebugger) {
//var url:String = "bigbluebutton://test-install.blindsidenetworks.com/bigbluebutton/api/join?fullName=AIR&meetingID=Demo+Meeting&password=mp&redirect=false&checksum=3fdf56e9915c1031c3ea012b4ec8823cedd7c272";
var url:String = "bigbluebutton://test-install.blindsidenetworks.com/bigbluebutton/api/join?fullName=User+2021828&meetingID=Demo+Meeting&password=ap&redirect=true&checksum=8751963df96437c7d435eac8124e4fb3ec147115";
//var url:String = "bigbluebutton://test-install.blindsidenetworks.com/bigbluebutton/api/join?fullName=User+2021828&meetingID=Demo+Meeting&password=ap&redirect=true&checksum=8751963df96437c7d435eac8124e4fb3ec147115";
var url:String = "bigbluebutton://206.47.241.19/bigbluebutton/api/join?fullName=AIR+Client&meetingID=Demo+Meeting&password=ap&redirect=true&userID=user2&checksum=c7184925fad9aa0b70da9c597cdc9772179452f0";
//var url:String = "bigbluebutton://206.47.241.19/bigbluebutton/api/join?fullName=AIR+Client&meetingID=Demo+Meeting&password=mp&redirect=true&userID=user2&checksum=cfe21ed0ee32c42f526d41b7327a84aa8e747b92";
joinRoom(url);
}
}

View File

@ -1,8 +1,10 @@
package org.bigbluebutton.air.main.views {
import org.bigbluebutton.air.common.views.NoTabView;
import org.bigbluebutton.air.presentation.views.PresentationView;
import org.bigbluebutton.air.video.views.WebcamDock;
import org.osmf.layout.HorizontalAlign;
import spark.layouts.BasicLayout;
import spark.layouts.VerticalLayout;
[Style(name = "menuHeight", inherit = "no", type = "Number")]
@ -11,20 +13,35 @@ package org.bigbluebutton.air.main.views {
private var _menuButtons:MenuButtons;
private var _webcamDock:WebcamDock;
public function MainView() {
super();
var vLayout:VerticalLayout = new VerticalLayout();
vLayout.gap = 0;
vLayout.horizontalAlign = HorizontalAlign.CENTER;
layout = vLayout;
//layout = vLayout;
var bLayout:BasicLayout = new BasicLayout();
layout = bLayout;
_presentationView = new PresentationView();
_presentationView.percentWidth = 100;
_presentationView.percentHeight = 100;
addElement(_presentationView);
// add deskshare view here and position like the presentation view
_webcamDock = new WebcamDock();
_webcamDock.percentWidth = 30;
_webcamDock.percentHeight = 30;
_webcamDock.right = 0;
addElement(_webcamDock);
_menuButtons = new MenuButtons();
_menuButtons.horizontalCenter = 0;
_menuButtons.bottom = 0;
addElement(_menuButtons);
}
@ -35,6 +52,9 @@ package org.bigbluebutton.air.main.views {
_presentationView.width = w;
_presentationView.height = h - _topToolbar.height - _menuButtons.height;
_presentationView.y = _topToolbar.height;
_webcamDock.bottom = _menuButtons.height;
}
}
}

View File

@ -0,0 +1,18 @@
package org.bigbluebutton.air.main.views {
import robotlegs.bender.bundles.mvcs.Mediator;
public class MainViewMediator extends Mediator {
[Inject]
public var view:MainView;
override public function initialize():void {
}
override public function destroy():void {
}
}
}

View File

@ -36,29 +36,21 @@ package org.bigbluebutton.air.main.views {
super();
_micButton = new Button();
_micButton.percentWidth = 100;
_micButton.percentHeight = 100;
_micButton.label = "Mic on";
_micButton.styleName = "icon-unmute menuButton";
addElement(_micButton);
_audioButton = new Button();
_audioButton.percentWidth = 100;
_audioButton.percentHeight = 100;
_audioButton.label = "Join";
_audioButton.styleName = "icon-audio-on menuButton";
addElement(_audioButton);
_camButton = new Button();
_camButton.percentWidth = 100;
_camButton.percentHeight = 100;
_camButton.label = "Cam on";
_camButton.styleName = "icon-video menuButton";
addElement(_camButton);
_statusButton = new Button();
_statusButton.percentWidth = 100;
_statusButton.percentHeight = 100;
_statusButton.label = "Status";
_statusButton.styleName = "icon-hand menuButton";
addElement(_statusButton);
@ -67,9 +59,7 @@ package org.bigbluebutton.air.main.views {
override protected function updateDisplayList(w:Number, h:Number):void {
super.updateDisplayList(w, h);
bottom = getStyle("bottom");
gap = getStyle("gap");
top = getStyle("top");
}
}
}

View File

@ -8,7 +8,6 @@ package org.bigbluebutton.air.settings {
import org.bigbluebutton.air.settings.views.audio.AudioSettingsViewBaseAIR;
import org.bigbluebutton.air.settings.views.audio.AudioSettingsViewMediatorAIR;
import org.bigbluebutton.air.settings.views.camera.CameraSettingsViewBase;
import org.bigbluebutton.air.settings.views.camera.CameraSettingsViewBaseAIR;
import org.bigbluebutton.air.settings.views.camera.CameraSettingsViewMediatorAIR;
import org.bigbluebutton.air.settings.views.chat.ChatSettingsViewBase;
import org.bigbluebutton.air.settings.views.chat.ChatSettingsViewBaseAIR;
@ -41,7 +40,7 @@ package org.bigbluebutton.air.settings {
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(CameraSettingsViewBase)).toMediator(CameraSettingsViewMediatorAIR);
mediatorMap.mapMatcher(new TypeMatcher().allOf(ChatSettingsViewBase, ChatSettingsViewBaseAIR)).toMediator(ChatSettingsViewMediatorBase);
mediatorMap.mapMatcher(new TypeMatcher().allOf(LockSettingsViewBase, LockSettingsViewBaseAIR)).toMediator(LockSettingsViewMediatorAIR);
}

View File

@ -17,7 +17,7 @@ package org.bigbluebutton.air.settings.views.camera {
vLayout.gap = 0;
layout = vLayout;
_settingsView = new CameraSettingsViewBaseAIR();
_settingsView = new CameraSettingsViewBase();
_settingsView.percentHeight = 100;
_settingsView.percentWidth = 100;
addElement(_settingsView);

View File

@ -2,11 +2,14 @@ package org.bigbluebutton.air.settings.views.camera {
import mx.core.ClassFactory;
import mx.graphics.SolidColor;
import org.bigbluebutton.air.user.views.UserItemRenderer;
import spark.components.Button;
import spark.components.Group;
import spark.components.HGroup;
import spark.components.Label;
import spark.components.List;
import spark.components.ToggleSwitch;
import spark.components.VGroup;
import spark.components.VideoDisplay;
import spark.components.supportClasses.ToggleButtonBase;
@ -14,8 +17,6 @@ package org.bigbluebutton.air.settings.views.camera {
import spark.layouts.VerticalLayout;
import spark.primitives.Rect;
import org.bigbluebutton.air.user.views.UserItemRenderer;
public class CameraSettingsViewBase extends VGroup {
private var _cameraBackground:Rect;
@ -35,7 +36,7 @@ package org.bigbluebutton.air.settings.views.camera {
private var _rotateCameraButton:Button;
protected function get toggleButtonClass():Class {
return ToggleButtonBase;
return ToggleSwitch;
}
public function get cameraHolder():Group {

View File

@ -1,9 +0,0 @@
package org.bigbluebutton.air.settings.views.camera {
import spark.components.ToggleSwitch;
public class CameraSettingsViewBaseAIR extends CameraSettingsViewBase {
override protected function get toggleButtonClass():Class {
return ToggleSwitch;
}
}
}

View File

@ -2,10 +2,12 @@ package org.bigbluebutton.air.video {
import org.bigbluebutton.air.video.commands.ShareCameraCommand;
import org.bigbluebutton.air.video.commands.ShareCameraSignal;
import org.bigbluebutton.air.video.views.WebcamDock;
import org.bigbluebutton.air.video.views.WebcamDockMediator;
import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap;
import robotlegs.bender.framework.api.IConfig;
import robotlegs.bender.framework.api.IConfig;
public class VideoConfig implements IConfig {
@ -24,14 +26,11 @@ package org.bigbluebutton.air.video {
* Maps view mediators to views.
*/
private function mediators():void {
//mediatorMap.map(IVideoButton).toMediator(VideoButtonMediator);
//mediatorMap.map(IVideoChatView).toMediator(VideoChatViewMediator);
//mediatorMap.map(ISwapCameraButton).toMediator(SwapCameraMediator);
mediatorMap.map(WebcamDock).toMediator(WebcamDockMediator);
}
private function signals():void {
signalCommandMap.map(ShareCameraSignal).toCommand(ShareCameraCommand);
//signalCommandMap.map(CameraQualitySignal).toCommand(CameraQualityCommand);
}
}
}

View File

@ -1,37 +0,0 @@
package org.bigbluebutton.air.video.air {
import flash.media.CameraPosition;
import org.bigbluebutton.air.video.services.VideoConnection;
public class AIRVideoConnection extends VideoConnection {
[PostConstruct]
public function init():void {
baseConnection.init(this);
userSession.successJoiningMeetingSignal.add(loadCameraSettings)
}
private function loadCameraSettings():void {
if (saveData.read("cameraQuality") != null) {
_selectedCameraQuality = userSession.videoProfileManager.getVideoProfileById(saveData.read("cameraQuality") as String);
if (!_selectedCameraQuality) {
_selectedCameraQuality = userSession.videoProfileManager.defaultVideoProfile;
trace("selected camera quality " + _selectedCameraQuality)
}
} else {
_selectedCameraQuality = userSession.videoProfileManager.defaultVideoProfile;
}
if (saveData.read("cameraRotation") != null) {
_selectedCameraRotation = saveData.read("cameraRotation") as int;
} else {
_selectedCameraRotation = 0;
}
if (saveData.read("cameraPosition") != null) {
_cameraPosition = saveData.read("cameraPosition") as String;
} else {
_cameraPosition = CameraPosition.FRONT;
}
}
}
}

View File

@ -2,10 +2,12 @@ package org.bigbluebutton.air.video.commands {
import flash.media.Camera;
import org.bigbluebutton.air.main.models.IConferenceParameters;
import org.bigbluebutton.air.main.models.IMeetingData;
import org.bigbluebutton.air.main.models.IUserSession;
import org.bigbluebutton.air.user.services.IUsersService;
import org.bigbluebutton.air.video.models.VideoProfile;
import org.bigbluebutton.air.video.models.WebcamStreamInfo;
import robotlegs.bender.bundles.mvcs.Command;
@ -14,14 +16,17 @@ package org.bigbluebutton.air.video.commands {
[Inject]
public var userSession:IUserSession;
[Inject]
public var usersService:IUsersService;
[Inject]
public var meetingData:IMeetingData;
[Inject]
public var enabled:Boolean;
public var conferenceParameters:IConferenceParameters;
[Inject]
public var usersService:IUsersService;
public var enabled:Boolean;
override public function execute():void {
if (enabled) {
@ -39,8 +44,12 @@ package org.bigbluebutton.air.video.commands {
trace("null video profile manager");
}
var videoProfile:VideoProfile = userSession.videoConnection.selectedCameraQuality;
var res:String = videoProfile.id;
return res.concat("-" + uid) + "-" + curTime;
var streamName:String = videoProfile.id + "-" + uid + "-" + curTime;
if (conferenceParameters.record) {
streamName += "-recorded";
}
return streamName;
}
private function setupCamera(position:String):Camera {
@ -102,9 +111,11 @@ package org.bigbluebutton.air.video.commands {
}
private function disableCamera():void {
trace("TODO: Need to actually end the webcam stream");
//usersService.removeStream(meetingData.users.me.intId, meetingData.webcams. .me.streamName);
userSession.videoConnection.stopPublishing(setupCamera(userSession.videoConnection.cameraPosition));
var webcams:Array = meetingData.webcams.findWebcamsByUserId(meetingData.users.me.intId);
if (webcams.length > 0) {
usersService.removeStream(meetingData.users.me.intId, (webcams[0] as WebcamStreamInfo).streamId);
userSession.videoConnection.stopPublishing(setupCamera(userSession.videoConnection.cameraPosition));
}
}
}
}

View File

@ -10,6 +10,8 @@ package org.bigbluebutton.air.video.models {
return _webcamChangeSignal;
}
public var viewedWebcamStream:String;
public function Webcams() {
_webcams = new Object();
_webcamChangeSignal = new Signal();
@ -54,5 +56,15 @@ package org.bigbluebutton.air.video.models {
return rw;
}
public function findWebcamByStreamId(streamId:String):WebcamStreamInfo {
for each (var webcam:WebcamStreamInfo in _webcams) {
if (webcam.streamId == streamId) {
return webcam;
}
}
return null;
}
}
}

View File

@ -7,25 +7,26 @@ package org.bigbluebutton.air.video.services {
import org.osflash.signals.ISignal;
public interface IVideoConnection {
function get connectionFailureSignal():ISignal
function get connectionSuccessSignal():ISignal
function set uri(uri:String):void
function get uri():String
function get connection():NetConnection
function get connectionFailureSignal():ISignal;
function get connectionSuccessSignal():ISignal;
function set uri(uri:String):void;
function get uri():String;
function get connection():NetConnection;
function get cameraPosition():String;
function set cameraPosition(position:String):void
function set cameraPosition(position:String):void;
function get camera():Camera;
function set camera(value:Camera):void
function set camera(value:Camera):void;
function get selectedCameraQuality():VideoProfile;
function set selectedCameraQuality(profile:VideoProfile):void
function get selectedCameraRotation():int
function set selectedCameraRotation(rotation:int):void
function connect():void
function disconnect(onUserCommand:Boolean):void
function startPublishing(camera:Camera, streamName:String):void
function set selectedCameraQuality(profile:VideoProfile):void;
function get selectedCameraRotation():int;
function set selectedCameraRotation(rotation:int):void;;
function loadCameraSettings():void;
function connect():void;
function disconnect(onUserCommand:Boolean):void;
function startPublishing(camera:Camera, streamName:String):void;
function getStreamNameForCamera(camera:Camera):String;
function stopPublishing(camera:Camera):void
function stopPublishing(camera:Camera):void;
function stopAllPublishing():void;
function selectCameraQuality(profile:VideoProfile):void
function selectCameraQuality(profile:VideoProfile):void;
}
}

View File

@ -4,6 +4,7 @@ package org.bigbluebutton.air.video.services {
import flash.events.IOErrorEvent;
import flash.events.NetStatusEvent;
import flash.media.Camera;
import flash.media.CameraPosition;
import flash.net.NetConnection;
import flash.net.NetStream;
@ -46,9 +47,7 @@ package org.bigbluebutton.air.video.services {
private var cameraToStreamNameMap:Object = new Object;
private var _ns:NetStream;
private var _cameraPosition:String;
private var _cameraPosition:String = CameraPosition.FRONT;
protected var _connectionSuccessSignal:ISignal = new Signal();
@ -65,7 +64,6 @@ package org.bigbluebutton.air.video.services {
[PostConstruct]
public function init():void {
baseConnection.init(this);
userSession.successJoiningMeetingSignal.add(loadCameraSettings);
baseConnection.connectionSuccessSignal.add(onConnectionSuccess);
baseConnection.connectionFailureSignal.add(onConnectionFailure);
meetingData.meetingStatus.lockSettingsChangeSignal.add(lockSettingsChange);
@ -77,7 +75,7 @@ package org.bigbluebutton.air.video.services {
}
}
private function loadCameraSettings():void {
public function loadCameraSettings():void {
if (saveData.read("cameraQuality") != null) {
_selectedCameraQuality = userSession.videoProfileManager.getVideoProfileById(saveData.read("cameraQuality") as String);
if (!_selectedCameraQuality) {
@ -86,6 +84,16 @@ package org.bigbluebutton.air.video.services {
} else {
_selectedCameraQuality = userSession.videoProfileManager.defaultVideoProfile;
}
if (saveData.read("cameraRotation") != null) {
_selectedCameraRotation = saveData.read("cameraRotation") as int;
} else {
_selectedCameraRotation = 0;
}
if (saveData.read("cameraPosition") != null) {
_cameraPosition = saveData.read("cameraPosition") as String;
} else {
_cameraPosition = CameraPosition.FRONT;
}
}
private function onConnectionFailure(reason:String):void {
@ -93,7 +101,6 @@ package org.bigbluebutton.air.video.services {
}
private function onConnectionSuccess():void {
_ns = new NetStream(baseConnection.connection);
connectionSuccessSignal.dispatch();
}
@ -118,7 +125,7 @@ package org.bigbluebutton.air.video.services {
}
public function connect():void {
trace("Video connect");
trace("Video connect");
baseConnection.connect(uri, conferenceParameters.meetingID, userSession.userId, conferenceParameters.authToken);
}
@ -172,13 +179,15 @@ package org.bigbluebutton.air.video.services {
}
public function startPublishing(camera:Camera, streamName:String):void {
var ns:NetStream = new NetStream(baseConnection.connection);
cameraToStreamNameMap[camera.index] = streamName;
cameraToNetStreamMap[camera.index] = new NetStream(baseConnection.connection);
_ns.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
_ns.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
_ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
_ns.client = this;
_ns.attachCamera(camera);
cameraToNetStreamMap[camera.index] = ns;
ns.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
ns.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
ns.client = this;
ns.attachCamera(camera);
/*
switch (selectedCameraRotation) {
case 90:
streamName = "rotate_right/" + streamName;
@ -190,8 +199,9 @@ package org.bigbluebutton.air.video.services {
streamName = "rotate_left/" + streamName;
break;
}
*/
trace(streamName);
_ns.publish(streamName);
ns.publish(streamName);
}
private function onNetStatus(e:NetStatusEvent):void {
@ -217,7 +227,7 @@ package org.bigbluebutton.air.video.services {
if (ns != null) {
ns.attachCamera(null);
ns.close();
ns = null;
cameraToNetStreamMap[camera.index] = null;
}
}
}

View File

@ -0,0 +1,34 @@
package org.bigbluebutton.air.video.views {
import flash.media.Video;
import flash.net.NetConnection;
import mx.graphics.SolidColor;
import org.bigbluebutton.air.common.views.VideoView;
import spark.components.BorderContainer;
import spark.components.Group;
import spark.primitives.Rect;
public class WebcamDock extends Group {
private var _video:VideoView;
public function WebcamDock() {
super();
_video = new VideoView();
_video.percentHeight = 100;
_video.percentWidth = 100;
addElement(_video);
}
public function startStream(connection:NetConnection, name:String, streamName:String, userId:String, oWidth:Number, oHeight:Number):void {
_video.startStream(connection, name, streamName, userId, oWidth, oHeight);
}
public function closeStream():void {
_video.close();
}
}
}

View File

@ -0,0 +1,87 @@
package org.bigbluebutton.air.video.views {
import org.bigbluebutton.air.main.models.IMeetingData;
import org.bigbluebutton.air.main.models.IUserSession;
import org.bigbluebutton.air.video.models.VideoProfile;
import org.bigbluebutton.air.video.models.WebcamChangeEnum;
import org.bigbluebutton.air.video.models.WebcamStreamInfo;
import org.bigbluebutton.air.video.services.IVideoConnection;
import robotlegs.bender.bundles.mvcs.Mediator;
public class WebcamDockMediator extends Mediator {
[Inject]
public var view:WebcamDock;
[Inject]
public var meetingData:IMeetingData;
[Inject]
public var userSession:IUserSession;
override public function initialize():void {
meetingData.webcams.webcamChangeSignal.add(onWebcamChangeSignal);
// check for active webcams
var viewedStream:String = meetingData.webcams.viewedWebcamStream;
if (viewedStream == "") {
// manually turned off so ignore
} else if (viewedStream != null) {
var previousWebcam:WebcamStreamInfo = meetingData.webcams.findWebcamByStreamId(viewedStream);
if (previousWebcam != null) {
startWebcam(previousWebcam);
} else {
showFirstWebcam();
}
} else {
showFirstWebcam();
}
}
private function onWebcamChangeSignal(webcam:WebcamStreamInfo, enum:int):void {
switch (enum) {
case WebcamChangeEnum.ADD:
// if none showing play it
if (meetingData.webcams.viewedWebcamStream == null) {
startWebcam(webcam);
}
break;
case WebcamChangeEnum.REMOVE:
// if playing stop
if (meetingData.webcams.viewedWebcamStream == webcam.streamId) {
stopWebcam(webcam);
}
break;
}
}
private function showFirstWebcam():void {
var webcams:Array = meetingData.webcams.getAll();
if (webcams.length > 0) {
startWebcam(webcams[0] as WebcamStreamInfo);
}
}
private function startWebcam(webcam:WebcamStreamInfo):void {
var videoProfile:VideoProfile = userSession.videoProfileManager.getVideoProfileByStreamName(webcam.streamId);
if (videoProfile) {
view.startStream(userSession.videoConnection.connection, webcam.name, webcam.streamId, webcam.userId, videoProfile.width, videoProfile.height);
meetingData.webcams.viewedWebcamStream = webcam.streamId;
}
}
private function stopWebcam(webcam:WebcamStreamInfo):void {
view.closeStream();
meetingData.webcams.viewedWebcamStream = null;
}
override public function destroy():void {
meetingData.webcams.webcamChangeSignal.remove(onWebcamChangeSignal);
if (meetingData.webcams.viewedWebcamStream) {
view.closeStream();
}
}
}
}

View File

@ -1,10 +0,0 @@
package org.bigbluebutton.air.video.views.swapcamera {
import mx.core.ILayoutElement;
import org.bigbluebutton.air.common.views.IView;
public interface ISwapCameraButton extends IView, ILayoutElement {
function setVisibility(val:Boolean):void;
}
}

View File

@ -1,18 +0,0 @@
package org.bigbluebutton.air.video.views.swapcamera {
import spark.components.Button;
public class SwapCameraButton extends Button implements ISwapCameraButton {
public function SwapCameraButton() {
super();
}
public function setVisibility(val:Boolean):void {
super.visible = val;
}
public function dispose():void {
this.dispose();
}
}
}

View File

@ -1,60 +0,0 @@
package org.bigbluebutton.air.video.views.swapcamera {
import flash.events.MouseEvent;
import flash.media.Camera;
import flash.media.CameraPosition;
import org.bigbluebutton.air.main.models.IUserSession;
import org.bigbluebutton.air.video.commands.ShareCameraSignal;
import robotlegs.bender.bundles.mvcs.Mediator;
public class SwapCameraMediator extends Mediator {
[Inject]
public var view:ISwapCameraButton;
[Inject]
public var userSession:IUserSession;
[Inject]
public var shareCameraSignal:ShareCameraSignal;
public override function initialize():void {
if (Camera.names.length > 1) {
view.setVisibility(userSession.userList.me.hasStream);
view.addEventListener(MouseEvent.CLICK, mouseClickHandler);
userSession.userList.userChangeSignal.add(userChangeHandler);
} else {
view.includeInLayout = false;
}
}
/**
* Raised on button click, will send signal to swap camera source
**/
private function mouseClickHandler(e:MouseEvent):void {
if (String(userSession.videoConnection.cameraPosition) == CameraPosition.FRONT) {
shareCameraSignal.dispatch(userSession.userList.me.hasStream, CameraPosition.BACK);
} else if (String(userSession.videoConnection.cameraPosition) == CameraPosition.BACK) {
shareCameraSignal.dispatch(userSession.userList.me.hasStream, CameraPosition.FRONT);
}
}
/**
* Update the view when there is a chenge in the model
*/
private function userChangeHandler(user:User, type:int):void {
if (user.me && type == UserList.HAS_STREAM) {
view.setVisibility(user.hasStream);
}
}
override public function destroy():void {
if (Camera.names.length > 1) {
view.removeEventListener(MouseEvent.CLICK, mouseClickHandler);
userSession.userList.userChangeSignal.remove(userChangeHandler);
}
}
}
}

View File

@ -102,6 +102,9 @@ package org.bigbluebutton.air.whiteboard.views {
}
private function drawAllAnnotations():void {
if (_whiteboard == null) {
return;
}
trace("++ draw draw Draw");
var annotations:Array = _whiteboard.getAnnotations();
for (var i:int = 0; i < annotations.length; i++) {