恩杰cam改灯光没反应的fps overlay怎么用

/ bigbluebutton
项目语言:JAVA
权限:read-only(如需更高权限请先加入项目)
bigbluebutton/
Index: business/ControlButtonsOverlay.as
===================================================================
--- business/ControlButtonsOverlay.as (revision 0)
+++ business/ControlButtonsOverlay.as (revision 15)
@@ -0,0 +1,54 @@
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+* This prog you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* F either version 3.0 of the License, or (at your option) any later
+* version.
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueB if not, see &http://www.gnu.org/licenses/&.
+package org.bigbluebutton.modules.videoconf.business
+ import mx.containers.HB
+ import mx.controls.B
+ import flash.utils.D
+ import flash.events.MouseE
+ import mon.LogU
+ public class ControlButtonsOverlay extends HBox
private var buttons:Dictionary = new D
private var BUTTONS_SIZE:int = 20;
private var BUTTONS_PADDING:int = 10;
public function add(name:String, icon:Class, tooltip:String, listener:Function):void {
var button:Button = new B
button.setStyle(&icon&, icon);
button.toolTip =
button.addEventListener(MouseEvent.CLICK, listener);
button.width = button.height = BUTTONS_SIZE;
this.addChild(button);
buttons[name] =
public function get(name:String):Button {
var tmp:Object = buttons[name];
return (tmp as Button);
public function get padding():int {
return BUTTONS_PADDING;
\ No newline at end of file
Index: business/VideoWindowItf.as
===================================================================
--- business/VideoWindowItf.as (revision 0)
+++ business/VideoWindowItf.as (revision 15)
@@ -0,0 +1,319 @@
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+* This prog you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* F either version 3.0 of the License, or (at your option) any later
+* version.
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueB if not, see &http://www.gnu.org/licenses/&.
+package org.bigbluebutton.modules.videoconf.business
+ import com.asfusion.mate.events.D
+ import flash.events.MouseE
+ import flash.geom.P
+ import flash.media.V
+ import flexlib.mdi.containers.MDIW
+ import flexlib.mdi.events.MDIWindowE
+ import mx.containers.P
+ import mx.controls.B
+ import mx.core.UIC
+ import mon.IBbbModuleW
+ import mon.I
+ import mon.LogU
+ import mon.events.CloseWindowE
+ import mon.events.DragWindowE
+ import org.bigbluebutton.core.EventC
+ import org.bigbluebutton.core.UsersU
+ import org.bigbluebutton.core.events.CoreE
+ import org.bigbluebutton.core.managers.UserM
+ import org.bigbluebutton.main.model.users.BBBU
+ import org.bigbluebutton.main.model.users.events.KickUserE
+ import org.bigbluebutton.main.model.users.events.RoleChangeE
+ import org.bigbluebutton.main.views.MainC
+ import org.bigbluebutton.modules.videoconf.events.UserTalkingE
+ import org.bigbluebutton.modules.videoconf.model.VideoConfO
+ import org.bigbluebutton.modules.videoconf.views.ControlB
+ import org.bigbluebutton.util.i18n.ResourceU
+ public class VideoWindowItf extends MDIWindow implements IBbbModuleWindow
protected var _video:V
protected var _videoHolder:UIC
// images must be static because it needs to be created *before* the PublishWindow creation
static protected var images:Images = new Images();
static public var PADDING_HORIZONTAL:Number = 6;
static public var PADDING_VERTICAL:Number = 29;
protected var _minWidth:int = 160 + PADDING_HORIZONTAL;
protected var _minHeight:int = 120 + PADDING_VERTICAL;
protected var aspectRatio:Number = 1;
protected var keepAspect:Boolean =
protected var mousePositionOnDragStart:P
public var streamName:S
private var windowType:String = &VideoWindowItf&;
public var userID:String =
protected var _controlButtons:ControlButtons = new ControlButtons();
[Bindable] public var resolutions:A
+ protected var videoConfOptions:VideoConfOptions = new VideoConfOptions();
public function getWindowType():String {
return windowT
protected function updateControlButtons():void {
_controlButtons.updateControlButtons();
protected function getVideoResolution(stream:String):Array {
var pattern:RegExp = new RegExp(&(\\d+x\\d+)-([A-Za-z0-9]+)-\\d+&, &&);
if (pattern.test(stream)) {
LogUtil.debug(&The stream name is well formatted [& + stream + &]&);
var uid:String = UserManager.getInstance().getConference().getMyUserId();
LogUtil.debug(&Stream resolution is [& + pattern.exec(stream)[1] + &]&);
LogUtil.debug(&Userid [& + pattern.exec(stream)[2] + &]&);
userID = pattern.exec(stream)[2];
addControlButtons();
return pattern.exec(stream)[1].split(&x&);
LogUtil.error(&The stream name doesn't follow the pattern &width&x&height&-&userId&-&timestamp&. However, the video resolution will be set to the lowest defined resolution in the config.xml: & + resolutions[0]);
return resolutions[0].split(&x&);
protected function get paddingVertical():Number {
return this.borderMetrics.top + this.borderMetrics.
protected function get paddingHorizontal():Number {
return this.borderMetrics.left + this.borderMetrics.
static private var RESIZING_DIRECTION_UNKNOWN:int = 0;
static private var RESIZING_DIRECTION_VERTICAL:int = 1;
static private var RESIZING_DIRECTION_HORIZONTAL:int = 2;
static private var RESIZING_DIRECTION_BOTH:int = 3;
private var resizeDirection:int = RESIZING_DIRECTION_BOTH;
* when the window is resized by the user, the application doesn't know
* about the resize direction
public function onResizeStart(event:MDIWindowEvent = null):void {
resizeDirection = RESIZING_DIRECTION_UNKNOWN;
* after the resize ends, the direction is set to BOTH because of the
* non-user resize actions - like when the window is docked, and so on
public function onResizeEnd(event:MDIWindowEvent = null):void {
resizeDirection = RESIZING_DIRECTION_BOTH;
protected function onResize():void {
if (_video == null || _videoHolder == null || this.minimized)
// limits the window size to the parent size
this.width = (this.parent != null? Math.min(this.width, this.parent.width): this.width);
this.height = (this.parent != null? Math.min(this.height, this.parent.height): this.height);
var tmpWidth:Number = this.width - PADDING_HORIZONTAL;
var tmpHeight:Number = this.height - PADDING_VERTICAL;
// try to discover in which direction the user is resizing the window
if (resizeDirection != RESIZING_DIRECTION_BOTH) {
if (tmpWidth == _video.width && tmpHeight != _video.height)
resizeDirection = (resizeDirection == RESIZING_DIRECTION_VERTICAL || resizeDirection == RESIZING_DIRECTION_UNKNOWN? RESIZING_DIRECTION_VERTICAL: RESIZING_DIRECTION_BOTH);
else if (tmpWidth != _video.width && tmpHeight == _video.height)
resizeDirection = (resizeDirection == RESIZING_DIRECTION_HORIZONTAL || resizeDirection == RESIZING_DIRECTION_UNKNOWN? RESIZING_DIRECTION_HORIZONTAL: RESIZING_DIRECTION_BOTH);
resizeDirection = RESIZING_DIRECTION_BOTH;
// depending on the direction, the tmp size is different
switch (resizeDirection) {
case RESIZING_DIRECTION_VERTICAL:
tmpWidth = Math.floor(tmpHeight * aspectRatio);
case RESIZING_DIRECTION_HORIZONTAL:
tmpHeight = Math.floor(tmpWidth / aspectRatio);
case RESIZING_DIRECTION_BOTH:
// this direction is used also for non-user window resize actions
tmpWidth = Math.min (tmpWidth, Math.floor(tmpHeight * aspectRatio));
tmpHeight = Math.min (tmpHeight, Math.floor(tmpWidth / aspectRatio));
_video.width = _videoHolder.width = tmpW
_video.height = _videoHolder.height = tmpH
if (!keepAspect || this.maximized) {
// center the video in the window
_video.x = Math.floor ((this.width - PADDING_HORIZONTAL - tmpWidth) / 2);
_video.y = Math.floor ((this.height - PADDING_VERTICAL - tmpHeight) / 2);
// fit window dimensions on video
_video.x = 0;
_video.y = 0;
this.width = tmpWidth + PADDING_HORIZONTAL;
this.height = tmpHeight + PADDING_VERTICAL;
// reposition the window to fit inside the parent window
if (this.parent != null) {
if (this.x + this.width & this.parent.width)
this.x = this.parent.width - this.
if (this.x & 0)
this.x = 0;
if (this.y + this.height & this.parent.height)
this.y = this.parent.height - this.
if (this.y & 0)
this.y = 0;
updateButtonsPosition();
public function updateWidth():void {
this.width = Math.floor((this.height - paddingVertical) * aspectRatio) + paddingH
onResize();
public function updateHeight():void {
this.height = Math.floor((this.width - paddingHorizontal) / aspectRatio) + paddingV
onResize();
protected function setAspectRatio(width:int,height:int):void {
aspectRatio = (width/height);
this.minHeight = Math.floor((this.minWidth - PADDING_HORIZONTAL) / aspectRatio) + PADDING_VERTICAL;
public function getPrefferedPosition():String{
if (_controlButtonsEnabled)
return MainCanvas.POPUP;
// the window is docked, so it should not be moved on reset layout
return MainCanvas.ABSOLUTE;
override public function close(event:MouseEvent = null):void{
trace(&VideoWIndowItf close window event&);
var e:CloseWindowEvent = new CloseWindowEvent();
e.window =
dispatchEvent(e);
super.close(event);
private var _controlButtonsEnabled:Boolean =
private var img_unlock_keep_aspect:Class = images.lock_
private var img_lock_keep_aspect:Class = images.lock_
private var img_fit_video:Class = images.arrow_
private var img_original_size:Class = images.shape_
private var img_mute_icon:Class = images.webcam_
private var signOutIcon:Class = images.webcam_
private var adminIcon:Class = images.webcam_make_
private var chatIcon:Class = images.webcam_private_
protected function addControlButtons():void {
_controlButtons.sharerUserID = userID;
_controlButtons.visible =
this.addChild(_controlButtons);
protected function get controlButtons():ControlButtons {
if (_controlButtons == null) {
_controlButtons.visible =
return _controlB
protected function createButtons():void {
updateButtonsPosition();
protected function updateButtonsPosition():void {
if (this.width & controlButtons.width) {
controlButtons.visible =
if (controlButtons.visible == false) {
controlButtons.y = controlButtons.x = 0;
controlButtons.y = this.height - PADDING_VERTICAL - controlButtons.height - controlButtons.
controlButtons.x = this.width - PADDING_HORIZONTAL - controlButtons.width - controlButtons.
protected function showButtons(event:MouseEvent = null):void {
if (_controlButtonsEnabled && controlButtons.visible == false && this.width & controlButtons.width) {
controlButtons.visible =
updateButtonsPosition();
protected function hideButtons(event:MouseEvent = null):void {
if (_controlButtonsEnabled && controlButtons.visible == true) {
controlButtons.visible =
updateButtonsPosition();
protected function onDoubleClick(event:MouseEvent = null):void {
// it occurs when the window is docked, for example
if (!this.maximizeRestoreBtn.visible)
this.maximizeRestore();
override public function maximizeRestore(event:MouseEvent = null):void {
// if the user is maximizing the window, the control buttons should disappear
buttonsEnabled = this.
super.maximizeRestore(event);
public function set buttonsEnabled(enabled:Boolean):void {
if (!enabled)
hideButtons();
_controlButtonsEnabled =
protected function userMuted(muted:Boolean):void {
_controlButtons.userMuted(muted);
protected function simulateClick():void {
if (videoConfOptions.focusTalking) {
var talkingEvent:UserTalkingEvent = new UserTalkingEvent(UserTalkingEvent.TALKING);
dispatchEvent(talkingEvent);
\ No newline at end of file
Index: business/TalkingButtonOverlay.as
===================================================================
--- business/TalkingButtonOverlay.as (revision 0)
+++ business/TalkingButtonOverlay.as (revision 15)
@@ -0,0 +1,60 @@
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+* This prog you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* F either version 3.0 of the License, or (at your option) any later
+* version.
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueB if not, see &http://www.gnu.org/licenses/&.
+package org.bigbluebutton.modules.videoconf.business
+ import flash.events.MouseE
+ import flash.utils.D
+ import mx.containers.HB
+ import mx.controls.B
+ import mon.I
+ import mon.LogU
+ public class TalkingButtonOverlay extends HBox
private var images:Images = new Images();
private var buttons:Dictionary = new D
private var BUTTONS_SIZE:int = 20;
private var BUTTONS_PADDING:int = 10;
public function add(name:String, icon:Class, tooltip:String, listener:Function):void {
var button:Button = new B
button.setStyle(&icon&, icon);
button.toolTip =
button.addEventListener(MouseEvent.CLICK, listener);
button.width = button.height = BUTTONS_SIZE;
button.enabled =
this.addChild(button);
buttons[name] =
public function get(name:String):Button {
var tmp:Object = buttons[name];
//return (flash.utils.getQualifiedClassName(tmp) == &mx.controls::Button&? (tmp as Button): null);
return (tmp as Button);
public function get padding():int {
return BUTTONS_PADDING;
\ No newline at end of file
Index: business/VideoProxy.as
===================================================================
--- business/VideoProxy.as (revision 0)
+++ business/VideoProxy.as (revision 15)
@@ -0,0 +1,196 @@
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+* This prog you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* F either version 3.0 of the License, or (at your option) any later
+* version.
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueB if not, see &http://www.gnu.org/licenses/&.
+package org.bigbluebutton.modules.videoconf.business
+ import com.asfusion.mate.events.D
+ import flash.events.AsyncErrorE
+ import flash.events.IOErrorE
+ import flash.events.NetStatusE
+ import flash.events.SecurityErrorE
+ import flash.media.H264L
+ import flash.media.H264P
+ import flash.media.H264VideoStreamS
+ import flash.net.NetC
+ import flash.net.NetS
+ import flash.system.C
+ import mx.collections.ArrayC
+ import mon.LogU
+ import org.bigbluebutton.core.BBB;
+ import org.bigbluebutton.core.managers.UserM
+ import org.bigbluebutton.main.model.users.BBBU
+ import org.bigbluebutton.main.model.users.events.StreamStartedE
+ import org.bigbluebutton.modules.videoconf.events.ConnectedE
+ import org.bigbluebutton.modules.videoconf.events.StartBroadcastE
+ import org.bigbluebutton.modules.videoconf.model.VideoConfO
+ public class VideoProxy
public var videoOptions:VideoConfO
private var nc:NetC
private var ns:NetS
private var _url:S
private function parseOptions():void {
videoOptions = new VideoConfOptions();
videoOptions.parseOptions();
public function VideoProxy(url:String)
parseOptions();
nc = new NetConnection();
nc.client =
nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
nc.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
nc.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
public function connect():void {
nc.connect(_url);
private function onAsyncError(event:AsyncErrorEvent):void{
private function onIOError(event:NetStatusEvent):void{
private function onConnectedToVideoApp():void{
var dispatcher:Dispatcher = new Dispatcher();
dispatcher.dispatchEvent(new ConnectedEvent(ConnectedEvent.VIDEO_CONNECTED));
private function onNetStatus(event:NetStatusEvent):void{
case &NetConnection.Connect.Success&:
ns = new NetStream(nc);
onConnectedToVideoApp();
LogUtil.debug(&[& + .code + &] for [& + _url + &]&);
private function onSecurityError(event:NetStatusEvent):void{
public function get connection():NetConnection{
return this.
public function startPublishing(e:StartBroadcastEvent):void{
ns.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
ns.addEventListener( IOErrorEvent.IO_ERROR, onIOError );
ns.addEventListener( AsyncErrorEvent.ASYNC_ERROR, onAsyncError );
ns.client =
ns.attachCamera(e.camera);
Uncomment if you want to build support for H264. But you need at least FP 11. (ralam july 23, 2011)
if (Capabilities.version.search(&11,0&) != -1) {
if ((BBB.getFlashPlayerVersion() &= 11) && videoOptions.enableH264) {
if (BBB.getFlashPlayerVersion() &= 11) {
(&Using H264 codec for video.&);
var h264:H264VideoStreamSettings = new H264VideoStreamSettings();
var h264profile:String = H264Profile.MAIN;
if (videoOptions.h264Profile != &main&) {
h264profile = H264Profile.BASELINE;
var h264Level:String = H264Level.LEVEL_4_1;
if (videoOptions.h264Level == &1&) {
h264Level = H264Level.LEVEL_1;
} else if (videoOptions.h264Level == &1.1&) {
h264Level = H264Level.LEVEL_1_1;
} else if (videoOptions.h264Level == &1.2&) {
h264Level = H264Level.LEVEL_1_2;
} else if (videoOptions.h264Level == &1.3&) {
h264Level = H264Level.LEVEL_1_3;
} else if (videoOptions.h264Level == &1b&) {
h264Level = H264Level.LEVEL_1B;
} else if (videoOptions.h264Level == &2&) {
h264Level = H264Level.LEVEL_2;
} else if (videoOptions.h264Level == &2.1&) {
h264Level = H264Level.LEVEL_2_1;
} else if (videoOptions.h264Level == &2.2&) {
h264Level = H264Level.LEVEL_2_2;
} else if (videoOptions.h264Level == &3&) {
h264Level = H264Level.LEVEL_3;
} else if (videoOptions.h264Level == &3.1&) {
h264Level = H264Level.LEVEL_3_1;
} else if (videoOptions.h264Level == &3.2&) {
h264Level = H264Level.LEVEL_3_2;
} else if (videoOptions.h264Level == &4&) {
h264Level = H264Level.LEVEL_4;
} else if (videoOptions.h264Level == &4.1&) {
h264Level = H264Level.LEVEL_4_1;
} else if (videoOptions.h264Level == &4.2&) {
h264Level = H264Level.LEVEL_4_2;
} else if (videoOptions.h264Level == &5&) {
h264Level = H264Level.LEVEL_5;
} else if (videoOptions.h264Level == &5.1&) {
h264Level = H264Level.LEVEL_5_1;
(&Codec used: & + h264Level);
h264.setProfileLevel(h264profile, h264Level);
ns.videoStreamSettings = h264;
ns.publish(e.stream);
public function stopBroadcasting():void{
trace(&Closing netstream for webcam publishing&);
if (ns != null) {
ns.attachCamera(null);
ns.close();
ns = new NetStream(nc);
public function disconnect():void {
trace(&VideoProxy:: disconnecting from Video application&);
stopBroadcasting();
if (nc != null) nc.close();
public function onBWCheck(... rest):Number {
public function onBWDone(... rest):void {
var p_bw:N
if (rest.length & 0) p_bw = rest[0];
// your application should do something here
// when the bandwidth check is complete
trace(&bandwidth = & + p_bw + & Kbps.&);
Index: views/ControlButtons.mxml
===================================================================
--- views/ControlButtons.mxml (revision 0)
+++ views/ControlButtons.mxml (revision 15)
@@ -0,0 +1,219 @@
+&?xml version=&1.0& encoding=&utf-8&?&
+BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+This prog you can redistribute it and/or modify it under the
+terms of the GNU Lesser General Public License as published by the Free Software
+F either version 3.0 of the License, or (at your option) any later
+BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+You should have received a copy of the GNU Lesser General Public License along
+with BigBlueB if not, see &http://www.gnu.org/licenses/&.
+&mx:HBox xmlns:mx=&/2006/mxml&
xmlns:mate=&/&
creationComplete=&onCreationComplete()&&
&mx:Script&
import com.asfusion.mate.events.D
import mon.I
import mon.LogU
import org.bigbluebutton.core.BBB;
import org.bigbluebutton.core.EventC
import org.bigbluebutton.core.UsersU
import org.bigbluebutton.core.events.CoreE
import org.bigbluebutton.core.events.VoiceConfE
import org.bigbluebutton.main.model.users.BBBU
import org.bigbluebutton.main.model.users.events.KickUserE
import org.bigbluebutton.main.model.users.events.RoleChangeE
import org.bigbluebutton.modules.chat.model.ChatO
import org.bigbluebutton.modules.users.model.UsersO
import org.bigbluebutton.modules.videoconf.model.VideoConfO
import org.bigbluebutton.util.i18n.ResourceU
public var sharerUserID:S
[Bindable]
private var BUTTONS_SIZE:int = 31;
private var BUTTONS_PADDING:int = 10;
[Bindable]
private var showButton:B
private function onCreationComplete():void {
showControlButtons();
showPrivateChatButton();
public function get padding():int {
return BUTTONS_PADDING;
public function userMuted(muted:Boolean):void {
if (muted) {
muteUnmuteBtn.styleName = &videoMutedButtonStyle&;
muteUnmuteBtn.styleName = &videoUnmutedButtonStyle&;
public function updateControlButtons():void {
showControlButtons();
private function onKickUserClicked(event:Event):void {
event.stopImmediatePropagation();
var gd:Dispatcher = new Dispatcher();
gd.dispatchEvent(new KickUserEvent(sharerUserID));
private function onPrivateChatClicked(event:Event):void {
event.stopImmediatePropagation();
var e:CoreEvent = new CoreEvent(EventConstants.START_PRIVATE_CHAT);
e.message.chatWith = sharerUserID;
var gd:Dispatcher = new Dispatcher();
gd.dispatchEvent(e);
private function onSwitchPresenterClicked(event:Event):void {
event.stopImmediatePropagation();
var e:RoleChangeEvent = new RoleChangeEvent(RoleChangeEvent.ASSIGN_PRESENTER);
e.userid = sharerUserID;
e.username = UsersUtil.getUserName(sharerUserID);
var gd:Dispatcher = new Dispatcher();
gd.dispatchEvent(e);
private function onMuteUnmuteClicked(event:Event):void {
event.stopImmediatePropagation();
var bu:BBBUser = UsersUtil.getUser(sharerUserID);
if (bu != null) {
var e:VoiceConfEvent = new VoiceConfEvent(VoiceConfEvent.MUTE_USER);
e.userid = bu.voiceU
e.mute = ! bu.voiceM
var gd:Dispatcher = new Dispatcher();
gd.dispatchEvent(e);
private function showControlButtons():void {
var vidOptions:VideoConfOptions = new VideoConfOptions();
displaySwitchPresenterButton(vidOptions.controlsForPresenter);
displayMuteButton(vidOptions.controlsForPresenter);
displayEjectButton(vidOptions.controlsForPresenter);
private function displayEjectButton(controlsForPresenter:Boolean):void {
var userOption:UsersOptions = new UsersOptions();
if (! userOption.allowKickUser) {
trace(&Kicking user not allowed&);
// User kicking not enabled. J
ejectUserBtn.visible =
trace(&Kicking user allowed [& + userOption.allowKickUser + &]&);
* Display button if:
* 1. If I am moderator and this window is not me.
* 2. If I am the presenter and display controls for presenter and this window is not me.
if (ejectUserBtn != null) {
if (UsersUtil.amIModerator() && ! UsersUtil.isMe(sharerUserID)) {
ejectUserBtn.visible =
ejectUserBtn.toolTip = ResourceUtil.getInstance().getString('bbb.video.controls.ejectUserBtn.toolTip', [UsersUtil.getUserName(sharerUserID)]);
if (controlsForPresenter && UsersUtil.amIPresenter() && ! UsersUtil.isMe(sharerUserID)) { /** 2 **/
ejectUserBtn.visible =
ejectUserBtn.toolTip = ResourceUtil.getInstance().getString('bbb.video.controls.ejectUserBtn.toolTip', [UsersUtil.getUserName(sharerUserID)]);
ejectUserBtn.visible =
private function displaySwitchPresenterButton(controlsForPresenter:Boolean):void {
* Display button if:
* 1. If I am moderator and this user is NOT presenter.
* 2. If I am the presenter and display controls for presenter and this window is not me.
if (switchPresenter != null) {
if (UsersUtil.amIModerator() && (sharerUserID != UsersUtil.getPresenterUserID())) { /** 1. **/
switchPresenter.visible =
switchPresenter.toolTip = ResourceUtil.getInstance().getString('bbb.video.controls.switchPresenter.toolTip', [UsersUtil.getUserName(sharerUserID)]);
if (controlsForPresenter && UsersUtil.amIPresenter() && ! UsersUtil.isMe(sharerUserID)) { /** 2 **/
switchPresenter.visible =
switchPresenter.toolTip = ResourceUtil.getInstance().getString('bbb.video.controls.switchPresenter.toolTip', [UsersUtil.getUserName(sharerUserID)]);
switchPresenter.visible =
private function displayMuteButton(controlsForPresenter:Boolean):void {
* Display button if user is joined to voice and:
* 1. if I am moderator OR
* 2. if display controls for presenter and I am presenter OR
* 3. if this window is me
if (muteUnmuteBtn != null) {
if (UsersUtil.isUserJoinedToVoice(sharerUserID)) {
if (UsersUtil.amIModerator() || (controlsForPresenter && UsersUtil.amIPresenter()) || UsersUtil.isMe(sharerUserID)) {
muteUnmuteBtn.visible =
muteUnmuteBtn.toolTip = ResourceUtil.getInstance().getString('bbb.video.controls.muteButton.toolTip', [UsersUtil.getUserName(sharerUserID)]);
muteUnmuteBtn.visible =
private function showPrivateChatButton():void {
var chatOptions:ChatOptions = new ChatOptions();
// the first check is to see if the chat module is in the config.xml
if (BBB.getConfigForModule(&ChatModule&) && chatOptions.privateEnabled && ! UsersUtil.isMe(sharerUserID)) {
privateChatBtn.toolTip = ResourceUtil.getInstance().getString('bbb.video.controls.privateChatBtn.toolTip', [UsersUtil.getUserName(sharerUserID)]);
privateChatBtn.visible =
privateChatBtn.visible =
privateChatBtn.includeInLayout =
&/mx:Script&
&mx:Button id=&muteUnmuteBtn& visible=&false& click=&onMuteUnmuteClicked(event)&
width=&{BUTTONS_SIZE}& height=&{BUTTONS_SIZE}& styleName=&videoUnmutedButtonStyle&/&
&mx:Spacer width=&2&/&
&mx:Button id=&switchPresenter& visible=&false& click=&onSwitchPresenterClicked(event)&
width=&{BUTTONS_SIZE}& height=&{BUTTONS_SIZE}& styleName=&videoSwitchPresenterButtonStyle&/&
&mx:Spacer width=&2&/&
&mx:Button id=&ejectUserBtn& visible=&false& click=&onKickUserClicked(event)&
width=&{BUTTONS_SIZE}& height=&{BUTTONS_SIZE}& styleName=&videoEjectUserButtonStyle&/&
&mx:Spacer width=&2&/&
&mx:Button id=&privateChatBtn& click=&onPrivateChatClicked(event)&
width=&{BUTTONS_SIZE}& height=&{BUTTONS_SIZE}& styleName=&videoPrivateChatButtonStyle&/&
+&/mx:HBox&
Index: views/AvatarWindow.mxml
===================================================================
--- views/AvatarWindow.mxml (revision 0)
+++ views/AvatarWindow.mxml (revision 15)
@@ -0,0 +1,256 @@
+&?xml version=&1.0& encoding=&utf-8&?&
+BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+This prog you can redistribute it and/or modify it under the
+terms of the GNU Lesser General Public License as published by the Free Software
+F either version 3.0 of the License, or (at your option) any later
+BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+You should have received a copy of the GNU Lesser General Public License along
+with BigBlueB if not, see &http://www.gnu.org/licenses/&.
+&pubVid:VideoWindowItf
+ xmlns:mx=&/2006/mxml&
+ xmlns:pubVid=&org.bigbluebutton.modules.videoconf.business.*&
+ implements=&mon.IBbbModuleWindow&
+ styleNameFocus=&videoAvatarStyleFocus&
+ styleNameNoFocus=&videoAvatarStyleNoFocus&
+ creationComplete=&onCreationComplete()&
+ width=&{defaultWidth + 6}& height=&{defaultHeight + 6}&
+ xmlns:mate=&/&
+ resize=&onResize()&
+ horizontalScrollPolicy=&off&
+ verticalScrollPolicy=&off&
+ layout=&absolute&&
+ &mate:Listener type=&{BBBEvent.USER_VOICE_MUTED}& method=&handleUserVoiceMutedEvent& /&
+ &mate:Listener type=&{EventConstants.USER_TALKING}& method=&handleUserTalkingEvent& /&
&mate:Listener type=&{SwitchedPresenterEvent.SWITCHED_PRESENTER}& method=&handleSwitchedPresenterEvent& /&
&mate:Listener type=&{MadePresenterEvent.SWITCH_TO_PRESENTER_MODE}& method=&handleMadePresenterEvent& /&
&mate:Listener type=&{BBBEvent.USER_VOICE_JOINED}& method=&handleNewRoleEvent& /&
&mate:Listener type=&{BBBEvent.USER_VOICE_LEFT}& method=&handleNewRoleEvent& /&
+ &mate:Listener type=&{CloseAllWindowsEvent.CLOSE_ALL_WINDOWS}& method=&closeWindow& /&
+ &mx:Script&
import flexlib.mdi.events.MDIWindowE
import mx.core.UIC
import mx.events.ResizeE
import mon.I
import mon.LogU
import mon.R
import mon.events.CloseWindowE
import mon.events.LocaleChangeE
import org.bigbluebutton.core.EventC
import org.bigbluebutton.core.UsersU
import org.bigbluebutton.core.events.CoreE
import org.bigbluebutton.core.events.SwitchedLayoutE
import org.bigbluebutton.core.managers.UserM
import org.bigbluebutton.main.events.BBBE
import org.bigbluebutton.main.events.MadePresenterE
import org.bigbluebutton.main.events.SwitchedPresenterE
import org.bigbluebutton.main.views.MainC
import org.bigbluebutton.modules.videoconf.business.TalkingButtonO
import org.bigbluebutton.modules.videoconf.events.CloseAllWindowsE
import org.bigbluebutton.modules.videoconf.events.OpenVideoWindowE
import org.bigbluebutton.modules.videoconf.events.StartBroadcastE
import org.bigbluebutton.modules.videoconf.model.VideoConfO
import org.bigbluebutton.util.i18n.ResourceU
[Bindable] private var defaultWidth:Number = 320;
[Bindable] private var defaultHeight:Number = 240;
[Bindable] public var glowColor:String = &&;
[Bindable] public var glowBlurSize:Number = 0;
private var avatarWidth:Number = 320;
private var avatarHeight:Number = 240;
private var videoconfOptions:VideoConfOptions = new VideoConfOptions();
private var windowType:String = &AvatarWindowType&;
override public function getWindowType():String {
return windowT
private var loader:L
private var request:URLR
private function loadAvatar():void {
request = new URLRequest(UsersUtil.getAvatarURL());
loader.contentLoaderInfo.PLETE, onLoadingComplete);
loader.load(request);
private function onLoadingComplete(event:Event):void {
// Save the size of the avatar image.
avatarWidth = loader.content.
avatarHeight = loader.content.
onResize();
private function onCreationComplete():void {
this.glowColor = videoconfOptions.glowC
this.glowBlurSize = videoconfOptions.glowBlurS
loader = new Loader();
_videoHolder = new UIComponent();
_videoHolder.width = avatarW
_videoHolder.height = avatarH
this.addChild(_videoHolder);
_videoHolder.addChild(loader);
_video = new Video();
_video.width = avatarW
_video.height = avatarH
this.minWidth = _minW
this.minHeight = _minH
maximizeRestoreBtn.visible =
this.showCloseButton = videoconfOptions.showCloseB
this.resizable =
setAspectRatio(avatarWidth, avatarHeight);
addEventListener(MDIWindowEvent.RESIZE_START, onResizeStart);
addEventListener(MDIWindowEvent.RESIZE_END, onResizeEnd);
addEventListener(MouseEvent.MOUSE_OVER, showButtons);
addEventListener(MouseEvent.MOUSE_OUT, hideButtons);
startPublishing();
loadAvatar();
override protected function onResize():void {
super.onResize();
if (loader != null && _videoHolder != null) {
if (avatarIsSmallerThanWindow()) {
// The avatar image is smaller than the window. Just center the image.
_video.width = loader.width = avatarW
_video.height = loader.height = avatarH
// The avatar is bigger than the window. Fit into the window maintaining aspect ratio.
fitAvatarToWindow();
_video.x = loader.x = (this.width - PADDING_HORIZONTAL - loader.width) / 2;
_video.y = loader.y = (this.height - PADDING_VERTICAL - loader.height) / 2;
private function fitAvatarToWindow():void {
if (_videoHolder.width - PADDING_HORIZONTAL & _videoHolder.height - PADDING_VERTICAL) {
fitToHeightAndAdjustWidthToMaintainAspectRatio();
fitToWidthAndAdjustHeightToMaintainAspectRatio();
private function avatarIsSmallerThanWindow():Boolean {
return (avatarWidth & _videoHolder.width - PADDING_HORIZONTAL) && (avatarHeight & _videoHolder.height - PADDING_VERTICAL);
private function fitToWidthAndAdjustHeightToMaintainAspectRatio():void {
var aspect:Number = avatarHeight / avatarW
_video.width = loader.width = _videoHolder.width - PADDING_HORIZONTAL;
// Maintain aspect-ratio
_video.height = loader.height = loader.width *
private function fitToHeightAndAdjustWidthToMaintainAspectRatio():void {
var aspect:Number = avatarWidth / avatarH
_video.height = loader.height = _videoHolder.height - PADDING_VERTICAL;
// Maintain aspect-ratio
_video.width = loader.width = loader.height *
private function handleMadePresenterEvent(event:MadePresenterEvent):void {
trace(&******** Avatar: HandleMadePresenter event *********&);
updateControlButtons();
private function handleSwitchedPresenterEvent(event:SwitchedPresenterEvent):void {
trace(&******** Avatar: handleSwitchedPresenterEvent event *********&);
updateControlButtons();
private function handleNewRoleEvent(event:Event):void {
updateControlButtons();
private function handleUserVoiceMutedEvent(event:BBBEvent):void {
if (event.payload.userID ==
userMuted(event.payload.muted);
private function handleUserTalkingEvent(event:CoreEvent):void {
if (event.message.userID ==
if (event.message.talking) {
notTalkingEffect.end();
talkingEffect.play([this]);
simulateClick();
talkingEffect.end();
notTalkingEffect.play([this]);
private function startPublishing():void{
this.resizable =
onResize();
createButtons();
addControlButtons();
updateButtonsPosition();
override public function close(event:MouseEvent=null):void{
closeThisWindow();
super.close(event);
private function closeWindow(e:CloseAllWindowsEvent):void{
closeThisWindow();
private function closeThisWindow():void {
trace(&* Closing avatar window for user [& + userID + &] *&);
+ &/mx:Script&
+ &mx:Glow id=&talkingEffect& duration=&500& alphaFrom=&1.0& alphaTo=&0.3&
blurXFrom=&0.0& blurXTo=&{glowBlurSize}& blurYFrom=&0.0& blurYTo=&{glowBlurSize}& color=&{glowColor}&/&
+ &mx:Glow id=&notTalkingEffect& duration=&500& alphaFrom=&0.3& alphaTo=&1.0&
blurXFrom=&{glowBlurSize}& blurXTo=&0.0& blurYFrom=&{glowBlurSize}& blurYTo=&0.0& color=&{glowColor}&/&
+&/pubVid:VideoWindowItf&
Index: views/PublishWindow.mxml
===================================================================
--- views/PublishWindow.mxml (revision 0)
+++ views/PublishWindow.mxml (revision 15)
@@ -0,0 +1,477 @@
+&?xml version=&1.0& encoding=&utf-8&?&
+BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+This prog you can redistribute it and/or modify it under the
+terms of the GNU Lesser General Public License as published by the Free Software
+F either version 3.0 of the License, or (at your option) any later
+BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+You should have received a copy of the GNU Lesser General Public License along
+with BigBlueB if not, see &http://www.gnu.org/licenses/&.
+&pubVid:VideoWindowItf
+ xmlns:mx=&/2006/mxml&
+ xmlns:pubVid=&org.bigbluebutton.modules.videoconf.business.*&
+ initialize=&init()&
+ implements=&mon.IBbbModuleWindow&
+ styleNameFocus=&videoPublishStyleFocus&
+ styleNameNoFocus=&videoPublishStyleNoFocus&
+ creationComplete=&onCreationComplete()&
+ width=&{defaultWidth + 6}& height=&{defaultHeight + 6}&
+ xmlns:mate=&/&
+ resize=&onResize()&
+ horizontalScrollPolicy=&off&
+ verticalScrollPolicy=&off&
+ layout=&absolute&&
&mate:Listener type=&{BBBEvent.USER_VOICE_MUTED}& method=&handleUserVoiceMutedEvent& /&
&mate:Listener type=&{EventConstants.USER_TALKING}& method=&handleUserTalkingEvent& /&
&mate:Listener type=&{SwitchedPresenterEvent.SWITCHED_PRESENTER}& method=&handleSwitchedPresenterEvent& /&
&mate:Listener type=&{MadePresenterEvent.SWITCH_TO_PRESENTER_MODE}& method=&handleMadePresenterEvent& /&
&mate:Listener type=&{BBBEvent.USER_VOICE_JOINED}& method=&handleNewRoleEvent& /&
&mate:Listener type=&{BBBEvent.USER_VOICE_LEFT}& method=&handleNewRoleEvent& /&
&mate:Listener type=&{CloseAllWindowsEvent.CLOSE_ALL_WINDOWS}& method=&closeWindow& /&
&mate:Listener type=&{ShortcutEvent.REMOTE_FOCUS_WEBCAM}& method=&remoteFocus& /&
+ &mx:Script&
import flexlib.mdi.events.MDIWindowE
import mx.core.UIC
import mx.events.ResizeE
import com.asfusion.mate.events.D
import mon.I
import mon.LogU
import mon.R
import mon.events.CloseWindowE
import mon.events.LocaleChangeE
import org.bigbluebutton.core.EventC
import org.bigbluebutton.core.UsersU
import org.bigbluebutton.core.events.CoreE
import org.bigbluebutton.core.managers.UserM
import org.bigbluebutton.main.events.BBBE
import org.bigbluebutton.main.events.MadePresenterE
import org.bigbluebutton.main.events.ShortcutE
import org.bigbluebutton.main.events.SwitchedPresenterE
import org.bigbluebutton.main.views.MainC
import org.bigbluebutton.modules.videoconf.business.TalkingButtonO
import org.bigbluebutton.modules.videoconf.events.CloseAllWindowsE
import org.bigbluebutton.modules.videoconf.events.OpenVideoWindowE
import org.bigbluebutton.modules.videoconf.events.StartBroadcastE
import org.bigbluebutton.modules.videoconf.events.StopBroadcastE
import org.bigbluebutton.modules.videoconf.model.VideoConfO
import org.bigbluebutton.util.i18n.ResourceU
import org.bigbluebutton.modules.videoconf.events.ClosePublishWindowE
[Bindable] private var defaultWidth:Number = 320;
[Bindable] private var defaultHeight:Number = 240;
public var camIndex:int = 0;
private var camWidth:Number = 320;
private var camHeight:Number = 240;
private var _camera:Camera =
public var quality:Number = 0;
// Timer to auto-publish webcam. We need this timer to delay
// the auto-publishing until after the Viewers's window has loaded
// to receive the publishing events. Otherwise, the user joining next
// won't be able to view the webcam.
private var autoPublishTimer:Timer =
// Timer used to enable the start publishing button, only after get
// any activity on the camera. It avoids the problem of publishing
// a blank video
private var _activationTimer:Timer =
private var _waitingForActivation:Boolean =
static private var _cameraAccessDenied:Boolean =
[Bindable] public var videoOptions:VideoConfO
[Bindable] public var baseIndex:
[Bindable] public var glowColor:String = &&;
[Bindable] public var glowBlurSize:Number = 0;
private function init():void{
videoOptions = new VideoConfOptions();
baseIndex = videoOptions.baseTabI
private var windowType:String = &PublishWindowType&;
override public function getWindowType():String {
return windowT
private function onCreationComplete():void{
this.glowColor = videoOptions.glowC
this.glowBlurSize = videoOptions.glowBlurS
_videoHolder = new UIComponent();
_videoHolder.width = camW
_videoHolder.height = camH
this.addChild(_videoHolder);
this.minWidth = _minW
this.minHeight = _minH
maximizeRestoreBtn.visible =
this.resizable =
this.visible = videoOptions.publishWindowV
this.showCloseButton = videoOptions.showCloseB
if (videoOptions.autoStart) {
* Need to have a timer to trigger auto-publishing of webcam.
autoPublishTimer = new Timer(3000, 1);
autoPublishTimer.addEventListener(TimerEvent.TIMER, autopublishTimerHandler);
autoPublishTimer.start();
titleBarOverlay.tabIndex = baseI
titleBarOverlay.accessibilityName = ResourceUtil.getInstance().getString('bbb.video.publish.titleBar');
closeBtn.focusEnabled =
closeBtn.tabIndex = baseIndex+3;
addEventListener(MDIWindowEvent.RESIZE_START, onResizeStart);
addEventListener(MDIWindowEvent.RESIZE_END, onResizeEnd);
addEventListener(MouseEvent.MOUSE_OVER, showButtons);
addEventListener(MouseEvent.MOUSE_OUT, hideButtons);
addEventListener(MouseEvent.DOUBLE_CLICK, onDoubleClick);
// start the camera preview
updateCamera();
private function remoteFocus(e:ShortcutEvent):void{
focusManager.setFocus(closeBtn);
private function autopublishTimerHandler(event:TimerEvent):void {
startPublishing();
autoPublishTimer.stop();
private function handleMadePresenterEvent(event:MadePresenterEvent):void {
trace(&******** PublishWindow: HandleMadePresenter event *********&);
updateControlButtons();
private function handleSwitchedPresenterEvent(event:SwitchedPresenterEvent):void {
trace(&******** PublishWindow: handleSwitchedPresenterEvent event *********&);
updateControlButtons();
private function handleNewRoleEvent(event:Event):void {
updateControlButtons();
private function handleUserVoiceMutedEvent(event:BBBEvent):void {
if (event.payload.userID ==
userMuted(event.payload.muted);
private function handleUserTalkingEvent(event:CoreEvent):void {
if (event.message.userID ==
if (event.message.talking) {
notTalkingEffect.end();
talkingEffect.play([this]);
simulateClick();
talkingEffect.end();
notTalkingEffect.play([this]);
private function updateCamera():void {
stopCamera();
if (Camera.names.length == 0) {
showWarning('bbb.video.publish.hint.noCamera');
_camera = Camera.getCamera();
if (_camera == null) {
showWarning('bbb.video.publish.hint.cantOpenCamera');
_camera.setMotionLevel(5, 1000);
if (_camera.muted) {
if (_cameraAccessDenied) {
onCameraAccessDisallowed();
showWarning('bbb.video.publish.hint.waitingApproval');
// if the camera isn't muted, that is because the user has
// previously allowed the camera capture on the flash privacy box
onCameraAccessAllowed();
_camera.addEventListener(ActivityEvent.ACTIVITY, onActivityEvent);
_camera.addEventListener(StatusEvent.STATUS, onStatusEvent);
_camera.setKeyFrameInterval(videoOptions.camKeyFrameInterval);
_camera.setMode(camWidth, camHeight, videoOptions.camModeFps);
_camera.setQuality(videoOptions.camQualityBandwidth, videoOptions.camQualityPicture);
if (_camera.width != camWidth || _camera.height != camHeight) {
trace(&Resolution & + camWidth + &x& + camHeight + & is not supported, using & + _camera.width + &x& + _camera.height + & instead&);
setResolution(_camera.width, _camera.height);
_video = new Video();
_video.attachCamera(_camera);
_video.smoothing =
if (aspectRatio & _videoHolder.width / _videoHolder.height) {
_video.width = _videoHolder.
_video.height = _videoHolder.width / aspectR
_video.x = 0;
_video.y = (_videoHolder.height - _video.height) / 2;
_video.width = _videoHolder.height * aspectR
_video.height = _videoHolder.
_video.x = (_videoHolder.width - _video.width) / 2;
_video.y = 0;
_videoHolder.addChild(_video);
private function onActivityEvent(e:ActivityEvent):void {
if (_waitingForActivation && e.activating) {
trace(&Cam activity event:
waitingForActivation = [& + _waitingForActivation + &] activating = [& + e.activating + &]&);
_activationTimer.stop();
showWarning('bbb.video.publish.hint.videoPreview', false, &0xFFFF00&);
_waitingForActivation =
trace(&Starting auto-publisher timer.&);
autoPublishTimer = new Timer(3000, 1);
autoPublishTimer.addEventListener(TimerEvent.TIMER, autopublishTimerHandler);
autoPublishTimer.start();
private function onStatusEvent(e:StatusEvent):void {
if (e.code == &Camera.Unmuted&) {
onCameraAccessAllowed();
// this is just to overwrite the message of waiting for approval
showWarning('bbb.video.publish.hint.openingCamera');
} else if (e.code == &Camera.Muted&) {
onCameraAccessDisallowed();
private function onCameraAccessAllowed():void {
// set timer to ensure that the camera activates.
If not, it might be in use by another application
_waitingForActivation =
if (_activationTimer != null) {
_activationTimer.stop();
_activationTimer = new Timer(10000, 1);
_activationTimer.addEventListener(TimerEvent.TIMER, activationTimeout);
_activationTimer.start();
private function onCameraAccessDisallowed():void {
showWarning('bbb.video.publish.hint.cameraDenied');
_cameraAccessDenied =
private function activationTimeout(e:TimerEvent):void {
showWarning('bbb.video.publish.hint.cameraIsBeingUsed');
// it will try to reopen the camera after the timeout
updateCamera();
private function startPublishing():void{
if (_camera == null)
if (autoPublishTimer != null) {
autoPublishTimer.stop();
showWarning('bbb.video.publish.hint.publishing', true, &0xFFFF00&);
var e:StartBroadcastEvent = new StartBroadcastEvent();
e.stream = this.streamN
e.camera = _
dispatchEvent(e);
// Store the userid for the publisher. This allows us to control
// the user's status from the video window
userID = UsersUtil.getMyUserID();
createButtons();
addControlButtons();
private var _isClosing:Boolean =
override public function close(event:MouseEvent=null):void{
trace(&PublishWindow:: closing&);
if (!_isClosing) {
_isClosing =
stopPublishing();
trace(&Dispatching ClosePublishWindowEvent event&);
var gDispatcher:Dispatcher = new Dispatcher();
gDispatcher.dispatchEvent(new ClosePublishWindowEvent());
private function stopCamera():void {
trace(&PublishWindow:: stopping camera&);
if (_video != null) {
trace(&PublishWindow:: removing video from display&);
_videoHolder.removeChild(_video);
_video.attachCamera(null);
_video.clear();
private function stopPublishing():void{
trace(&PublishWindow::stopPublishing&);
stopCamera();
var e:StopBroadcastEvent = new StopBroadcastEvent()
e.stream = streamN
dispatchEvent(e);
override protected function onResize():void {
super.onResize();
if (_videoHolder != null) {
fitVideoToWindow();
_video.x = (this.width - PADDING_HORIZONTAL - _video.width) / 2;
_video.y = (this.height - PADDING_VERTICAL - _video.height) / 2;
private function fitVideoToWindow():void {
if (_videoHolder.width - PADDING_HORIZONTAL & _videoHolder.height - PADDING_VERTICAL) {
fitToHeightAndAdjustWidthToMaintainAspectRatio();
fitToWidthAndAdjustHeightToMaintainAspectRatio();
private function videoIsSmallerThanWindow():Boolean {
return (camWidth & _videoHolder.width - PADDING_HORIZONTAL) && (camHeight & _videoHolder.height - PADDING_VERTICAL);
private function fitToWidthAndAdjustHeightToMaintainAspectRatio():void {
var aspect:Number = camHeight / camW
_video.width = _videoHolder.width - PADDING_HORIZONTAL;
// Maintain aspect-ratio
_video.height = _video.width *
private function fitToHeightAndAdjustWidthToMaintainAspectRatio():void {
var aspect:Number = camWidth / camH
_video.height = _videoHolder.height - PADDING_VERTICAL;
// Maintain aspect-ratio
_video.width = _video.height *
public function setResolution(width:int, height:int):void {
camWidth =
camHeight =
setAspectRatio(camWidth, camHeight);
* Add timestamp to create a unique stream name. This way we can record
* stream without overwriting previously recorded streams.
var d:Date = new Date();
var curTime:Number = d.getTime();
var uid:String = UserManager.getInstance().getConference().getMyUserId();
var res:String = camWidth + &x& + camH
this.streamName = res.concat(&-& + uid) + &-& + curT
private function isPresenter():Boolean{
if (UsersUtil.amIModerator() || UsersUtil.amIPresenter())
private function closeWindow(e:CloseAllWindowsEvent):void{
trace(&PublishWindow::closeWindow&);
stopCamera();
private var hideWarningTimer:Timer =
private function showWarning(resourceName:String, autoHide:Boolean=false, color:String=&0xFF0000&):void {
const text:String = ResourceUtil.getInstance().getString(resourceName);
if (hideWarningTimer != null)
hideWarningTimer.stop();
if (autoHide) {
hideWarningTimer = new Timer(3000, 1);
hideWarningTimer.addEventListener(TimerEvent.TIMER, hideWarning);
hideWarningTimer.start();
// bring the label to front
setChildIndex(lblWarning, getChildren().length - 1);
lblWarning.text =
lblWarning.setStyle(&color&, color);
lblWarning.visible =
LogUtil.debug(&Showing warning: & + text);
private function hideWarning(e:TimerEvent):void {
lblWarning.visible =
+ &/mx:Script&
&mx:Glow id=&talkingEffect& duration=&500& alphaFrom=&1.0& alphaTo=&0.3&
blurXFrom=&0.0& blurXTo=&{glowBlurSize}& blurYFrom=&0.0& blurYTo=&{glowBlurSize}& color=&{glowColor}&/&
&mx:Glow id=&notTalkingEffect& duration=&500& alphaFrom=&0.3& alphaTo=&1.0&
blurXFrom=&{glowBlurSize}& blurXTo=&0.0& blurYFrom=&{glowBlurSize}& blurYTo=&0.0& color=&{glowColor}&/&
+ &mx:Fade id=&dissolveOut& duration=&1000& alphaFrom=&1.0& alphaTo=&0.0&/&
+ &mx:Fade id=&dissolveIn& duration=&1000& alphaFrom=&0.0& alphaTo=&1.0&/&
+ &mx:Text id=&lblWarning& width=&100%& textAlign=&right& fontSize=&14& fontWeight=&bold& y=&{this.height - lblWarning.height - 30}&
visible=&false& selectable=&false& hideEffect=&{dissolveOut}& showEffect=&{dissolveIn}&/&
+ &mate:Listener type=&{CloseAllWindowsEvent.CLOSE_ALL_WINDOWS}& method=&closeWindow& /&
+&/pubVid:VideoWindowItf&
Index: views/ToolbarButton.mxml
===================================================================
--- views/ToolbarButton.mxml (revision 0)
+++ views/ToolbarButton.mxml (revision 15)
@@ -0,0 +1,152 @@
+&?xml version=&1.0& encoding=&utf-8&?&
+BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+This prog you can redistribute it and/or modify it under the
+terms of the GNU Lesser General Public License as published by the Free Software
+F either version 3.0 of the License, or (at your option) any later
+BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+You should have received a copy of the GNU Lesser General Public License along
+with BigBlueB if not, see &http://www.gnu.org/licenses/&.
+&mx:Button xmlns:mx=&/2006/mxml& icon=&{camIcon}&
xmlns:mate=&/&
click=&openPublishWindow()& creationComplete=&init()&
mouseOver = &mouseOverHandler(event)&
mouseOut = &mouseOutHandler(event)&
height=&24&
toolTip=&{this.selected ? ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.stop') : ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.start')}&
visible=&false&
implements=&mon.IBbbToolbarComponent&&
+ &mate:Listener type=&{ShortcutEvent.SHARE_WEBCAM}& method=&remoteClick& /&
+ &mate:Listener type=&{BBBEvent.CAM_SETTINGS_CLOSED}& method=&handleCamSettingsClosedEvent&/&
+ &mate:Listener type=&{ShareCameraRequestEvent.SHARE_CAMERA_REQUEST}& receive=&enabled=false& /&
+ &mx:Script&
import com.asfusion.mate.events.D
import mon.I
import org.bigbluebutton.main.events.BBBE
import org.bigbluebutton.main.events.ShortcutE
import org.bigbluebutton.main.views.MainT
import org.bigbluebutton.modules.videoconf.events.ClosePublishWindowE
import org.bigbluebutton.modules.videoconf.events.ShareCameraRequestE
import org.bigbluebutton.util.i18n.ResourceU
private var images:Images = new Images();
[Bindable] public var camIcon:Class = images.
public const OFF_STATE:Number = 0;
public const ON_STATE:Number = 1;
public const STOP_PUBLISHING:Number = 0;
public const START_PUBLISHING:Number = 1;
private var _currentState:Number = OFF_STATE;
private var dispatcher:D
private function init():void{
dispatcher = new Dispatcher();
this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.start');
camIcon = images.
this.enabled =
this.selected =
_currentState = OFF_STATE;
public function set isPresenter(presenter:Boolean):void {
public function remoteClick(e:ShortcutEvent):void{
openPublishWindow();
dispatchEvent(new ShortcutEvent(ShortcutEvent.REMOTE_FOCUS_WEBCAM));
public function publishingStatus(status:Number):void {
if(status == START_PUBLISHING) {
_currentState = ON_STATE;
//this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.stop');
camIcon = images.webcamOn;
this.enabled =
this.selected =
_currentState = OFF_STATE;
//this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.start');
camIcon = images.
this.enabled =
this.selected =
private function openPublishWindow():void{
if(_currentState == ON_STATE) {
trace(&Close window&);
_currentState = OFF_STATE;
//this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.start');
camIcon = images.
this.selected =
dispatchEvent(new ClosePublishWindowEvent());
trace(&Share camera&);
_currentState = ON_STATE;
//this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.video.toolTip.stop');
camIcon = images.webcamOn;
this.selected =
dispatchEvent(new ShareCameraRequestEvent());
private function handleCamSettingsClosedEvent(e:BBBEvent):void {
this.setFocus();
if(e.payload['clicked'] == &cancel&){
this.enabled =
this.selected =
_currentState = OFF_STATE;
camIcon = images.
private function mouseOverHandler(event:MouseEvent):void {
if(_currentState == ON_STATE)
camIcon = images.webcamC
camIcon = images.webcamOn;
private function mouseOutHandler(event:MouseEvent):void {
if(_currentState == ON_STATE)
camIcon = images.webcamOn;
camIcon = images.
public function getAlignment():String{
return MainToolbar.ALIGN_LEFT;
public function theory():String{
return &Webcam button&;
+ &/mx:Script&
+&/mx:Button&
Index: views/VideoWindow.mxml
===================================================================
--- views/VideoWindow.mxml (revision 0)
+++ views/VideoWindow.mxml (revision 15)
@@ -0,0 +1,278 @@
+&?xml version=&1.0& encoding=&utf-8&?&
+BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+This prog you can redistribute it and/or modify it under the
+terms of the GNU Lesser General Public License as published by the Free Software
+F either version 3.0 of the License, or (at your option) any later
+BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+You should have received a copy of the GNU Lesser General Public License along
+with BigBlueB if not, see &http://www.gnu.org/licenses/&.
+&viewVid:VideoWindowItf
+ xmlns:viewVid=&org.bigbluebutton.modules.videoconf.business.*&
+ xmlns:mx=&/2006/mxml&
+ creationComplete=&onCreationComplete()&
+ implements=&mon.IBbbModuleWindow&
+ xmlns:mate=&/&
+ styleNameFocus=&videoViewStyleFocus&
+ styleNameNoFocus=&videoViewStyleNoFocus&
+ horizontalScrollPolicy=&off&
+ verticalScrollPolicy=&off&
+ resize=&onResize()&
+ layout=&absolute&&
+ &mate:Listener type=&{BBBEvent.USER_VOICE_MUTED}& method=&handleUserVoiceMutedEvent& /&
+ &mate:Listener type=&{EventConstants.USER_TALKING}& method=&handleUserTalkingEvent& /&
&mate:Listener type=&{SwitchedPresenterEvent.SWITCHED_PRESENTER}& method=&handleSwitchedPresenterEvent& /&
&mate:Listener type=&{MadePresenterEvent.SWITCH_TO_PRESENTER_MODE}& method=&handleMadePresenterEvent& /&
&mate:Listener type=&{BBBEvent.USER_VOICE_JOINED}& method=&handleNewRoleEvent& /&
&mate:Listener type=&{BBBEvent.USER_VOICE_LEFT}& method=&handleNewRoleEvent& /&
+ &mate:Listener type=&{CloseAllWindowsEvent.CLOSE_ALL_WINDOWS}& method=&closeWindow& /&
+ &mx:Script&
import com.asfusion.mate.events.D
import flexlib.mdi.events.MDIWindowE
import mx.core.UIC
import mon.LogU
import mon.R
import mon.events.CloseWindowE
import org.bigbluebutton.core.EventC
import org.bigbluebutton.core.events.CoreE
import org.bigbluebutton.core.managers.UserM
import org.bigbluebutton.main.events.BBBE
import org.bigbluebutton.main.events.MadePresenterE
import org.bigbluebutton.main.events.StoppedViewingWebcamE
import org.bigbluebutton.main.events.SwitchedPresenterE
import org.bigbluebutton.main.views.MainC
import org.bigbluebutton.modules.videoconf.business.TalkingButtonO
import org.bigbluebutton.modules.videoconf.events.CloseAllWindowsE
import org.bigbluebutton.modules.videoconf.model.VideoConfO
private var ns:NetS
private var globalDispatcher:D
[Bindable]
public var videoOptions:VideoConfOptions = new VideoConfOptions();
private var windowType:String = &VideoWindowType&;
[Bindable] public var glowColor:String = &&;
[Bindable] public var glowBlurSize:Number = 0;
override public function getWindowType():String {
return windowT
private function onCreationComplete():void{
this.glowColor = videoOptions.glowC
this.glowBlurSize = videoOptions.glowBlurS
LogUtil.debug(&checking glow values: &+this.glowColor+& and &+this.glowBlurSize);
_videoHolder = new UIComponent();
_videoHolder.addChild(_video);
this.addChild(_videoHolder);
addEventListener(MDIWindowEvent.RESIZE_START, onResizeStart);
addEventListener(MDIWindowEvent.RESIZE_END, onResizeEnd);
addEventListener(MDIWindowEvent.CLOSE, onCloseEvent);
addEventListener(MouseEvent.MOUSE_OVER, showButtons);
addEventListener(MouseEvent.MOUSE_OUT, hideButtons);
addEventListener(MouseEvent.DOUBLE_CLICK, onDoubleClick);
createButtons();
addControlButtons();
globalDispatcher = new Dispatcher();
this.minWidth = _minW
this.minHeight = _minH
maximizeRestoreBtn.visible =
this.resizable =
At this point, the function startVideo has been called, and
the video has the exactly dimensions of the original stream.
It's needed to call onResize() to fit the video window in the
main canvas in case that the video dimensions are larger than
the parent window.
onResize();
if (videoOptions.viewerWindowMaxed)
this.maximize();
this.showCloseButton = videoOptions.showCloseB
private function handleMadePresenterEvent(event:MadePresenterEvent):void {
trace(&******** VideoWindow: HandleMadePresenter event *********&);
updateControlButtons();
private function handleSwitchedPresenterEvent(event:SwitchedPresenterEvent):void {
trace(&******** VideoWindow: handleSwitchedPresenterEvent event *********&);
updateControlButtons();
private function handleNewRoleEvent(event:Event):void {
updateControlButtons();
private function handleUserVoiceMutedEvent(event:BBBEvent):void {
if (event.payload.userID ==
userMuted(event.payload.muted);
private var _closing:Boolean =
private function onCloseEvent(event:MDIWindowEvent = null):void {
LogUtil.debug(&ViewWindow closing & + streamName);
if (!_closing) {
_closing =
var stopEvent:StoppedViewingWebcamEvent = new StoppedViewingWebcamEvent();
stopEvent.webcamUserID = userID;
globalDispatcher.dispatchEvent(stopEvent);
if (UserManager.getInstance().getConference().hasUser(userID)) {
UserManager.getInstance().getConference().getUser(userID).viewingStream =
private function handleUserTalkingEvent(event:CoreEvent):void {
if (event.message.userID ==
if (event.message.talking) {
notTalkingEffect.end();
talkingEffect.play([this]);
simulateClick();
talkingEffect.end();
notTalkingEffect.play([this]);
public function startVideo(connection:NetConnection, stream:String):void{
ns = new NetStream(connection);
ns.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
ns.client =
ns.bufferTime = 0;
ns.receiveVideo(true);
ns.receiveAudio(false);
var res:Array = getVideoResolution(stream);
if (res == null) // error
_video = new Video(Number(res[0]), Number(res[1]));
_video.width = Number(res[0]);
_video.height = Number(res[1]);
_video.smoothing =
setAspectRatio(Number(res[0]), Number(res[1]));
_video.attachNetStream(ns);
if (videoOptions.smoothVideo) {
trace(&Smoothing video.&)
_video.smoothing =
if (videoOptions.applyConvolutionFilter) {
var filter:ConvolutionFilter = new flash.filters.ConvolutionFilter();
filter.matrixX = 3;
filter.matrixY = 3;
trace(&Applying convolution filter =[& + videoOptions.convolutionFilter + &]&);
filter.matrix = videoOptions.convolutionF
filter.bias =
videoOptions.filterB
filter.divisor = videoOptions.filterD
_video.filters = [filter];
ns.play(stream);
this.streamName =
this.width = _video.width + paddingH
this.height = _video.height + paddingV
if (UserManager.getInstance().getConference().hasUser(userID)) {
UserManager.getInstance().getConference().getUser(userID).viewingStream =
private function onAsyncError(e:AsyncErrorEvent):void{
LogUtil.debug(&VideoWindow::asyncerror & + e.toString());
public function onMetaData(info:Object):void{
trace(&metadata: width=& + info.width + & height=& + info.height);
_video.width = info.
_video.height = info.
setAspectRatio(info.width, info.height);
onResize();
private function onNetStatus(e:NetStatusEvent):void{
case &NetStream.Publish.Start&:
LogUtil.debug(&NetStream.Publish.Start for broadcast stream & + streamName);
case &NetStream.Play.UnpublishNotify&:
ns.close();
this.close();
// shouldn't call onCloseEvent() here because of the viewer cam icon
super.close();
case &NetStream.Play.Start&:
LogUtil.debug(&Netstatus: & + e.info.code);
globalDispatcher.dispatchEvent(new BBBEvent(BBBEvent.VIDEO_STARTED));
case &NetStream.Play.FileStructureInvalid&:
LogUtil.debug(&The MP4's file structure is invalid.&);
case &NetStream.Play.NoSupportedTrackFound&:
LogUtil.debug(&The MP4 doesn't contain any supported tracks&);
override public function close(event:MouseEvent=null):void{
ns.close();
onCloseEvent();
super.close(event);
private function closeWindow(e:CloseAllWindowsEvent):void{
this.close();
+ &/mx:Script&
+ &mx:Glow id=&talkingEffect& duration=&500& alphaFrom=&1.0& alphaTo=&0.3&
blurXFrom=&0.0& blurXTo=&{glowBlurSize}& blurYFrom=&0.0& blurYTo=&{glowBlurSize}& color=&{glowColor}&/&
+ &mx:Glow id=&notTalkingEffect& duration=&500& alphaFrom=&0.3& alphaTo=&1.0&
blurXFrom=&{glowBlurSize}& blurXTo=&0.0& blurYFrom=&{glowBlurSize}& blurYTo=&0.0& color=&{glowColor}&/&
+&/viewVid:VideoWindowItf&
Index: maps/VideoEventMap.mxml
===================================================================
--- maps/VideoEventMap.mxml (revision 0)
+++ maps/VideoEventMap.mxml (revision 15)
@@ -0,0 +1,120 @@
+&?xml version=&1.0& encoding=&utf-8&?&
+BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+This prog you can redistribute it and/or modify it under the
+terms of the GNU Lesser General Public License as published by the Free Software
+F either version 3.0 of the License, or (at your option) any later
+BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+You should have received a copy of the GNU Lesser General Public License along
+with BigBlueB if not, see &http://www.gnu.org/licenses/&.
+&EventMap xmlns:mx=&/2006/mxml& xmlns=&/&&
+ &mx:Script&
import org.bigbluebutton.core.events.ConnectAppE
import org.bigbluebutton.main.events.BBBE
import org.bigbluebutton.main.events.MadePresenterE
import org.bigbluebutton.main.events.StoppedViewingWebcamE
import org.bigbluebutton.main.events.UserJoinedE
import org.bigbluebutton.main.events.UserLeftE
import org.bigbluebutton.main.model.users.events.StreamStartedE
import org.bigbluebutton.modules.videoconf.events.ClosePublishWindowE
import org.bigbluebutton.modules.videoconf.events.ConnectedE
import org.bigbluebutton.modules.videoconf.events.ShareCameraRequestE
import org.bigbluebutton.modules.videoconf.events.StartBroadcastE
import org.bigbluebutton.modules.videoconf.events.StopBroadcastE
import org.bigbluebutton.modules.videoconf.events.VideoModuleStartE
import org.bigbluebutton.modules.videoconf.events.VideoModuleStopE
import org.bigbluebutton.modules.users.events.ViewCameraE
+ &/mx:Script&
&EventHandlers type=&{VideoModuleStartEvent.START}&&
&ObjectBuilder generator=&{VideoEventMapDelegate}& cache=&global& constructorArguments=&{scope.dispatcher}&/&
&MethodInvoker generator=&{VideoEventMapDelegate}& method=&start& arguments=&{event.uri}&/&
&/EventHandlers&
&EventHandlers type=&{VideoModuleStopEvent.STOP}&&
&MethodInvoker generator=&{VideoEventMapDelegate}& method=&stopModule&/&
&/EventHandlers&
&EventHandlers type=&{BBBEvent.CAMERA_SETTING}& &
&MethodInvoker generator=&{VideoEventMapDelegate}& method=&handleCameraSetting& arguments=&{event}&/&
&/EventHandlers&
&EventHandlers type=&{ConnectAppEvent.CONNECT_VIDEO_APP}&&
&MethodInvoker generator=&{VideoEventMapDelegate}& method=&connectToVideoApp& /&
&/EventHandlers&
+ &EventHandlers type=&{ShareCameraRequestEvent.SHARE_CAMERA_REQUEST}&&
&MethodInvoker generator=&{VideoEventMapDelegate}& method=&handleShareCameraRequestEvent& arguments=&{event}&/&
+ &/EventHandlers&
+ &EventHandlers type=&{StartBroadcastEvent.START_BROAD}

我要回帖

更多关于 恩杰cam软件 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信