- screenshare client

This commit is contained in:
Richard Alam 2016-02-10 19:43:38 +00:00
parent f71cfe343c
commit dd37445b7d
57 changed files with 3777 additions and 8 deletions

View File

@ -15,6 +15,7 @@
</compiler>
<applications>
<application path="BigBlueButton.mxml"/>
<application path="ScreenshareStandalone.mxml"/>
</applications>
<modules/>
<workers/>

View File

@ -512,7 +512,7 @@ TitleWindow {
}
.chromeJavaHelpImage {
imageSource: Embed(source='assets/images/chromePluginBlocked.png');
imageSource: Embed(source='assets/images/jnlp-run-chrome.png');
}
.webcamSettingsWindowTitleStyle, .micSettingsWindowTitleStyle {

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -25,6 +25,8 @@
<property name="PRESENT" value="PresentModule" />
<property name="DESKSHARE" value="DeskShareModule" />
<property name="DESKSHARE_SA" value="DeskshareStandalone" />
<property name="SCREENSHARE" value="ScreenshareModule" />
<property name="SCREENSHARE_SA" value="ScreenshareStandalone" />
<property name="CAM_PREVIEW_SA" value="WebcamPreviewStandalone" />
<property name="MICROPHONE_CHECK" value="MicrophoneCheck" />
<property name="CAMERA_CHECK" value="CameraCheck" />
@ -217,7 +219,17 @@
<echo message="Compiling deskshare without optimization." />
<build-module-no-link src="${SRC_DIR}" target="${DESKSHARE}" />
</target>
<target name="build-screenshare-standalone" depends="build-screenshare-no-linker" description="Compile Screenshare Standalone Application">
<echo message="Compiling screenshare standalone without optimization." />
<build-module-no-link src="${SRC_DIR}" target="${SCREENSHARE_SA}" />
</target>
<target name="build-screenshare-no-linker" description="Compile Screenshare Module without the linker">
<echo message="Compiling screenshare without optimization." />
<build-module-no-link src="${SRC_DIR}" target="${SCREENSHARE}" />
</target>
<target name="build-webcam-preview-standalone" description="Compile Webcam Preview Standalone Application">
<echo message="Compiling webcam preview standalone without optimization." />
<build-module-no-link src="${SRC_DIR}" target="${CAM_PREVIEW_SA}" />
@ -250,6 +262,11 @@
<copy file="${PROD_RESOURCES_DIR}/bbb-deskshare-applet-0.9.0.jar" todir="${OUTPUT_DIR}"/>
</target>
<target name="build-screenshare" description="Compile Screenshare Module">
<build-module src="${SRC_DIR}" target="${SCREENSHARE}" />
<echo message="Copying deskshare applet for Screenshare Module" />
</target>
<target name="build-phone" description="Compile Phone Module">
<build-module src="${SRC_DIR}" target="${PHONE}" />
@ -283,7 +300,7 @@
<!-- just a grouping of modules to compile -->
<target name="build-deskshare-phone-video-whiteboard-dyn"
depends="build-deskshare, build-phone, build-video, build-whiteboard, build-notes, build-polling"
depends="build-deskshare, build-screenshare, build-phone, build-video, build-whiteboard, build-notes, build-polling"
description="Compile deskshare, phone, video, whiteboard modules">
</target>
@ -384,7 +401,12 @@
description="Compiling standalone desktop sharing">
<echo message="Deskshare standalone built without optimization." />
</target>
<target name="compile-screenshare-standalone" depends="build-screenshare-standalone"
description="Compiling standalone screen sharing">
<echo message="Screenshare standalone built without optimization." />
</target>
<target name="compile-bbb" depends="build-main-chat-present, build-deskshare-phone-video-whiteboard-dyn, copy-resource-files"
description="Compiling the BBB without copying config.xml">
</target>
@ -505,14 +527,17 @@
<!-- NOTE: compile-deskshare-standalone MUST come first before compile-bbb as we need the deskshare-standalone
to be compiled withouth being optimized by using the linker -->
<target name="clean-build-bbb" depends="clean, init-ant-contrib, generate-html-wrapper, compile-deskshare-standalone,
<target name="clean-build-bbb" depends="clean, init-ant-contrib, generate-html-wrapper, compile-deskshare-standalone,
compile-screenshare-standalone,
build-webcam-preview-standalone, build-webcam-view-standalone, compile-bbb"
description="Build BBB client skipping compiling of locales"/>
<target name="clean-build-all" depends="clean, init-ant-contrib, generate-html-wrapper, compile-deskshare-standalone, build-mic-check,
<target name="clean-build-all" depends="clean, init-ant-contrib, generate-html-wrapper, compile-deskshare-standalone,
compile-screenshare-standalone, build-mic-check,
build-cam-check, build-conn-check, build-webcam-preview-standalone, build-webcam-view-standalone,
compile-bbb, branding, branding-black"
description="Build BBB client including locales"/>
<target name="modules" depends="init-ant-contrib, generate-html-wrapper, compile-deskshare-standalone,
<target name="modules" depends="init-ant-contrib, generate-html-wrapper, compile-deskshare-standalone,
compile-screenshare-standalone,
build-webcam-preview-standalone, build-webcam-view-standalone, compile-bbb"
description="Build BBB client without locales"/>
<target name="cleanandmake" depends="clean-build-all" description="Build BBB client including locales"/>

View File

@ -280,6 +280,28 @@ bbb.video.publish.closeBtn.accessName = Close the webcam settings dialog box
bbb.video.publish.closeBtn.label = Cancel
bbb.video.publish.titleBar = Publish Webcam Window
bbb.video.streamClose.toolTip = Close stream for: {0}
bbb.screensharePublish.title = Desktop Sharing: Presenter's Preview
bbb.screensharePublish.fullscreen.tooltip = Share Your Main Screen
bbb.screensharePublish.fullscreen.label = Full Screen
bbb.screensharePublish.region.tooltip = Share a Part of Your Screen
bbb.screensharePublish.region.label = Region
bbb.screensharePublish.stop.tooltip = Close screen share
bbb.screensharePublish.stop.label = Close
bbb.screensharePublish.maximizeRestoreBtn.toolTip = You cannot maximize this window.
bbb.screensharePublish.closeBtn.toolTip = Stop Sharing and Close
bbb.screensharePublish.chromeOnMacUnsupportedHint = Desktop sharing is not currently supported on Chrome running under Mac OS X. Recommend you use FireFox to share desktop.
bbb.screensharePublish.minimizeBtn.toolTip = Minimize
bbb.screensharePublish.minimizeBtn.accessibilityName = Minimize the Desktop Sharing Publish Window
bbb.screensharePublish.maximizeRestoreBtn.accessibilityName = Maximize the Desktop Sharing Publish Window
bbb.screensharePublish.chromeHint.title = Chrome needs your permission to run the application.
bbb.screensharePublish.chromeHint.message = Click Keep button to save the file then click the file to run the application.
bbb.screensharePublish.chromeHint.button = Retry
bbb.screenshareView.title = Desktop Sharing
bbb.screenshareView.fitToWindow = Fit to Window
bbb.screenshareView.actualSize = Display actual size
bbb.screenshareView.minimizeBtn.accessibilityName = Minimize the Desktop Sharing View Window
bbb.screenshareView.maximizeRestoreBtn.accessibilityName = Maximize the Desktop Sharing View Window
bbb.screenshareView.closeBtn.accessibilityName = Close the Desktop Sharing View Window
bbb.desktopPublish.title = Desktop Sharing: Presenter's Preview
bbb.desktopPublish.fullscreen.tooltip = Share Your Main Screen
bbb.desktopPublish.fullscreen.label = Full Screen

View File

@ -53,6 +53,15 @@
baseTabIndex="201"
/>
<module name="ScreenshareModule"
url="http://HOST/client/ScreenshareModule.swf?v=VERSION"
uri="rtmp://HOST/screenshare"
showButton="true"
autoStart="false"
autoFullScreen="false"
baseTabIndex="201"
/>
<module name="PhoneModule" url="http://HOST/client/PhoneModule.swf?v=VERSION"
uri="rtmp://HOST/sip"
autoJoin="true"

View File

@ -91,6 +91,7 @@
<script src="lib/bigbluebutton.js?v=VERSION" language="javascript"></script>
<script src="lib/bbb_localization.js?v=VERSION" language="javascript"></script>
<script src="lib/bbb_blinker.js?v=VERSION" language="javascript"></script>
<script src="lib/bbb_screenshare.js" language="javascript"></script>
<script src="lib/bbb_deskshare.js?v=VERSION" language="javascript"></script>
<script src="lib/bbb_api_bridge.js?v=VERSION" language="javascript"></script>
<script src="lib/sip.js?v=VERSION" language="javascript"></script>

View File

@ -0,0 +1,42 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css" media="screen">
html, body, #content { height:100%; }
body { margin:0; padding:0; overflow:hidden; }
#altContent { /* style alt content */ }
</style>
<script type="text/javascript" src="swfobject/swfobject.js"></script>
<script type="text/javascript">
swfobject.registerObject("BigBlueButton", "10.3.0", "expressInstall.swf");
</script>
<script src="lib/jquery-1.5.1.min.js" language="javascript"></script>
<script src="lib/bigbluebutton.js" language="javascript"></script>
<script src="lib/bbb_localization.js" language="javascript"></script>
<script src="lib/bbb_blinker.js" language="javascript"></script>
<script src="lib/bbb_deskshare.js" language="javascript"></script>
</head>
<body>
<div id="content">
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%" id="BigBlueButton" name="BigBlueButton" align="middle">
<param name="movie" value="ScreenshareStandalone.swf?v=VERSION" />
<param name="quality" value="high" />
<param name="allowfullscreen" value="true" />
<param name="bgcolor" value="#869ca7" />
<!--[if !IE]>-->
<object type="application/x-shockwave-flash" data="DeskshareStandalone.swf?v=VERSION" width="100%" height="100%" align="middle">
<param name="quality" value="high" />
<param name="bgcolor" value="#869ca7" />
<!--<![endif]-->
<a href="http://www.adobe.com/go/getflashplayer">
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
</a>
<!--[if !IE]>-->
</object>
<!--<![endif]-->
</object>
</div>
</body>
</html>

View File

@ -0,0 +1,27 @@
function startScreensharing(jnlp, meetingId, authToken, fullScreen)
{
console.log("Starting JSW [" + authToken + "]");
var launchuri = jnlp + "?authToken=" + authToken + "&fullScreen=" + fullScreen + "&meetingId=" + meetingId;
$('<iframe id="iframe"><iframe/>').attr('src', launchuri).hide().appendTo('body');
}
function removeFrame () {
var div = document.getElementById("deskshare");
div.parentNode.removeChild(div);
}
function setScreenCoordinates(x, y) {
document.DeskShareApplet.setScreenCoordinates(x,y);
}
function stopApplet(){
document.DeskShareApplet.destroy();
removeFrame();
}
function checkForJava(){
// if (navigator.javaEnabled() || window.navigator.javaEnabled())
return 1;
}

View File

@ -0,0 +1,117 @@
<?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 program is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-->
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:maps="org.bigbluebutton.modules.deskShare.maps.*"
implements="org.bigbluebutton.common.IBigBlueButtonModule"
creationComplete="onCreationComplete()" xmlns:maps1="org.bigbluebutton.modules.screenshare.maps.*">
<maps1:ScreenshareEventMap id="deskshareGlobalEventMap" />
<mx:Script>
<![CDATA[
import com.asfusion.mate.events.Dispatcher;
import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger;
import org.bigbluebutton.modules.screenshare.events.ModuleEvent;
import org.bigbluebutton.modules.screenshare.maps.ScreenshareEventMap;
private static const LOGGER:ILogger = getClassLogger(ScreenshareModule);
private var _moduleName:String = "Desk Share";
private var _attributes:Object;
private var globalDispatcher:Dispatcher = new Dispatcher();;
private function onCreationComplete():void{
LOGGER.debug("DeskShareModule initialized");
}
public function get moduleName():String{
return _moduleName;
}
public function get uri():String{
return _attributes.uri;
}
public function get username():String{
return _attributes.username;
}
public function get mode():String{
if (_attributes.mode == null){
_attributes.mode = "LIVE";
LOGGER.debug("Setting DeskShare mode: " + _attributes.mode);
}
LOGGER.debug("DeskShare mode: " + _attributes.mode);
return _attributes.mode;
}
public function get userid():Number{
return _attributes.userid as Number;
}
public function get role():String{
return _attributes.userrole as String;
}
public function start(attributes:Object):void{
LOGGER.debug("desk share attr: " + attributes.username);
_attributes = attributes;
var startEvent:ModuleEvent = new ModuleEvent(ModuleEvent.START);
startEvent.module = this;
globalDispatcher.dispatchEvent(startEvent);
}
public function stop():void{
LOGGER.debug("STOPPING DESKSHARE MODULE!!!");
var stopEvent:ModuleEvent = new ModuleEvent(ModuleEvent.STOP);
globalDispatcher.dispatchEvent(stopEvent);
}
public function getRoom():String{
return _attributes.room;
}
public function getRed5ServerUri():String{
return _attributes.uri;
}
public function getCaptureServerUri():String{
var uri:String = _attributes.uri;
uri = uri.split("/")[2];
return uri;
}
public function tunnel():Boolean {
if (_attributes.protocol == "RTMPT") {
LOGGER.debug("Use tunneling for desktop sharing");
return true;
}
return false;
}
]]>
</mx:Script>
</mx:Module>

View File

@ -0,0 +1,355 @@
<?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 program is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:mate="http://mate.asfusion.com/"
creationComplete="onCreationComplete()" resize="onResize()"
backgroundColor="white"
width="100%" height="100%"
layout="absolute">
<mate:Listener type="{AppletStartedEvent.APPLET_STARTED}" method="onAppletStart" />
<mate:Listener type="{ViewStreamEvent.STOP}" method="onAppletStop" />
<mate:Listener type="{ViewStreamEvent.START}" method="onViewStreamStart"/>
<mate:Listener type="{CursorEvent.UPDATE_CURSOR_LOC_EVENT}" method="onUpdateCursorEvent" />
<mate:Listener type="{ConnectionEvent.SUCCESS}" method="onDeskshareConnectionEvent" />
<mx:Script>
<![CDATA[
import mx.controls.Image;
import mx.core.UIComponent;
import org.bigbluebutton.common.Images;
import org.bigbluebutton.modules.screenshare.events.AppletStartedEvent;
import org.bigbluebutton.modules.screenshare.events.CursorEvent;
import org.bigbluebutton.modules.screenshare.events.ViewStreamEvent;
import org.bigbluebutton.modules.screenshare.services.ScreenshareService;
import org.bigbluebutton.modules.screenshare.services.red5.ConnectionEvent;
import org.bigbluebutton.util.QueryStringParameters;
private var videoHolder:UIComponent;
private var cursor:Shape = new Shape();;
private var images:Images = new Images();
[Bindable] public var bbbLogo:Class = images.bbb_logo;
private var video:Video;
private var ns:NetStream;
private var stream:String;
private var logoutURL:String;
private var host:String;
private var room:String;
private var displayWidth:Number;
private var displayHeight:Number;
private var service:ScreenshareService = new ScreenshareService();
private var videoWidth:int;
private var videoHeight:int;
private function onCreationComplete():void {
var p:QueryStringParameters = new QueryStringParameters();
p.collectParameters();
logoutURL = p.getParameter("LOGOUTURL");
host = p.getParameter("HOST");
room = p.getParameter("ROOM");
service.connect(host, room);
cursor.graphics.lineStyle(6, 0xFF0000, 0.6);
cursor.graphics.drawCircle(0,0,3);
cursor.visible = false;
displayWidth = this.parent.width;
displayHeight = this.parent.height;
}
private function onAppletStart(event:AppletStartedEvent):void{
trace("DeskshareSA::onAppletStart.");
startVideo(service.getConnection(), room, event.videoWidth, event.videoHeight);
}
private function onViewStreamStart(event:ViewStreamEvent):void {
trace("DeskshareSA::onViewStreamStart.");
// startVideo(service.getConnection(), room, event.videoWidth, event.videoHeight);
}
private function onAppletStop(event:ViewStreamEvent):void {
trace("DeskshareSA::onAppletStop.");
var url:URLRequest = new URLRequest(logoutURL);
navigateToURL(url, '_self');
}
private function onDeskshareConnectionEvent(event:ConnectionEvent):void {
var warningText:String;
switch(event.type) {
case ConnectionEvent.SUCCESS:
warningText = "Connecting to server successful.";
break;
case ConnectionEvent.FAILED:
warningText = "Connecting to server failed.";
break;
case ConnectionEvent.CLOSED:
warningText = "Connection to server closed.";
break;
case ConnectionEvent.REJECTED:
warningText = "Connection to server rejected.";
break;
case ConnectionEvent.INVALIDAPP:
warningText = "Connecting to server failed. Invalid application.";
break;
case ConnectionEvent.APPSHUTDOWN:
warningText = "Connection to server failed. Server shutting down.";
break;
case ConnectionEvent.SECURITYERROR:
warningText = "Connecting to server failed. Security error.";
break;
case ConnectionEvent.DISCONNECTED:
warningText = "Connection to server disconnected.";
break;
case ConnectionEvent.CONNECTING:
warningText = "Connecting to server...";
break;
case ConnectionEvent.CONNECTING_RETRY:
warningText = "Connecting to server failed. Retry [" + event.retryAttempts + "]";
break;
case ConnectionEvent.CONNECTING_MAX_RETRY:
warningText = "Connecting to server failed. Max retry reached. Giving up.";
break;
case ConnectionEvent.CHECK_FOR_DESKSHARE_STREAM:
warningText = "Loading...";
break;
case ConnectionEvent.FAIL_CHECK_FOR_DESKSHARE_STREAM:
warningText = "Loading shared desktop failed.";
break;
case ConnectionEvent.NO_DESKSHARE_STREAM:
warningText = "Desktop is not shared.";
break;
}
showStatusText(warningText, true, "0x000000");
trace("CONNECT STATUS EVENT [" + event.type + "]");
}
private function startVideo(connection:NetConnection, stream:String, videoWidth:Number, videoHeight:Number):void{
ns = new NetStream(connection);
ns.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
ns.client = this;
ns.bufferTime = 0;
ns.receiveVideo(true);
ns.receiveAudio(false);
video = new Video(videoWidth, videoHeight);
video.attachNetStream(ns);
this.videoWidth = videoWidth;
this.videoHeight = videoHeight;
videoHolder = new UIComponent();
trace("DeskshareSA::Determine how to display video = [" + videoWidth + "x" + videoHeight + "] display=[" + this.width + "x" + this.height + "]");
determineHowToDisplayVideo();
ns.play(stream);
this.stream = stream;
}
private function onMetaData(info:Object):void {
trace("DeskshareSA:: ****metadata: width=" + info.width + " height=" + info.height);
videoWidth = info.width;
videoHeight = info.height;
// determineHowToDisplayVideo();
}
private function onResize():void {
if (video != null) {
determineHowToDisplayVideo();
}
}
private function onUpdateCursorEvent(event:CursorEvent):void {
if (cursor == null) return;
cursor.x = videoHolder.x + (event.x * (videoHolder.width / videoWidth));
cursor.y = videoHolder.y + (event.y * (videoHolder.height / videoHeight));
cursorImg.visible = true;
// DO NOT compute the x and y coordinate and assign directly to the cursorImg
// as it results in a flickering and jerky mouse pointer (ralam jun 10, 2010).
cursorImg.x = cursor.x;
cursorImg.y = cursor.y;
}
public function stopViewing():void {
ns.close();
}
private function onAsyncError(e:AsyncErrorEvent):void{
trace("DeskshareSA::::asyncerror " + e.toString());
}
private function onNetStatus(e:NetStatusEvent):void{
switch(e.info.code){
case "NetStream.Play.Start":
trace("DeskshareSA::NetStream.Publish.Start for broadcast stream " + stream);
trace("DeskshareSA::Dispatching start viewing event");
service.sendStartedViewingNotification(stream);
break;
case "NetStream.Play.UnpublishNotify":
trace("DeskshareSA::NetStream.Play.UnpublishNotify for broadcast stream " + stream);
stopViewing();
break;
case "NetStream.DRM.UpdateNeeded":
case "NetStream.Play.Failed":
case "NetStream.Play.FileStructureInvalid":
case "NetStream.Play.NoSupportedTrackFound":
case "NetStream.Play.StreamNotFound":
// case "NetStream.Play.Reset":
showStatusText(e.info.code, true, "0x000000");
break;
}
trace("NET STATUS EVENT [" + e.info.code + "]");
}
//----------------------------
private function centerToWindow():void{
videoHolder.width = video.width = videoWidth;
videoHolder.height = video.height = videoHeight;
videoHolder.x = video.x = (this.width - video.width) / 4;
videoHolder.y = video.y = (this.height - video.height) / 4;
trace("DeskshareSA::Center video = [" + video.width + "x" + video.height
+ "] display=[" + this.width + "x" + this.height + "]"
+ "loc=[" + videoHolder.x + "," + videoHolder.y + "]");
videoHolder.addChild(video);
videoHolder.addChild(cursor);
videoHolder.addChild(cursorImg);
showVideoHolder();
}
private function fitVideoToWindow():void {
if (width < height) {
fitToWidthAndAdjustHeightToMaintainAspectRatio();
} else {
fitToHeightAndAdjustWidthToMaintainAspectRatio();
}
}
private function videoIsSmallerThanWindow():Boolean {
return (videoHeight < height) && (videoWidth < width);
}
private function fitToWidthAndAdjustHeightToMaintainAspectRatio():void {
trace("DeskshareSA::fitToWidthAndAdjustHeightToMaintainAspectRatio");
videoHolder.width = video.width = width;
// Maintain aspect-ratio
videoHolder.height = video.height = (videoHeight * video.width) / videoWidth;
videoHolder.x = video.x = 0;
videoHolder.y = video.y = 0;
trace("DeskshareSA::Disp video = [" + video.width + "x" + video.height
+ "] display=[" + this.width + "x" + this.height + "]"
+ "loc=[" + videoHolder.x + "," + videoHolder.y + "]");
videoHolder.addChild(video);
videoHolder.addChild(cursor);
videoHolder.addChild(cursorImg);
showVideoHolder();
}
private function fitToHeightAndAdjustWidthToMaintainAspectRatio():void {
trace("DeskshareSA::fitToHeightAndAdjustWidthToMaintainAspectRatio");
videoHolder.height = video.height = height;
// Maintain aspect-ratio
videoHolder.width = video.width = (videoWidth * video.height) / videoHeight;
if (videoHolder.width > width) {
videoHolder.width = video.width = width;
videoHolder.height = video.height = (videoHeight * video.width) / videoWidth;
}
videoHolder.x = video.x = (width - video.width) / 4;
videoHolder.y = video.y = (height - video.height) / 4;
trace("DeskshareSA::Disp video = [" + video.width + "x" + video.height
+ "] display=[" + this.width + "x" + this.height + "]"
+ "loc=[" + videoHolder.x + "," + videoHolder.y + "]");
videoHolder.addChild(video);
videoHolder.addChild(cursor);
videoHolder.addChild(cursorImg);
showVideoHolder();
}
private function showVideoHolder():void {
addChild(videoHolder);
}
private function determineHowToDisplayVideo():void {
// if (videoIsSmallerThanWindow()) {
// trace("Video is smaller than window. Centering.");
centerToWindow();
// } else {
// trace("Video is greater than window. Scaling.");
// fitVideoToWindow();
// }
}
private var hideStatusTextTimer:Timer = null;
private function showStatusText(statusText:String, autoHide:Boolean=false, color:String="0xFF0000"):void {
if (hideStatusTextTimer != null)
hideStatusTextTimer.stop();
if (autoHide) {
hideStatusTextTimer = new Timer(3000, 1);
hideStatusTextTimer.addEventListener(TimerEvent.TIMER, hideStatusText);
hideStatusTextTimer.start();
}
// bring the label to front
setChildIndex(statusTextDisplay, getChildren().length - 1);
statusTextDisplay.text = statusText;
statusTextDisplay.setStyle("color", color);
statusTextDisplay.visible = true;
}
private function hideStatusText(e:TimerEvent):void {
statusTextDisplay.visible = false;
}
]]>
</mx:Script>
<mx:Image id="cursorImg" visible="false" source="@Embed('org/bigbluebutton/modules/deskshare/assets/images/cursor4.png')"/>
<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="statusTextDisplay" width="100%" fontSize="14" fontWeight="bold" textAlign="center" y="{(this.height - statusTextDisplay.height) / 2}"
visible="false" selectable="false" hideEffect="{dissolveOut}" showEffect="{dissolveIn}"/>
</mx:Application>

View File

@ -66,6 +66,10 @@ package org.bigbluebutton.core
return UserManager.getInstance().getConference().getUserEjectedFromMeeting();
}
public static function isRecorded():Boolean {
return UserManager.getInstance().getConference().record;
}
public static function amIPublishing():CameraSettingsVO {
return UserManager.getInstance().getConference().amIPublishing();
}

View File

@ -96,7 +96,7 @@ package org.bigbluebutton.main.model.users
UserManager.getInstance().getConference().avatarURL = result.avatarURL;
UserManager.getInstance().getConference().voiceBridge = result.voicebridge;
UserManager.getInstance().getConference().dialNumber = result.dialnumber;
UserManager.getInstance().getConference().record = (result.record != "false");
UserManager.getInstance().getConference().record = (result.record.toUpperCase() == "TRUE");

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

View File

@ -0,0 +1,36 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class AppletStartedEvent extends Event
{
public static const APPLET_STARTED:String = "ScreenshareStartedEvent";
public var videoWidth:Number = 0;
public var videoHeight:Number = 0;
public function AppletStartedEvent(type:String = APPLET_STARTED)
{
super(type, true, false);
}
}
}

View File

@ -0,0 +1,36 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class CursorEvent extends Event
{
public static const UPDATE_CURSOR_LOC_EVENT:String = "Screenshare Update sharer cursor event";
public var x:Number = 0;
public var y:Number = 0;
public function CursorEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}

View File

@ -0,0 +1,39 @@
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class IsSharingScreenEvent extends Event
{
private var _streamId: String;
private var _width: int;
private var _height: int;
private var _url: String;
public static const IS_SCREENSHARING: String = "screenshare is sharing screen event";
public function IsSharingScreenEvent(streamId: String, width: int, height: int, url: String)
{
super(IS_SCREENSHARING, true, false);
_streamId = streamId;
_width = width;
_height = height;
_url = url;
}
public function get streamId():String {
return _streamId;
}
public function get width():int {
return _width;
}
public function get height():int {
return _height;
}
public function get url():String {
return _url;
}
}
}

View File

@ -0,0 +1,39 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
import org.bigbluebutton.common.IBigBlueButtonModule;
public class ModuleEvent extends Event
{
public static const START:String = "Screenshare Module Start Event";
public static const STOP:String = "Screenshare Module Stop Event";
public var module:IBigBlueButtonModule;
public function ModuleEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
{
this.module = module;
super(type, bubbles, cancelable);
}
}
}

View File

@ -0,0 +1,40 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class RecordingStatusEvent extends Event
{
public static const DESKSHARE_RECORD_EVENT = "SCREENSHARE RECORD EVENT";
public static const RECORD_STOPPED_EVENT = "SCREENSHARE RECORD STOPPED EVENT";
public static const RECORD_STARTED_EVENT = "SCREENSHARE RECORD STARTED EVENT";
public static const RECORD_UPDATED_EVENT = "SCREENSHARE RECORD UPDATED EVENT";
public static const RECORD_ERROR_EVENT = "SCREENSHARE RECORD ERROR EVENT";
public var status:String;
public function RecordingStatusEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}

View File

@ -0,0 +1,15 @@
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class RequestToStartSharing extends Event
{
public static const REQUEST_SHARE_START:String = "screenshare request to start sharing event";
public function RequestToStartSharing()
{
super(REQUEST_SHARE_START, true, false);
}
}
}

View File

@ -0,0 +1,14 @@
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class RequestToStopSharing extends Event
{
public static const REQUEST_SHARE_STOP:String = "screenshare request to stop sharing event";
public function RequestToStopSharing()
{
super(REQUEST_SHARE_STOP, true, false);
}
}
}

View File

@ -0,0 +1,14 @@
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class ScreenshareAppletLaunchedEvent extends Event
{
public static const APPLET_LAUNCHED:String = "SCREENSHARE APPLET LAUNCHED EVENT";
public function ScreenshareAppletLaunchedEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}

View File

@ -0,0 +1,34 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class ShareEvent extends Event
{
public static const START_SHARING:String = "SCREENSHARE START SHARING";
public static const STOP_SHARING:String = "SCREENSHARE STOP SHARING";
public function ShareEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}

View File

@ -0,0 +1,21 @@
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class ShareStartRequestResponseEvent extends Event
{
public static const SHARE_START_REQUEST_RESPONSE:String = "screenshare start request response event";
public var token: String = null;
public var jnlp: String = null;
public var success: Boolean;
public function ShareStartRequestResponseEvent(token: String, jnlp: String, success: Boolean)
{
super(SHARE_START_REQUEST_RESPONSE, true, false);
this.token = token;
this.jnlp = jnlp;
this.success = success;
}
}
}

View File

@ -0,0 +1,17 @@
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class ShareStartedEvent extends Event
{
public static const SHARE_STATED:String = "screenshare share started event";
public var streamId:String;
public function ShareStartedEvent(streamId: String)
{
super(SHARE_STATED, true, false);
this.streamId = streamId;
}
}
}

View File

@ -0,0 +1,17 @@
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class ShareStoppedEvent extends Event
{
public static const SHARE_STOPPED:String = "screenshare stopped event";
public var streamId:String;
public function ShareStoppedEvent(streamId: String)
{
super(SHARE_STOPPED, true, false);
this.streamId = streamId;
}
}
}

View File

@ -0,0 +1,33 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class ShareWindowEvent extends Event
{
public static const CLOSE:String = "Screenshare Share Window Close Event";
public function ShareWindowEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}

View File

@ -0,0 +1,14 @@
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class StartShareRequestFailedEvent extends Event
{
public static const REQUEST_SHARE_FAILED:String = "screenshare request to start share failed event";
public function StartShareRequestFailedEvent()
{
super(REQUEST_SHARE_FAILED, true, false);
}
}
}

View File

@ -0,0 +1,17 @@
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class StartShareRequestSuccessEvent extends Event
{
public static const START_SHARE_REQUEST_SUCCESS:String = "screenshare start share request success event";
public var authToken: String;
public function StartShareRequestSuccessEvent(token: String)
{
super(START_SHARE_REQUEST_SUCCESS, true, false);
authToken = token;
}
}
}

View File

@ -0,0 +1,35 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class StartedViewingEvent extends Event
{
public static const STARTED_VIEWING_EVENT:String = "STARTED VIEWING SCREENSHARE EVENT";
public var stream:String;
public function StartedViewingEvent(type: String, bubbles:Boolean=true, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}

View File

@ -0,0 +1,33 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class StopSharingButtonEvent extends Event
{
public static const STOP_SHARING:String = "SCREENSHARE Stop Sharing Event";
public function StopSharingButtonEvent(type:String)
{
super(type, true, false);
}
}
}

View File

@ -0,0 +1,37 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class StreamEvent extends Event
{
public static const START:String = "SCREENSHARE Stream Started Event";
public static const STOP:String = "SCREENSHARE Stream Stopped Event";
public var videoWidth:Number = 0;
public var videoHeight:Number = 0;
public function StreamEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}

View File

@ -0,0 +1,39 @@
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class StreamStartedEvent extends Event
{
public static const STREAM_STARTED:String = "screenshare stream started event";
private var _streamId: String;
private var _width: int;
private var _height: int;
private var _url: String;
public function StreamStartedEvent(streamId: String, width: int, height: int, url: String)
{
super(STREAM_STARTED, true, false);
_streamId = streamId;
_width = width;
_height = height;
_url = url;
}
public function get streamId():String {
return _streamId;
}
public function get width():int {
return _width;
}
public function get height():int {
return _height;
}
public function get url():String {
return _url;
}
}
}

View File

@ -0,0 +1,17 @@
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class StreamStoppedEvent extends Event
{
public static const STREAM_STOPPED:String = "screenshare stream stopped event";
public var streamId: String;
public function StreamStoppedEvent(streamId: String)
{
super(STREAM_STOPPED, true, false);
this.streamId = streamId;
}
}
}

View File

@ -0,0 +1,34 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class ViewStreamEvent extends Event
{
public static const START:String = "SCREENSHARE Start Viewing Stream Event";
public static const STOP:String = "SCREENSHARE Stop Viewing Stream Event";
public function ViewStreamEvent(type:String)
{
super(type, true, false);
}
}
}

View File

@ -0,0 +1,33 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.events
{
import flash.events.Event;
public class ViewWindowEvent extends Event
{
public static const CLOSE:String = "SCREENSHARE View Window Close Event";
public function ViewWindowEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}

View File

@ -0,0 +1,100 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.managers
{
import com.asfusion.mate.events.Dispatcher;
import flash.events.TimerEvent;
import flash.utils.Timer;
import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger;
import org.bigbluebutton.common.IBbbModuleWindow;
import org.bigbluebutton.common.LogUtil;
import org.bigbluebutton.common.events.CloseWindowEvent;
import org.bigbluebutton.common.events.OpenWindowEvent;
import org.bigbluebutton.modules.screenshare.services.ScreenshareService;
import org.bigbluebutton.modules.screenshare.view.components.ScreensharePublishWindow;
public class PublishWindowManager {
private static const LOGGER:ILogger = getClassLogger(PublishWindowManager);
private var shareWindow:ScreensharePublishWindow;
private var globalDispatcher:Dispatcher;
private var service:ScreenshareService;
private var buttonShownOnToolbar:Boolean = false;
// 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;
public function PublishWindowManager(service:ScreenshareService) {
LOGGER.debug("PublishWindowManager init");
globalDispatcher = new Dispatcher();
this.service = service;
}
public function stopSharing():void {
if (shareWindow != null) shareWindow.stopSharing();
}
public function startSharing(uri:String, room:String, autoStart:Boolean, autoFullScreen:Boolean):void {
LOGGER.debug("DS:PublishWindowManager::opening desk share window, autostart=" + autoStart + " autoFullScreen=" + autoFullScreen);
shareWindow = new ScreensharePublishWindow();
shareWindow.initWindow(service.getConnection(), uri, room, autoStart, autoFullScreen);
shareWindow.visible = true;
openWindow(shareWindow);
if (autoStart || autoFullScreen) {
/*
* Need to have a timer to trigger auto-publishing of deskshare.
*/
shareWindow.btnFSPublish.enabled = false;
shareWindow.btnRegionPublish.enabled = false;
autoPublishTimer = new Timer(2000, 1);
autoPublishTimer.addEventListener(TimerEvent.TIMER, autopublishTimerHandler);
autoPublishTimer.start();
}
}
private function autopublishTimerHandler(event:TimerEvent):void {
shareWindow.shareScreen(true);
}
public function handleShareWindowCloseEvent():void {
closeWindow(shareWindow);
}
private function openWindow(window:IBbbModuleWindow):void {
var event:OpenWindowEvent = new OpenWindowEvent(OpenWindowEvent.OPEN_WINDOW_EVENT);
event.window = window;
globalDispatcher.dispatchEvent(event);
}
private function closeWindow(window:IBbbModuleWindow):void {
var event:CloseWindowEvent = new CloseWindowEvent(CloseWindowEvent.CLOSE_WINDOW_EVENT);
event.window = window;
globalDispatcher.dispatchEvent(event);
}
}
}

View File

@ -0,0 +1,207 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.managers
{
import com.asfusion.mate.events.Dispatcher;
import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger;
import org.bigbluebutton.core.UsersUtil;
import org.bigbluebutton.main.events.MadePresenterEvent;
import org.bigbluebutton.modules.screenshare.events.IsSharingScreenEvent;
import org.bigbluebutton.modules.screenshare.events.ShareStartRequestResponseEvent;
import org.bigbluebutton.modules.screenshare.events.StartShareRequestFailedEvent;
import org.bigbluebutton.modules.screenshare.events.StartShareRequestSuccessEvent;
import org.bigbluebutton.modules.screenshare.events.StreamStartedEvent;
import org.bigbluebutton.modules.screenshare.events.ViewStreamEvent;
import org.bigbluebutton.modules.screenshare.model.ScreenshareModel;
import org.bigbluebutton.modules.screenshare.model.ScreenshareOptions;
import org.bigbluebutton.modules.screenshare.services.ScreenshareService;
public class ScreenshareManager {
private static const LOGGER:ILogger = getClassLogger(ScreenshareManager);
private static const LOG:String = "SC::ScreenshareManager - ";
private var publishWindowManager:PublishWindowManager;
private var viewWindowManager:ViewerWindowManager;
private var toolbarButtonManager:ToolbarButtonManager;
private var module:ScreenshareModule;
private var service:ScreenshareService;
private var globalDispatcher:Dispatcher;
private var sharing:Boolean = false;
public function ScreenshareManager() {
service = new ScreenshareService();
globalDispatcher = new Dispatcher();
publishWindowManager = new PublishWindowManager(service);
viewWindowManager = new ViewerWindowManager(service);
toolbarButtonManager = new ToolbarButtonManager();
}
public function handleStartModuleEvent(module:ScreenshareModule):void {
trace(LOG + "Screenshare Module starting");
this.module = module;
service.handleStartModuleEvent(module);
if (UsersUtil.amIPresenter()) {
initDeskshare();
}
}
public function handleStopModuleEvent():void {
trace(LOG + "Screenshare Module stopping");
publishWindowManager.stopSharing();
viewWindowManager.stopViewing();
service.disconnect();
}
public function handleConnectionSuccessEvent():void {
trace(LOG + "handle Connection Success Event");
service.checkIfPresenterIsSharingScreen();
}
public function handleStreamStoppedEvent():void {
LOGGER.debug("Sending deskshare stopped command");
service.stopSharingDesktop(module.getRoom(), module.getRoom());
}
public function handleStreamStartedEvent(event: StreamStartedEvent):void {
ScreenshareModel.getInstance().streamId = event.streamId;
ScreenshareModel.getInstance().width = event.width;
ScreenshareModel.getInstance().height = event.height;
ScreenshareModel.getInstance().url = event.url;
if (UsersUtil.amIPresenter()) {
// var dispatcher:Dispatcher = new Dispatcher();
// dispatcher.dispatchEvent(new ViewStreamEvent(ViewStreamEvent.START));
} else {
handleStreamStartEvent(ScreenshareModel.getInstance().streamId, event.width, event.height);
}
var dispatcher:Dispatcher = new Dispatcher();
dispatcher.dispatchEvent(new ViewStreamEvent(ViewStreamEvent.START));
}
public function handleIsSharingScreenEvent(event: IsSharingScreenEvent):void {
ScreenshareModel.getInstance().streamId = event.streamId;
ScreenshareModel.getInstance().width = event.width;
ScreenshareModel.getInstance().height = event.height;
ScreenshareModel.getInstance().url = event.url;
if (UsersUtil.amIPresenter()) {
// var dispatcher:Dispatcher = new Dispatcher();
// dispatcher.dispatchEvent(new ViewStreamEvent(ViewStreamEvent.START));
} else {
handleStreamStartEvent(ScreenshareModel.getInstance().streamId, event.width, event.height);
}
var dispatcher:Dispatcher = new Dispatcher();
dispatcher.dispatchEvent(new ViewStreamEvent(ViewStreamEvent.START));
}
public function handleStartedViewingEvent(stream:String):void {
LOGGER.debug("handleStartedViewingEvent [" + stream + "]");
service.sendStartedViewingNotification(stream);
}
private function initDeskshare():void {
sharing = false;
var option:ScreenshareOptions = new ScreenshareOptions();
option.parseOptions();
if (option.autoStart) {
handleStartSharingEvent(true);
}
if(option.showButton){
toolbarButtonManager.addToolbarButton();
}
}
public function handleMadePresenterEvent(e:MadePresenterEvent):void {
LOGGER.debug("Got MadePresenterEvent ");
initDeskshare();
}
public function handleMadeViewerEvent(e:MadePresenterEvent):void{
LOGGER.debug("Got MadeViewerEvent ");
toolbarButtonManager.removeToolbarButton();
if (sharing) {
service.requestStopSharing(ScreenshareModel.getInstance().streamId);
publishWindowManager.stopSharing();
}
sharing = false;
}
public function handleRequestStartSharingEvent():void {
toolbarButtonManager.startedSharing();
var option:ScreenshareOptions = new ScreenshareOptions();
option.parseOptions();
var autoStart:Boolean = false; // harcode for now
publishWindowManager.startSharing(module.getCaptureServerUri(), module.getRoom(), autoStart, option.autoFullScreen);
sharing = true;
service.requestStartSharing();
}
public function handleRequestStopSharingEvent():void {
service.requestStopSharing(ScreenshareModel.getInstance().streamId);
}
public function handleShareStartRequestResponseEvent(event:ShareStartRequestResponseEvent):void {
trace(LOG + "handleShareStartRequestResponseEvent");
var dispatcher:Dispatcher = new Dispatcher();
if (event.success) {
ScreenshareModel.getInstance().authToken = event.token;
ScreenshareModel.getInstance().jnlp = event.jnlp;
dispatcher.dispatchEvent(new StartShareRequestSuccessEvent(ScreenshareModel.getInstance().authToken));
} else {
dispatcher.dispatchEvent(new StartShareRequestFailedEvent());
}
}
public function handleStartSharingEvent(autoStart:Boolean):void {
trace(LOG + "handleStartSharingEvent");
//toolbarButtonManager.disableToolbarButton();
toolbarButtonManager.startedSharing();
var option:ScreenshareOptions = new ScreenshareOptions();
option.parseOptions();
publishWindowManager.startSharing(module.getCaptureServerUri(), module.getRoom(), autoStart, option.autoFullScreen);
sharing = true;
}
public function handleShareWindowCloseEvent():void {
//toolbarButtonManager.enableToolbarButton();
publishWindowManager.handleShareWindowCloseEvent();
sharing = false;
toolbarButtonManager.stopedSharing();
}
public function handleViewWindowCloseEvent():void {
LOGGER.debug("Received stop viewing command");
viewWindowManager.handleViewWindowCloseEvent();
}
private function handleStreamStartEvent(streamId: String, videoWidth:Number, videoHeight:Number):void{
trace(LOG + "Received start vieweing command");
viewWindowManager.startViewing(streamId, videoWidth, videoHeight);
}
}
}

View File

@ -0,0 +1,84 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.managers
{
import com.asfusion.mate.events.Dispatcher;
import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger;
import org.bigbluebutton.common.events.ToolbarButtonEvent;
import org.bigbluebutton.modules.screenshare.view.components.ToolbarButton;
public class ToolbarButtonManager {
private static const LOGGER:ILogger = getClassLogger(ToolbarButtonManager);
private var button:ToolbarButton;
private var isSharing:Boolean = false;
private var globalDispatcher:Dispatcher;
private var buttonShownOnToolbar:Boolean = false;
public function ToolbarButtonManager() {
globalDispatcher = new Dispatcher();
button = new ToolbarButton();
}
public function addToolbarButton():void {
LOGGER.debug("DeskShare::addToolbarButton");
if ((button != null) && (!buttonShownOnToolbar)) {
button = new ToolbarButton();
/* Test */ //button.tabIndex=4;
var event:ToolbarButtonEvent = new ToolbarButtonEvent(ToolbarButtonEvent.ADD);
event.button = button;
event.module="DeskShare";
//event.tabIndex = 0;
globalDispatcher.dispatchEvent(event);
buttonShownOnToolbar = true;
button.enabled = true;
}
}
public function removeToolbarButton():void {
if (buttonShownOnToolbar) {
var event:ToolbarButtonEvent = new ToolbarButtonEvent(ToolbarButtonEvent.REMOVE);
event.button = button;
globalDispatcher.dispatchEvent(event);
buttonShownOnToolbar = false;
}
}
//OLD - CAN BE DELETED
public function enableToolbarButton():void {
button.enabled = true;
button.stopDeskshare();
}
//OLD - CAN BE DELETED
public function disableToolbarButton():void {
button.enabled = false;
}
public function startedSharing():void {
button.deskshareStatus(button.START_SHARING);
}
public function stopedSharing():void {
button.deskshareStatus(button.STOP_SHARING);
}
}
}

View File

@ -0,0 +1,83 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.managers
{
import com.asfusion.mate.events.Dispatcher;
import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger;
import org.bigbluebutton.common.IBbbModuleWindow;
import org.bigbluebutton.common.LogUtil;
import org.bigbluebutton.common.events.CloseWindowEvent;
import org.bigbluebutton.common.events.OpenWindowEvent;
import org.bigbluebutton.modules.screenshare.services.ScreenshareService;
import org.bigbluebutton.modules.screenshare.view.components.ScreenshareViewWindow;
public class ViewerWindowManager {
private static const LOG:String = "SC::ViewerWindowManager - ";
private static const LOGGER:ILogger = getClassLogger(ViewerWindowManager);
private var viewWindow:ScreenshareViewWindow;
private var service:ScreenshareService;
private var isViewing:Boolean = false;
private var globalDispatcher:Dispatcher;
public function ViewerWindowManager(service:ScreenshareService) {
this.service = service;
globalDispatcher = new Dispatcher();
}
public function stopViewing():void {
if (isViewing) viewWindow.stopViewing();
}
public function handleStartedViewingEvent(stream:String):void{
LOGGER.debug("ViewerWindowManager handleStartedViewingEvent");
service.sendStartedViewingNotification(stream);
}
private function openWindow(window:IBbbModuleWindow):void{
var event:OpenWindowEvent = new OpenWindowEvent(OpenWindowEvent.OPEN_WINDOW_EVENT);
event.window = window;
globalDispatcher.dispatchEvent(event);
}
public function handleViewWindowCloseEvent():void {
LOGGER.debug("ViewerWindowManager Received stop viewing command");
closeWindow(viewWindow);
isViewing = false;
}
private function closeWindow(window:IBbbModuleWindow):void {
var event:CloseWindowEvent = new CloseWindowEvent(CloseWindowEvent.CLOSE_WINDOW_EVENT);
event.window = window;
globalDispatcher.dispatchEvent(event);
}
public function startViewing(streamId:String, videoWidth:Number, videoHeight:Number):void{
trace(LOG + "ViewerWindowManager::startViewing");
viewWindow = new ScreenshareViewWindow();
viewWindow.startVideo(service.getConnection());
openWindow(viewWindow);
isViewing = true;
}
}
}

View File

@ -0,0 +1,121 @@
<?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 program is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-->
<EventMap xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns="http://mate.asfusion.com/">
<mx:Script>
<![CDATA[
import org.bigbluebutton.modules.screenshare.events.IsSharingScreenEvent;
import mx.events.FlexEvent;
import org.bigbluebutton.main.events.BBBEvent;
import org.bigbluebutton.main.events.MadePresenterEvent;
import org.bigbluebutton.modules.screenshare.events.ModuleEvent;
import org.bigbluebutton.modules.screenshare.events.RequestToStartSharing;
import org.bigbluebutton.modules.screenshare.events.RequestToStopSharing;
import org.bigbluebutton.modules.screenshare.events.ShareEvent;
import org.bigbluebutton.modules.screenshare.events.ShareStartRequestResponseEvent;
import org.bigbluebutton.modules.screenshare.events.ShareWindowEvent;
import org.bigbluebutton.modules.screenshare.events.StartedViewingEvent;
import org.bigbluebutton.modules.screenshare.events.StreamEvent;
import org.bigbluebutton.modules.screenshare.events.StreamStartedEvent;
import org.bigbluebutton.modules.screenshare.events.IsSharingScreenEvent;
import org.bigbluebutton.modules.screenshare.events.ViewWindowEvent;
import org.bigbluebutton.modules.screenshare.managers.ScreenshareManager;
import org.bigbluebutton.modules.screenshare.services.red5.ConnectionEvent;
]]>
</mx:Script>
<EventHandlers type="{FlexEvent.PREINITIALIZE}">
<!--
The FlexEvent.PREINITIALIZE event is a good place for creating and initializing managers.
-->
<ObjectBuilder generator="{ScreenshareManager}"/>
</EventHandlers>
<EventHandlers type="{ShareEvent.START_SHARING}">
<MethodInvoker generator="{ScreenshareManager}" method="handleStartSharingEvent" arguments="{false}"/>
</EventHandlers>
<EventHandlers type="{BBBEvent.START_DESKSHARE}">
<MethodInvoker generator="{ScreenshareManager}" method="handleStartSharingEvent" arguments="{true}"/>
</EventHandlers>
<EventHandlers type="{RequestToStartSharing.REQUEST_SHARE_START}">
<MethodInvoker generator="{ScreenshareManager}" method="handleRequestStartSharingEvent"/>
</EventHandlers>
<EventHandlers type="{RequestToStopSharing.REQUEST_SHARE_STOP}">
<MethodInvoker generator="{ScreenshareManager}" method="handleRequestStopSharingEvent"/>
</EventHandlers>
<EventHandlers type="{ShareStartRequestResponseEvent.SHARE_START_REQUEST_RESPONSE}">
<MethodInvoker generator="{ScreenshareManager}" method="handleShareStartRequestResponseEvent" arguments="{event}"/>
</EventHandlers>
<EventHandlers type="{MadePresenterEvent.SWITCH_TO_PRESENTER_MODE}">
<MethodInvoker generator="{ScreenshareManager}" method="handleMadePresenterEvent" arguments="{event}"/>
</EventHandlers>
<EventHandlers type="{MadePresenterEvent.SWITCH_TO_VIEWER_MODE}">
<MethodInvoker generator="{ScreenshareManager}" method="handleMadeViewerEvent" arguments="{event}"/>
</EventHandlers>
<EventHandlers type="{StreamStartedEvent.STREAM_STARTED}">
<MethodInvoker generator="{ScreenshareManager}" method="handleStreamStartedEvent" arguments="{event}"/>
</EventHandlers>
<EventHandlers type="{StreamEvent.STOP}" >
<MethodInvoker generator="{ScreenshareManager}" method="handleStreamStoppedEvent"/>
</EventHandlers>
<EventHandlers type="{IsSharingScreenEvent.IS_SCREENSHARING}">
<MethodInvoker generator="{ScreenshareManager}" method="handleIsSharingScreenEvent" arguments="{event}"/>
</EventHandlers>
<EventHandlers type="{ShareWindowEvent.CLOSE}">
<MethodInvoker generator="{ScreenshareManager}" method="handleShareWindowCloseEvent"/>
</EventHandlers>
<EventHandlers type="{ConnectionEvent.SUCCESS}">
<MethodInvoker generator="{ScreenshareManager}" method="handleConnectionSuccessEvent"/>
</EventHandlers>
<EventHandlers type="{StartedViewingEvent.STARTED_VIEWING_EVENT}">
<MethodInvoker generator="{ScreenshareManager}" method="handleStartedViewingEvent" arguments="{event.stream}"/>
</EventHandlers>
<EventHandlers type="{ViewWindowEvent.CLOSE}">
<MethodInvoker generator="{ScreenshareManager}" method="handleViewWindowCloseEvent"/>
</EventHandlers>
<EventHandlers type="{ModuleEvent.STOP}">
<MethodInvoker generator="{ScreenshareManager}" method="handleStopModuleEvent"/>
</EventHandlers>
<EventHandlers type="{ModuleEvent.START}">
<MethodInvoker generator="{ScreenshareManager}" method="handleStartModuleEvent" arguments="{event.module}"/>
</EventHandlers>
</EventMap>

View File

@ -0,0 +1,79 @@
package org.bigbluebutton.modules.screenshare.model
{
public class ScreenshareModel
{
private static var instance:ScreenshareModel = null;
private var _isScreenSharing:Boolean = false;
private var _stream: ScreenshareStream = new ScreenshareStream();
public function ScreenshareModel(enforcer:SingletonEnforcer) {
if (enforcer == null){
throw new Error("There can only be 1 ScreenshareModel instance");
}
}
public static function getInstance():ScreenshareModel{
if (instance == null){
instance = new ScreenshareModel(new SingletonEnforcer());
}
return instance;
}
public function get isSharing():Boolean {
return _isScreenSharing;
}
public function get width():int {
return _stream.width;
}
public function set width(w: int):void {
_stream.width = w;
}
public function get height():int {
return _stream.height;
}
public function set height(h: int):void {
_stream.height = h;
}
public function get url():String {
return _stream.url;
}
public function set url(u: String):void {
_stream.url = u;
}
public function get streamId():String {
return _stream.streamId;
}
public function set streamId(s: String):void {
_stream.streamId = s;
}
public function get authToken():String {
return _stream.authToken;
}
public function set authToken(token:String):void {
_stream.authToken = token;
}
public function get jnlp():String {
return _stream.jnlp;
}
public function set jnlp(j:String):void {
_stream.jnlp = j;
}
}
}
class SingletonEnforcer{}

View File

@ -0,0 +1,51 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.model
{
import org.bigbluebutton.core.BBB;
public class ScreenshareOptions
{
[Bindable] public var showButton:Boolean = true;
[Bindable] public var autoStart:Boolean = false;
[Bindable] public var autoFullScreen:Boolean = false;
[Bindable] public var baseTabIndex:int;
public function parseOptions():void {
var vxml:XML = BBB.getConfigForModule("ScreenshareModule");
if (vxml != null) {
if (vxml.@autoStart != undefined) {
autoStart = (vxml.@autoStart.toString().toUpperCase() == "TRUE") ? true : false;
}
if (vxml.@autoFullScreen != undefined){
autoFullScreen = (vxml.@autoFullScreen.toString().toUpperCase() == "TRUE") ? true : false;
}
if (vxml.@baseTabIndex != undefined) {
baseTabIndex = vxml.@baseTabIndex;
}
else{
baseTabIndex = 201;
}
if (vxml.@showButton != undefined){
showButton = (vxml.@showButton.toString().toUpperCase() == "TRUE") ? true : false;
}
}
}
}
}

View File

@ -0,0 +1,12 @@
package org.bigbluebutton.modules.screenshare.model
{
public class ScreenshareStream
{
public var streamId: String;
public var width: int;
public var height: int;
public var url: String;
public var authToken: String;
public var jnlp: String;
}
}

View File

@ -0,0 +1,135 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.services
{
import com.asfusion.mate.events.Dispatcher;
import org.bigbluebutton.modules.screenshare.events.IsSharingScreenEvent;
import org.bigbluebutton.modules.screenshare.events.ShareStartRequestResponseEvent;
import org.bigbluebutton.modules.screenshare.events.ShareStartedEvent;
import org.bigbluebutton.modules.screenshare.events.ShareStoppedEvent;
import org.bigbluebutton.modules.screenshare.events.StreamStartedEvent;
import org.bigbluebutton.modules.screenshare.events.StreamStoppedEvent;
import org.bigbluebutton.modules.screenshare.services.red5.Connection;
import org.bigbluebutton.modules.screenshare.services.red5.IMessageListener;
public class MessageReceiver implements IMessageListener
{
private static const LOG:String = "SC::MessageReceiver - ";
private var conn: Connection;
private var dispatcher:Dispatcher = new Dispatcher();
public function MessageReceiver(conn: Connection) {
this.conn = conn;
this.conn.addMessageListener(this);
}
public function onMessage(messageName:String, message:Object):void {
trace(LOG + " Received message " + messageName);
switch (messageName) {
case "isSharingScreenRequestResponse":
handleIsSharingScreenRequestResponse(message);
break;
case "startShareRequestResponse":
handleStartShareRequestResponse(message);
break;
case "screenShareStartedMessage":
handleScreenShareStartedMessage(message);
break;
case "screenShareStoppedMessage":
handleScreenShareStoppedMessage(message);
break;
case "screenStreamStartedMessage":
handleScreenStreamStartedMessage(message);
break;
case "screenStreamStoppedMessage":
handleScreenStreamStoppedMessage(message);
break;
default:
// LogUtil.warn("Cannot handle message [" + messageName + "]");
}
}
private function handleStartShareRequestResponse(message:Object):void {
trace(LOG + "handleStartShareRequestResponse " + message);
var map:Object = JSON.parse(message.msg);
if (map.hasOwnProperty("authToken") && map.hasOwnProperty("jnlp")) {
var shareSuccessEvent: ShareStartRequestResponseEvent = new ShareStartRequestResponseEvent(map.authToken, map.jnlp, true);
dispatcher.dispatchEvent(shareSuccessEvent);
} else {
var shareFailedEvent: ShareStartRequestResponseEvent = new ShareStartRequestResponseEvent(null, null, false);
dispatcher.dispatchEvent(shareFailedEvent);
}
}
private function handleScreenShareStartedMessage(message:Object):void {
trace(LOG + "handleScreenShareStartedMessage " + message);
var map:Object = JSON.parse(message.msg);
if (map.hasOwnProperty("streamId")) {
var streamEvent: ShareStartedEvent = new ShareStartedEvent(map.streamId);
dispatcher.dispatchEvent(streamEvent);
}
}
private function handleScreenShareStoppedMessage(message:Object):void {
trace(LOG + "handleScreenShareStoppedMessage " + message);
var map:Object = JSON.parse(message.msg);
if (map.hasOwnProperty("streamId")) {
var streamEvent: ShareStoppedEvent = new ShareStoppedEvent(map.streamId);
dispatcher.dispatchEvent(streamEvent);
}
}
private function handleScreenStreamStartedMessage(message:Object):void {
trace(LOG + "handleScreenStreamStartedMessage " + message);
var map:Object = JSON.parse(message.msg);
if (map.hasOwnProperty("streamId") && map.hasOwnProperty("width") &&
map.hasOwnProperty("height") && map.hasOwnProperty("url")) {
var streamEvent: StreamStartedEvent = new StreamStartedEvent(map.streamId, map.width,
map.height, map.url);
dispatcher.dispatchEvent(streamEvent);
}
}
private function handleScreenStreamStoppedMessage(message:Object):void {
trace(LOG + "handleScreenStreamStoppedMessage " + message);
var map:Object = JSON.parse(message.msg);
if (map.hasOwnProperty("streamId")) {
var streamEvent: StreamStoppedEvent = new StreamStoppedEvent(map.streamId);
dispatcher.dispatchEvent(streamEvent);
}
}
private function handleIsSharingScreenRequestResponse(message:Object):void {
trace(LOG + "handleIsSharingScreenRequestResponse " + message);
var map:Object = JSON.parse(message.msg);
if (map.hasOwnProperty("sharing") && map.sharing) {
if (map.hasOwnProperty("streamId") && map.hasOwnProperty("width") &&
map.hasOwnProperty("height") && map.hasOwnProperty("url")) {
// var shareEvent: IsSharingScreenEvent = new IsSharingScreenEvent(map.streamId, map.width,
// map.height, map.url);
// dispatcher.dispatchEvent(shareEvent);
var streamEvent: StreamStartedEvent = new StreamStartedEvent(map.streamId, map.width,
map.height, map.url);
dispatcher.dispatchEvent(streamEvent);
}
}
}
}
}

View File

@ -0,0 +1,47 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.services
{
import org.bigbluebutton.modules.screenshare.services.red5.Connection;
public class MessageSender
{
private static const LOG:String = "SC::MessageSender - ";
private var conn: Connection;
public function MessageSender(conn: Connection) {
this.conn = conn;
}
public function isScreenSharing(meetingId: String):void {
conn.isScreenSharing(meetingId);
}
public function startShareRequest(meetingId: String, userId: String, record: Boolean):void {
conn.startShareRequest(meetingId, userId, record);
}
public function stopShareRequest(meetingId: String, streamId: String):void {
conn.stopShareRequest(meetingId, streamId);
}
}
}

View File

@ -0,0 +1,104 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.services
{
import com.asfusion.mate.events.Dispatcher;
import flash.net.NetConnection;
import org.bigbluebutton.core.UsersUtil;
import org.bigbluebutton.modules.screenshare.services.red5.Connection;
/**
* The DeskShareProxy communicates with the Red5 deskShare server application
* @author Snap
*
*/
public class ScreenshareService
{
private static const LOG:String = "SC::ScreenshareService - ";
private var conn:Connection;
private var module:ScreenshareModule;
private var dispatcher:Dispatcher;
private var uri:String;
private var room:String;
private var sender: MessageSender;
private var receiver: MessageReceiver;
public function ScreenshareService() {
this.dispatcher = new Dispatcher();
}
public function handleStartModuleEvent(module:ScreenshareModule):void {
trace(LOG + "Screenshare Module starting");
this.module = module;
connect(module.uri, module.getRoom());
}
public function connect(uri:String, room:String):void {
this.uri = uri;
this.room = room;
trace(LOG + "Screenshare Service connecting to " + uri);
conn = new Connection(room);
sender = new MessageSender(conn);
receiver = new MessageReceiver(conn);
conn.setURI(uri);
conn.connect();
}
public function getConnection():NetConnection{
return conn.getConnection();
}
public function disconnect():void{
conn.disconnect();
}
public function checkIfPresenterIsSharingScreen():void {
trace(LOG + "check if presenter is sharing screen");
sender.isScreenSharing(UsersUtil.getInternalMeetingID());
}
public function requestStartSharing():void {
sender.startShareRequest(UsersUtil.getInternalMeetingID(), UsersUtil.getMyUserID(), UsersUtil.isRecorded());
}
public function requestStopSharing(streamId: String):void {
sender.stopShareRequest(UsersUtil.getInternalMeetingID(), streamId);
}
public function sendStartViewingNotification(captureWidth:Number, captureHeight:Number):void{
conn.sendStartViewingNotification(captureWidth, captureHeight);
}
public function sendStartedViewingNotification(stream:String):void{
conn.sendStartedViewingNotification(stream);
}
public function stopSharingDesktop(meetingId: String, stream: String):void {
conn.stopSharingDesktop(meetingId, stream);
}
}
}

View File

@ -0,0 +1,422 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.services.red5
{
import com.asfusion.mate.events.Dispatcher;
import flash.events.NetStatusEvent;
import flash.events.SecurityErrorEvent;
import flash.events.TimerEvent;
import flash.net.NetConnection;
import flash.net.ObjectEncoding;
import flash.net.Responder;
import flash.net.SharedObject;
import flash.utils.Timer;
import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger;
import org.bigbluebutton.common.LogUtil;
import org.bigbluebutton.core.UsersUtil;
import org.bigbluebutton.modules.screenshare.events.AppletStartedEvent;
import org.bigbluebutton.modules.screenshare.events.CursorEvent;
import org.bigbluebutton.modules.screenshare.events.ViewStreamEvent;
public class Connection {
private static const LOGGER:ILogger = getClassLogger(Connection);
public static const LOG:String = "Screenshare::Connection - ";
private var netConn:NetConnection;
private var uri:String;
private const connectionTimeout:int = 5000;
private var retryTimer:Timer = null;
private var retryCount:int = 0;
private const MAX_RETRIES:int = 5;
private var deskSO:SharedObject;
private var responder:Responder;
private var width:Number;
private var height:Number;
private var meetingId:String;
private var dispatcher:Dispatcher = new Dispatcher();
private var _messageListeners:Array = new Array();
public function Connection(meetingId:String) {
this.meetingId = meetingId;
}
public function connect(retry:Boolean = false):void {
netConn = new NetConnection();
netConn.proxyType = "best";
netConn.objectEncoding = ObjectEncoding.AMF0;
netConn.client = this;
netConn.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
netConn.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
if (getURI().length == 0){
trace(LOG + "please provide a valid URI connection string. URI Connection String missing");
return;
} else if (netConn.connected){
trace(LOG + "You are already connected to " + getURI());
return;
}
trace(LOG + "Trying to connect to [" + getURI() + "] retry=[" + retry + "]");
if (! (retryCount > 0)) {
var ce:ConnectionEvent = new ConnectionEvent(ConnectionEvent.CONNECTING);
dispatcher.dispatchEvent(ce);
}
netConn.connect(getURI());
if (!retry) {
retryTimer = new Timer(connectionTimeout, 1);
retryTimer.addEventListener(TimerEvent.TIMER_COMPLETE, connectTimeoutHandler);
retryTimer.start();
}
}
public function addMessageListener(listener:IMessageListener):void {
_messageListeners.push(listener);
}
public function removeMessageListener(listener:IMessageListener):void {
for (var ob:int=0; ob<_messageListeners.length; ob++) {
if (_messageListeners[ob] == listener) {
_messageListeners.splice (ob,1);
break;
}
}
}
private function notifyListeners(messageName:String, message:Object):void {
if (messageName != null && messageName != "") {
for (var notify:String in _messageListeners) {
_messageListeners[notify].onMessage(messageName, message);
}
} else {
trace( LOG + "Message name is undefined");
}
}
public function onMessageFromServer(messageName:String, msg:Object):void {
trace(LOG + "Got message from server [" + messageName + "] data=" + msg.msg);
notifyListeners(messageName, msg);
}
private function connectTimeoutHandler(e:TimerEvent):void {
trace(LOG + "Connection attempt to [" + getURI() + "] timedout. Retrying.");
retryTimer.stop();
retryTimer = null;
netConn.close();
netConn = null;
var ce:ConnectionEvent;
retryCount++;
if (retryCount < MAX_RETRIES) {
ce = new ConnectionEvent(ConnectionEvent.CONNECTING_RETRY);
ce.retryAttempts = retryCount;
dispatcher.dispatchEvent(ce);
connect(false);
} else {
ce = new ConnectionEvent(ConnectionEvent.CONNECTING_MAX_RETRY);
dispatcher.dispatchEvent(ce);
}
}
public function close():void{
netConn.close();
}
public function isScreenSharing(meetingId: String):void {
var message:Object = new Object();
message["meetingId"] = meetingId;
sendMessage("screenshare.isScreenSharing",
function(result:String):void { // On successful result
LOGGER.debug(result);
},
function(status:String):void { // status - On error occurred
LOGGER.error(status);
},
message
);
}
private function sendMessage(service:String, onSuccess:Function, onFailure:Function, message:Object=null):void {
trace(LOG + "SENDING [" + service + "]");
var responder:Responder = new Responder(
function(result:Object):void { // On successful result
onSuccess("Successfully sent [" + service + "].");
},
function(status:Object):void { // status - On error occurred
var errorReason:String = "Failed to send [" + service + "]:\n";
for (var x:Object in status) {
errorReason += "\t" + x + " : " + status[x];
}
}
);
if (message == null) {
netConn.call(service, responder);
} else {
netConn.call(service, responder, message);
}
}
public function startShareRequest(meetingId: String, userId: String, record: Boolean):void {
var message:Object = new Object();
message["meetingId"] = meetingId;
message["userId"] = userId;
message["record"] = record;
sendMessage("screenshare.startShareRequest",
function(result:String):void { // On successful result
LOGGER.debug(result);
},
function(status:String):void { // status - On error occurred
LOGGER.error(status);
},
message
);
}
public function stopShareRequest(meetingId: String, streamId: String):void {
var message:Object = new Object();
message["meetingId"] = meetingId;
message["streamId"] = streamId;
sendMessage("screenshare.stopShareRequest",
function(result:String):void { // On successful result
LOGGER.debug(result);
},
function(status:String):void { // status - On error occurred
LOGGER.error(status);
},
message
);
}
public function setURI(p_URI:String):void{
uri = p_URI;
}
public function getURI():String{
return uri + "/" + UsersUtil.getInternalMeetingID();
}
public function onBWCheck(... rest):Number {
return 0;
}
public function onBWDone(... rest):void {
var p_bw:Number;
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.");
}
private function sendUserIdToServer():void {
var message:Object = new Object();
message["meetingId"] = meetingId;
message["userId"] = UsersUtil.getMyUserID();
sendMessage("screenshare.setUserId",
function(result:String):void { // On successful result
LOGGER.debug(result);
},
function(status:String):void { // status - On error occurred
LOGGER.error(status);
},
message
);
}
private function netStatusHandler(event:NetStatusEvent):void {
trace(LOG + "Connected to [" + getURI() + "]. [" + event.info.code + "]");
if (retryTimer) {
retryCount = 0;
trace(LOG + "Cancelling retry timer.");
retryTimer.stop();
retryTimer = null;
}
var ce:ConnectionEvent;
switch(event.info.code){
case "NetConnection.Connect.Failed":
ce = new ConnectionEvent(ConnectionEvent.FAILED);
dispatcher.dispatchEvent(ce);
break;
case "NetConnection.Connect.Success":
sendUserIdToServer();
ce = new ConnectionEvent(ConnectionEvent.SUCCESS);
dispatcher.dispatchEvent(ce);
break;
case "NetConnection.Connect.Rejected":
ce = new ConnectionEvent(ConnectionEvent.REJECTED);
dispatcher.dispatchEvent(ce);
break;
case "NetConnection.Connect.Closed":
trace(LOG + "Screenshare connection closed.");
ce = new ConnectionEvent(ConnectionEvent.CLOSED);
break;
case "NetConnection.Connect.InvalidApp":
ce = new ConnectionEvent(ConnectionEvent.INVALIDAPP);
dispatcher.dispatchEvent(ce);
break;
case "NetConnection.Connect.AppShutdown":
ce = new ConnectionEvent(ConnectionEvent.APPSHUTDOWN);
dispatcher.dispatchEvent(ce);
break;
case "NetConnection.Connect.NetworkChange":
trace(LOG + "Detected network change. User might be on a wireless and temporarily dropped connection. Doing nothing. Just making a note.");
break;
default :
// I dispatch DISCONNECTED incase someone just simply wants to know if we're not connected'
// rather than having to subscribe to the events individually
ce = new ConnectionEvent(ConnectionEvent.DISCONNECTED);
dispatcher.dispatchEvent(ce);
break;
}
}
private function securityErrorHandler(event:SecurityErrorEvent):void{
var ce:ConnectionEvent = new ConnectionEvent(ConnectionEvent.SECURITYERROR);
dispatcher.dispatchEvent(ce);
}
public function mouseLocationCallback(x:Number, y:Number):void {
var event:CursorEvent = new CursorEvent(CursorEvent.UPDATE_CURSOR_LOC_EVENT);
event.x = x;
event.y = y;
dispatcher.dispatchEvent(event);
}
public function disconnect():void{
if (netConn != null) netConn.close();
}
public function getConnection():NetConnection{
return netConn;
}
public function connectionFailedHandler(e:ConnectionEvent):void{
LOGGER.error("connection failed to " + uri + " with message " + e.toString());
trace(LOG + "connection failed to " + uri + " with message " + e.toString());
}
public function connectionRejectedHandler(e:ConnectionEvent):void{
LOGGER.error("connection rejected " + uri + " with message " + e.toString());
trace(LOG + "connection rejected " + uri + " with message " + e.toString());
}
/**
* Invoked on the server once the clients' applet has started sharing and the server has started a video stream
*
*/
public function appletStarted(videoWidth:Number, videoHeight:Number):void{
trace(LOG + "Got applet started");
var event:AppletStartedEvent = new AppletStartedEvent();
event.videoWidth = videoWidth;
event.videoHeight = videoHeight;
dispatcher.dispatchEvent(event);
}
/**
* Call this method to send out a room-wide notification to start viewing the stream
*
*/
public function sendStartViewingNotification(captureWidth:Number, captureHeight:Number):void{
try{
deskSO.send("startViewing", captureWidth, captureHeight);
} catch(e:Error){
LOGGER.error("error while trying to send start viewing notification");
}
}
public function sendStartedViewingNotification(stream:String):void{
trace(LOG + "Sending start viewing to server");
netConn.call("deskshare.startedToViewStream", null, stream);
}
public function stopSharingDesktop(meetingId: String, stream: String):void {
netConn.call("deskshare.stopSharingDesktop", null, meetingId);
}
/**
* Called by the server when a notification is received to start viewing the broadcast stream .
* This method is called on successful execution of sendStartViewingNotification()
*
*/
public function startViewing(videoWidth:Number, videoHeight:Number):void{
trace(LOG + "startViewing invoked by server");
var event:ViewStreamEvent = new ViewStreamEvent(ViewStreamEvent.START);
dispatcher.dispatchEvent(event);
}
/**
* Sends a notification through the server to all the participants in the room to stop viewing the stream
*
*/
public function sendStopViewingNotification():void{
trace(LOG + "Sending stop viewing notification to other clients.");
try{
deskSO.send("stopViewing");
} catch(e:Error){
trace(LOG + "could not send stop viewing notification");
}
}
/**
* Called by the server to notify clients that the deskshare stream has stooped.
*/
public function deskshareStreamStopped():void {
stopViewing();
}
/**
* Sends a notification to the module to stop viewing the stream
* This method is called on successful execution of sendStopViewingNotification()
*
*/
public function stopViewing():void{
trace(LOG + "Received dekskshareStreamStopped");
dispatcher.dispatchEvent(new ViewStreamEvent(ViewStreamEvent.STOP));
}
}
}

View File

@ -0,0 +1,48 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.services.red5
{
import flash.events.Event;
public class ConnectionEvent extends Event {
public static const SCREENSHARE_CONNECTION_EVENT:String = "screenshare connection event";
public static const SUCCESS:String = "screenshare connection success";
public static const FAILED:String = "screenshare connection failed";
public static const CLOSED:String = "screenshare connection closed";
public static const REJECTED:String = "screenshare connection rejected";
public static const INVALIDAPP:String = "screenshare connection invalidApp";
public static const APPSHUTDOWN:String = "screenshare connection appShutdown";
public static const SECURITYERROR:String = "screenshare connection securityError";
public static const DISCONNECTED:String = "screenshare connection disconnected";
public static const CONNECTING:String = "screenshare connection connecting";
public static const CONNECTING_RETRY:String = "screenshare connection retry";
public static const CONNECTING_MAX_RETRY:String = "screenshare connection max retry";
public static const CHECK_FOR_DESKSHARE_STREAM:String = "screenshare connection check screenshare publishing";
public static const NO_DESKSHARE_STREAM:String = "screenshare connection screenshare publishing";
public static const FAIL_CHECK_FOR_DESKSHARE_STREAM:String = "screenshare connection failed check screenshare publishing";
public var retryAttempts:int = 0;
public function ConnectionEvent(event: String):void {
super(event, true, false);
}
}
}

View File

@ -0,0 +1,25 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.services.red5
{
public interface IMessageListener
{
function onMessage(messageName:String, message:Object):void;
}
}

View File

@ -0,0 +1,104 @@
/**
* WebMeeting open source conferencing system - http://www.speakserve.org/
*
* Copyright (c) 2013 SpeakServe Ltd. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* WebMeeting 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 WebMeeting; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.modules.screenshare.utils
{
import com.asfusion.mate.events.Dispatcher;
import flash.external.ExternalInterface;
import flash.utils.setTimeout;
import org.bigbluebutton.core.BBB;
import org.bigbluebutton.main.events.ClientStatusEvent;
import org.bigbluebutton.util.i18n.ResourceUtil;
public class JavaCheck {
public static function checkJava():String {
var dispatcher : Dispatcher = new Dispatcher();
var java_version:String = "1.7.0_51";
var xml:XML = BBB.initConfigManager().config.browserVersions;
if (xml.@java != undefined) {
java_version = xml.@java.toString();
}
try {
var javas : Array = JavaCheck.getJREs();
} catch ( e : Error ) {
dispatcher.dispatchEvent(new ClientStatusEvent(ClientStatusEvent.FAIL_MESSAGE_EVENT, ResourceUtil.getInstance().getString("bbb.clientstatus.java.title"), ResourceUtil.getInstance().getString("bbb.clientstatus.java.notdetected")));
return ResourceUtil.getInstance().getString("bbb.clientstatus.java.notdetected");
}
if (javas.length == 0) {
dispatcher.dispatchEvent(new ClientStatusEvent(ClientStatusEvent.FAIL_MESSAGE_EVENT, ResourceUtil.getInstance().getString("bbb.clientstatus.java.title"), ResourceUtil.getInstance().getString("bbb.clientstatus.java.notinstalled")));
return ResourceUtil.getInstance().getString("bbb.clientstatus.java.notinstalled");
}
var highestJava : String = javas[0];
for each (var java : String in javas) {
var highest : Array = highestJava.split(".");
var iter : Array = java.split(".");
if (Number(iter[0]) > Number(highest[0])) {
highestJava = java;
} else if (Number(iter[0]) == Number(highest[0]) && Number(iter[1]) > Number(highest[1])) {
highestJava = java;
} else if (Number(iter[0]) == Number(highest[0]) && Number(iter[1]) == Number(highest[1])) {
var iterMinor : Number = Number((iter[2] as String).split("_")[1]);
var highestMinor : Number = Number((highest[2] as String).split("_")[1]);
if (iterMinor > highestMinor)
{
highestJava = java;
}
}
}
var passedJava : Boolean = true;
var required : Array = java_version.split(".");
highest = highestJava.split(".");
if (Number(required[0]) > Number(highest[0])) {
passedJava = false;
} else if (Number(required[0]) == Number(highest[0]) && Number(required[1]) > Number(highest[1])) {
passedJava = false;
} else if (Number(required[0]) == Number(highest[0]) && Number(required[1]) == Number(highest[1])) {
var requiredMinor : Number = Number((required[2] as String).split("_")[1]);
var highestJavaMinor : Number = Number((highest[2] as String).split("_")[1]);
if (requiredMinor > highestJavaMinor)
{
passedJava = false;
}
}
if (!passedJava) {
dispatcher.dispatchEvent(new ClientStatusEvent(ClientStatusEvent.FAIL_MESSAGE_EVENT, ResourceUtil.getInstance().getString("bbb.clientstatus.java.title"), ResourceUtil.getInstance().getString("bbb.clientstatus.java.oldversion")));
return ResourceUtil.getInstance().getString("bbb.clientstatus.java.oldversion");
} else {
// Java success
return null;
}
}
private static function getJREs():Array{
var installedJREs:Array = ExternalInterface.call("deployJava.getJREs");
if (installedJREs == null) throw new Error("Javascript files not found.");
return installedJREs;
}
}
}

View File

@ -0,0 +1,448 @@
<?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 program is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-->
<dspub:MDIWindow
xmlns:mx="http://www.adobe.com/2006/mxml"
implements="org.bigbluebutton.common.IBbbModuleWindow"
xmlns:mate="http://mate.asfusion.com/"
xmlns:dspub="flexlib.mdi.containers.*"
backgroundColor="#C0C0C0"
initialize="init()"
creationComplete="onCreationComplete()"
verticalScrollPolicy="off" horizontalScrollPolicy="off"
width="365" height="350"
title="{ResourceUtil.getInstance().getString('bbb.screensharePublish.title')}"
resizable="false">
<mate:Listener type="{StartShareRequestSuccessEvent.START_SHARE_REQUEST_SUCCESS}" method="handleStartShareRequestSuccessEvent" />
<mate:Listener type="{ViewStreamEvent.START}" method="handleStartViewStreamEvent" />
<mate:Listener type="{MadePresenterEvent.SWITCH_TO_PRESENTER_MODE}" method="onChangedPresenter" />
<mate:Listener type="{MadePresenterEvent.SWITCH_TO_VIEWER_MODE}" method="onChangedPresenter" />
<mate:Listener type="{ViewStreamEvent.STOP}" method="closePublishWindow" />
<mate:Listener type="{LocaleChangeEvent.LOCALE_CHANGED}" method="localeChanged" />
<mate:Listener type="{StopSharingButtonEvent.STOP_SHARING}" method="stopSharingEvent" />
<mate:Listener type="{ShortcutEvent.REMOTE_FOCUS_DESKTOP}" method="remoteFocus" />
<mx:Script>
<![CDATA[
import com.asfusion.mate.events.Dispatcher;
import mx.core.UIComponent;
import org.bigbluebutton.common.Images;
import org.bigbluebutton.common.events.LocaleChangeEvent;
import org.bigbluebutton.core.UsersUtil;
import org.bigbluebutton.main.events.BBBEvent;
import org.bigbluebutton.main.events.MadePresenterEvent;
import org.bigbluebutton.main.events.ShortcutEvent;
import org.bigbluebutton.main.views.MainCanvas;
import org.bigbluebutton.modules.screenshare.events.RequestToStopSharing;
import org.bigbluebutton.modules.screenshare.events.ScreenshareAppletLaunchedEvent;
import org.bigbluebutton.modules.screenshare.events.ShareWindowEvent;
import org.bigbluebutton.modules.screenshare.events.StartShareRequestSuccessEvent;
import org.bigbluebutton.modules.screenshare.events.StopSharingButtonEvent;
import org.bigbluebutton.modules.screenshare.events.StreamEvent;
import org.bigbluebutton.modules.screenshare.events.ViewStreamEvent;
import org.bigbluebutton.modules.screenshare.model.ScreenshareModel;
import org.bigbluebutton.modules.screenshare.model.ScreenshareOptions;
import org.bigbluebutton.modules.screenshare.utils.JavaCheck;
import org.bigbluebutton.util.i18n.ResourceUtil;
private static const LOG:String = "SC::ScreensharePublishWIndow - ";
public static const SCALE:Number = 5;
private static const VID_HEIGHT_PAD:Number = 73;
private static const VID_WIDTH_PAD:Number = 6;
private var images:Images = new Images();
[Bindable] public var bbbLogo:Class = images.bbb_logo;
private var connection:NetConnection;
private var uri:String;
private var room:String;
private var sharingFullScreen:Boolean = false;
private var streaming:Boolean = false;
private var video:Video;
private var ns:NetStream;
[Bindable] private var videoHolder:UIComponent;
private var stream:String;
private var videoHeight:Number;
private var videoWidth:Number;
private var captureHeight:Number = Capabilities.screenResolutionY;
private var captureWidth:Number = Capabilities.screenResolutionX;
private var autoStart:Boolean = false;
private var globalDispatcher:Dispatcher = new Dispatcher();
private var javaTimer:Timer;
[Bindable] private var cursor:Sprite;
[Bindable] private var baseIndex:int;
[Bindable] private var dsOptions:ScreenshareOptions;
private function init():void {
dsOptions = new ScreenshareOptions();
baseIndex = dsOptions.baseTabIndex;
}
private function onCreationComplete():void {
windowControls.maximizeRestoreBtn.enabled = false;
cursor = new Sprite();
cursor.graphics.lineStyle(6, 0xFF0000, 0.6);
cursor.graphics.drawCircle(0,0,3);
var javaIssue:String = JavaCheck.checkJava();
if (isUsingLessThanChrome38OnMac()) {
setCurrentState("chromeOnMacWarningState");
}
else if (javaIssue != null) {
setCurrentState("javaIssueWarningState");
javaIssueWarningStateLbl.htmlText = javaIssue;
}
else {
setCurrentState("dispFullRegionControlBar");
}
resourcesChanged();
titleBarOverlay.tabIndex = baseIndex;
titleBarOverlay.focusEnabled = true;
minimizeBtn.tabIndex = baseIndex+1;
maximizeRestoreBtn.tabIndex = baseIndex+2;
closeBtn.tabIndex = baseIndex+3;
}
private function remoteFocus(e:ShortcutEvent):void{
focusManager.setFocus(minimizeBtn);
}
public function get defaultWidth():int{
return this.width;
}
public function get defaultHeight():int{
return this.height;
}
public function set defaultHeight(height:int):void{
this.height = height;
}
public function set defaultWidth(width:int):void{
this.width = width;
}
public function getPrefferedPosition():String{
return MainCanvas.DESKTOP_SHARING_PUBLISH;
}
/*
* Implement resizeable interface.
*/
public function resetWidthAndHeight():void{/* do nothing */}
public function initWindow(connection:NetConnection, uri:String, room:String, autoStart:Boolean, autoFullScreen:Boolean):void {
this.connection = connection;
this.uri = uri;
this.room = room;
this.autoStart = autoStart;
/*if(autoFullScreen)
shareScreen(true);*/
}
private function handleStartShareRequestSuccessEvent(event:StartShareRequestSuccessEvent):void {
}
public function shareScreen(fullScreen:Boolean):void {
trace(LOG + "Calling shareScreen");
btnFSPublish.enabled = false;
btnRegionPublish.enabled = false;
javaTimer = new Timer(1000, 1);
javaTimer.addEventListener(TimerEvent.TIMER, onJavaTimer);
javaTimer.start();
startSharing(connection, uri, room, fullScreen);
}
private function startSharing(connection:NetConnection, uri:String, room:String, fullScreen:Boolean):void {
var captureX:Number = 0;
var captureY:Number = 0;
sharingFullScreen = fullScreen;
var authToken:String = ScreenshareModel.getInstance().authToken;
var jnlp: String = ScreenshareModel.getInstance().jnlp;
trace(LOG + "StartScreensharing jnlp=" + jnlp + " token=" + authToken);
ExternalInterface.call("startScreensharing", jnlp, UsersUtil.getInternalMeetingID(), authToken, fullScreen);
}
public function stopSharing():void {
trace(LOG + "Calling stopSharing");
if (streaming) {
stopStream();
var streamEvent:RequestToStopSharing = new RequestToStopSharing();
dispatchEvent(streamEvent);
}
sharingFullScreen = false;
streaming = false;
closeWindow();
}
public function stopSharingEvent(evt:StopSharingButtonEvent):void{
if (streaming) {
stopStream();
var streamEvent:StreamEvent = new StreamEvent(StreamEvent.STOP);
dispatchEvent(streamEvent);
}
sharingFullScreen = false;
streaming = false;
closeWindow();
}
private function onJavaTimer(e:TimerEvent):void {
var browser:Array = ExternalInterface.call("determineBrowser");
if (browser[0] == "Chrome")
javaHelpArea.visible = javaHelpArea.includeInLayout = true;
}
private function handleStartViewStreamEvent(event:ViewStreamEvent):void{
trace(LOG + "handleStartViewStreamEvent");
var width: int = ScreenshareModel.getInstance().width;
var height: int = ScreenshareModel.getInstance().height;
var streamId: String = ScreenshareModel.getInstance().streamId;
startPreviewStream(connection, streamId, width, height);
}
private function startPreviewStream(nc:NetConnection, streamId:String, capWidth:Number, capHeight:Number):void{
removeJavaHelpArea();
trace(LOG + "Viewing stream =[" + streamId + "]");
streaming = true;
// Store capture dimensions so we can position cursor properly.
captureWidth = capWidth;
captureHeight = capHeight;
videoHolder = new UIComponent();
var vidW:Number = captureWidth;
var vidH:Number = captureHeight;
// Don't scale if capture dimension is smaller than window.
if((captureWidth > this.width - VID_WIDTH_PAD) && (captureHeight < this.height - VID_HEIGHT_PAD)){
vidW = this.width - VID_WIDTH_PAD;
vidH = (captureHeight / captureWidth) * vidW;
}
else if( ((captureWidth < this.width - VID_WIDTH_PAD) && (captureHeight > this.height - VID_HEIGHT_PAD))
|| ((captureWidth > this.width - VID_WIDTH_PAD) && (captureHeight > this.height - VID_HEIGHT_PAD)) ){
vidH = this.height - VID_HEIGHT_PAD;
vidW = (captureWidth / captureHeight) * vidH;
}
else{
vidW = captureWidth;
vidH = captureHeight;
}
trace("deskshare preview[" + captureWidth + "," + captureHeight + "][" + vidW + "," + vidH + "]");
video = new Video(vidW, vidH);
video.width = vidW;
video.height = vidH;
videoHolder.width = vidW;
videoHolder.height = vidH;
video.x = videoHolder.x = (this.width - VID_WIDTH_PAD - vidW) / 2;
video.y = videoHolder.y = (this.height - VID_HEIGHT_PAD - vidH) / 2;
videoHolder.addChild(video);
videoHolder.addChild(cursor);
cursor.visible = false;
this.addChild(videoHolder);
ns = new NetStream(nc);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
ns.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
ns.client = this;
ns.bufferTime = 0;
ns.receiveVideo(true);
ns.receiveAudio(false);
video.attachNetStream(ns);
ns.play(streamId);
btnClosePublish.enabled = true;
btnFSPublish.enabled = false;
btnRegionPublish.enabled = false;
}
public function onMetaData(info:Object):void{
trace("metadata: width=" + info.width + " height=" + info.height);
}
private function stopStream():void{
streaming = false;
captureHeight = Capabilities.screenResolutionY;
captureWidth = Capabilities.screenResolutionX;
ns.close();
}
private function onAsyncError(e:AsyncErrorEvent):void{
trace("VIdeoWindow::asyncerror " + e.toString());
}
private function onNetStatus(e:NetStatusEvent):void{
switch(e.info.code){
case "NetStream.Publish.Start":
trace("NetStream.Publish.Start for broadcast stream " + stream);
break;
case "NetStream.Play.UnpublishNotify":
trace("NetStream.Play.UnpublishNotify for broadcast stream " + stream);
stopSharing();
break;
case "NetStream.Play.Start":
trace("Netstatus: " + e.info.code);
globalDispatcher.dispatchEvent(new BBBEvent(BBBEvent.DESKSHARE_STARTED));
}
}
private function onChangedPresenter(e:Event):void{
stopSharing();
closeWindow();
}
private function closeWindow():void {
dispatchEvent(new ShareWindowEvent(ShareWindowEvent.CLOSE));
}
private function restartJava():void {
shareScreen(sharingFullScreen);
}
private function removeJavaHelpArea():void {
if (javaTimer && javaTimer.running) {
javaTimer.stop();
}
javaHelpArea.visible = javaHelpArea.includeInLayout = false;
}
/*
* Override the close handler. We want the Event Map to send a message to
* the MDIManager to close this window;
*/
override public function close(event:MouseEvent = null):void {
stopSharing();
closeWindow();
}
override protected function resourcesChanged():void{
super.resourcesChanged();
this.title = ResourceUtil.getInstance().getString('bbb.screensharePublish.title');
if (titleBarOverlay != null) {
titleBarOverlay.accessibilityName = ResourceUtil.getInstance().getString('bbb.screensharePublish.title');
}
if (windowControls != null) {
minimizeBtn.toolTip = ResourceUtil.getInstance().getString('bbb.screensharePublish.minimizeBtn.toolTip');
minimizeBtn.accessibilityName = ResourceUtil.getInstance().getString("bbb.screensharePublish.minimizeBtn.accessibilityName");
maximizeRestoreBtn.toolTip = ResourceUtil.getInstance().getString('bbb.screensharePublish.maximizeRestoreBtn.toolTip');
maximizeRestoreBtn.accessibilityName = ResourceUtil.getInstance().getString("bbb.screensharePublish.maximizeRestoreBtn.accessibilityName");
closeBtn.toolTip = ResourceUtil.getInstance().getString('bbb.screensharePublish.closeBtn.toolTip');
closeBtn.accessibilityName = ResourceUtil.getInstance().getString("bbb.screensharePublish.closeBtn.accessibilityName");
}
}
private function localeChanged(e:Event):void{
resourcesChanged();
}
private function closePublishWindow(event:ViewStreamEvent):void{
stopStream();
closeWindow();
}
private function isUsingLessThanChrome38OnMac():Boolean {
var browser:Array = ExternalInterface.call("determineBrowser");
return ((browser[0] == "Chrome") && (parseInt(browser[1]) <= 38) && (Capabilities.os.indexOf("Mac") >= 0));
}
]]>
</mx:Script>
<!--http://stackoverflow.com/questions/369120/why-does-mxstates-have-trouble-being-resolved-to-a-component-implementation-->
<mx:VBox id="javaHelpArea" includeInLayout="false" visible="false" height="100%" width="100%" verticalAlign="middle" horizontalAlign="center">
<mx:Text width="80%" textAlign="center" styleName="desktopShareTextStyle" text="{ResourceUtil.getInstance().getString('bbb.screensharePublish.chromeHint.title')}" />
<mx:Image id="javaHelpImg" styleName="chromeJavaHelpImage" source="{javaHelpImg.getStyle('imageSource')}" />
<mx:Text width="80%" textAlign="center" styleName="desktopShareTextStyle" text="{ResourceUtil.getInstance().getString('bbb.screensharePublish.chromeHint.message')}" />
</mx:VBox>
<dspub:states>
<mx:State name="dispFullRegionControlBar">
<mx:AddChild>
<mx:ControlBar id="fullRegionBottomBar">
<mx:VBox width="100%" height="100%" horizontalAlign="center">
<mx:HBox horizontalAlign="center">
<mx:Button id="btnFSPublish"
toolTip="{ResourceUtil.getInstance().getString('bbb.screensharePublish.fullscreen.tooltip')}"
label="{ResourceUtil.getInstance().getString('bbb.screensharePublish.fullscreen.label')}"
visible="true"
click="shareScreen(true)"
tabIndex="{baseIndex+4}"/>
<mx:Spacer width="100%"/>
<mx:Button id="btnClosePublish"
toolTip="{ResourceUtil.getInstance().getString('bbb.screensharePublish.stop.tooltip')}"
label="{ResourceUtil.getInstance().getString('bbb.screensharePublish.stop.label')}"
visible="true"
enabled="false"
click="stopSharing()"
tabIndex="{baseIndex+5}"/>
<mx:Spacer width="100%"/>
<mx:Button id="btnRegionPublish"
toolTip="{ResourceUtil.getInstance().getString('bbb.screensharePublish.region.tooltip')}"
label="{ResourceUtil.getInstance().getString('bbb.screensharePublish.region.label')}"
visible="true"
click="shareScreen(false)"
tabIndex="{baseIndex+6}"
focusEnabled="false"
tabEnabled="false"/>
<mx:Spacer width="100%"/>
</mx:HBox>
</mx:VBox>
</mx:ControlBar>
</mx:AddChild>
</mx:State>
<mx:State name="chromeOnMacWarningState">
<mx:AddChild>
<mx:VBox height="100%" width="100%" verticalAlign="middle" horizontalAlign="center">
<mx:Text id="chromeOnMacWarningLbl" width="80%" textAlign="center" styleName="desktopShareTextStyle"
text="{ResourceUtil.getInstance().getString('bbb.screensharePublish.chromeOnMacUnsupportedHint')}" />
</mx:VBox>
</mx:AddChild>
</mx:State>
<mx:State name="javaIssueWarningState">
<mx:AddChild>
<mx:VBox height="100%" width="100%" verticalAlign="middle" horizontalAlign="center">
<mx:Text id="javaIssueWarningStateLbl" width="80%" textAlign="center" styleName="desktopShareTextStyle" />
</mx:VBox>
</mx:AddChild>
</mx:State>
</dspub:states>
</dspub:MDIWindow>

View File

@ -0,0 +1,351 @@
<?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 program is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-->
<MDIWindow xmlns="flexlib.mdi.containers.*"
xmlns:mx="http://www.adobe.com/2006/mxml"
width="600" height="400"
initialize="init()"
creationComplete="onCreationComplete()"
implements="org.bigbluebutton.common.IBbbModuleWindow"
xmlns:mate="http://mate.asfusion.com/"
title="{ResourceUtil.getInstance().getString('bbb.screenshareView.title')}"
showCloseButton="false"
resize="fitToWindow()" >
<mate:Listener type="{ViewStreamEvent.STOP}" method="onStopViewStreamEvent" />
<mate:Listener type="{LocaleChangeEvent.LOCALE_CHANGED}" method="localeChanged" />
<mx:Script>
<![CDATA[
import com.asfusion.mate.events.Dispatcher;
import flexlib.mdi.events.MDIWindowEvent;
import mx.core.UIComponent;
import org.bigbluebutton.common.Images;
import org.bigbluebutton.common.events.LocaleChangeEvent;
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.main.api.JSLog;
import org.bigbluebutton.main.views.MainCanvas;
import org.bigbluebutton.modules.screenshare.events.CursorEvent;
import org.bigbluebutton.modules.screenshare.events.StartedViewingEvent;
import org.bigbluebutton.modules.screenshare.events.ViewStreamEvent;
import org.bigbluebutton.modules.screenshare.events.ViewWindowEvent;
import org.bigbluebutton.modules.screenshare.model.ScreenshareModel;
import org.bigbluebutton.modules.screenshare.model.ScreenshareOptions;
import org.bigbluebutton.util.i18n.ResourceUtil;
private static const LOG:String = "SC::ScreenshareViewWIndow - ";
private var screenHeight:Number = Capabilities.screenResolutionY;
private var screenWidth:Number = Capabilities.screenResolutionX;
private var images:Images = new Images();
[Bindable] public var fitToWidthIcon:Class = images.magnifier;
[Bindable] public var fitToActualSizeIcon:Class = images.mag_reset;
private var streamAvailable:Boolean = false;
private var video:Video;
private var ns:NetStream;
private var videoHolder:UIComponent = new UIComponent();
private var streamId:String;
private var videoHeight:Number = 1;
private var videoWidth:Number = 1;
private static const VIDEO_WIDTH_PADDING:int = 7;
private static const VIDEO_HEIGHT_PADDING:int = 65;
// The following code block is to deal with a bug in FLexLib
// with MDI windows not responding well to being maximized
private var savedWindowWidth:Number;
private var savedWindowHeight:Number;
private var savedX:Number;
private var savedY:Number;
private var isMaximized:Boolean = false;
private var connection:NetConnection;
[Bindable] private var baseIndex:int;
[Bindable] private var dsOptions:ScreenshareOptions;
private function init():void{
dsOptions = new ScreenshareOptions();
baseIndex = dsOptions.baseTabIndex;
}
private function onCreationComplete():void{
viewScreenshareStream();
videoHolder.addChild(video);
this.addChild(videoHolder);
videoHolder.percentWidth = 100;
videoHolder.percentHeight = 100;
addEventListener(MDIWindowEvent.RESIZE_END, onResizeEndEvent);
fitToActualSize();
maximize();
resourcesChanged();
titleBarOverlay.tabIndex = baseIndex;
minimizeBtn.tabIndex = baseIndex+1;
maximizeRestoreBtn.tabIndex = baseIndex+2;
closeBtn.tabIndex = baseIndex+3;
var logData:Object = new Object();
logData.width = videoWidth;
logData.height = videoHeight;
logData.streamId = streamId;
JSLog.debug(LOG + "onCreationComplete", logData);
}
private function onResizeEndEvent(event:MDIWindowEvent):void {
if (event.window == this && streamAvailable) {
fitToWindow();
}
}
public function startVideo(connection:NetConnection):void{
var logData:Object = new Object();
logData.width = videoWidth;
logData.height = videoHeight;
logData.streamId = streamId;
JSLog.debug(LOG + "startVideo", logData);
this.connection = connection;
}
private function viewScreenshareStream():void{
videoWidth = ScreenshareModel.getInstance().width;
videoHeight = ScreenshareModel.getInstance().height;
streamId = ScreenshareModel.getInstance().streamId;
var logData:Object = new Object();
logData.width = videoWidth;
logData.height = videoHeight;
logData.streamId = streamId;
JSLog.debug(LOG + "viewScreenshareStream Chrome", logData);
ns = new NetStream(connection);
ns.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
ns.client = this;
ns.bufferTime = 0;
ns.receiveVideo(true);
ns.receiveAudio(false);
video = new Video(videoWidth, videoHeight);
video.width = videoWidth;
video.height = videoHeight;
video.smoothing = true;
video.attachNetStream(ns);
ns.play(streamId);
this.title = "Viewing Remote Desktop";
streamAvailable = true;
fitToWindow();
}
public function onMetaData(info:Object):void{
trace("metadata: width=" + info.width + " height=" + info.height);
var logData:Object = new Object();
logData.width = info.width;
logData.height = info.height;
JSLog.debug(LOG + "onMetaData", logData);
}
protected function updateButtonsPosition():void {
if (this.width < bottomBar.width) {
bottomBar.visible = false;
}
if (bottomBar.visible == false) {
bottomBar.y = bottomBar.x = 0;
} else {
bottomBar.y = (this.height - bottomBar.height) / 2;
bottomBar.x = (this.width - bottomBar.width) / 2;
}
}
public function stopViewing():void {
ns.close();
closeWindow();
}
private function onStopViewStreamEvent(event:ViewStreamEvent):void {
stopViewing();
}
private function onAsyncError(e:AsyncErrorEvent):void{
trace(LOG + "asyncerror " + e.toString());
var logData:Object = new Object();
logData.error = e.toString();
JSLog.debug(LOG + "asyncerror ", logData);
}
private function onNetStatus(e:NetStatusEvent):void{
var logData:Object = new Object();
logData.stream = streamId;
switch(e.info.code){
case "NetStream.Play.Start":
trace(LOG + "NetStream.Publish.Start for broadcast stream " + streamId);
JSLog.debug(LOG + "NetStream.Publish.Start for broadcast stream ", logData);
var dispatcher: Dispatcher = new Dispatcher();
var viewEvent:StartedViewingEvent = new StartedViewingEvent(StartedViewingEvent.STARTED_VIEWING_EVENT);
viewEvent.stream = streamId;
dispatcher.dispatchEvent(viewEvent);
break;
case "NetStream.Play.UnpublishNotify":
trace(LOG + "NetStream.Play.UnpublishNotify for broadcast stream " + streamId);
JSLog.debug(LOG + "NetStream.Play.UnpublishNotify for broadcast stream ", logData);
stopViewing();
break;
}
}
public function getPrefferedPosition():String{
return MainCanvas.DESKTOP_SHARING_VIEW;
}
/**
* resizes the desktop sharing video to fit to this window
*/
private function fitToWindow():void{
if (!streamAvailable) return;
if (videoIsSmallerThanWindow()) {
fitWindowToVideo();
}
// Ignore if we are displaying the actual size of the video
if (! btnActualSize.selected) {
fitVideoToWindow();
}
}
private function fitVideoToWindow():void {
if (this.width < this.height) {
fitToWidthAndAdjustHeightToMaintainAspectRatio();
} else {
fitToHeightAndAdjustWidthToMaintainAspectRatio();
}
}
private function fitWindowToVideo():void {
video.width = videoWidth;
videoHolder.width = videoWidth;
video.height = videoHeight;
videoHolder.height = videoHeight;
this.height = videoHeight + VIDEO_HEIGHT_PADDING;
this.width = videoWidth + VIDEO_WIDTH_PADDING;
}
private function videoIsSmallerThanWindow():Boolean {
return (videoHeight < this.height) && (videoWidth < this.width);
}
private function fitToWidthAndAdjustHeightToMaintainAspectRatio():void {
video.width = this.width - VIDEO_WIDTH_PADDING;
videoHolder.width = video.width;
// Maintain aspect-ratio
video.height = (videoHeight * video.width) / videoWidth;
videoHolder.height = video.height;
this.height = video.height + VIDEO_HEIGHT_PADDING;
}
private function fitToHeightAndAdjustWidthToMaintainAspectRatio():void {
video.height = this.height - VIDEO_HEIGHT_PADDING;
videoHolder.height = video.height;
// Maintain aspect-ratio
video.width = (videoWidth * video.height) / videoHeight;
videoHolder.width = video.width;
this.width = video.width + VIDEO_WIDTH_PADDING;
}
/**
* resizes the desktop sharing video to actual video resolution
*/
private function fitToActualSize():void{
if (videoIsSmallerThanWindow()) {
fitWindowToVideo();
} else {
video.width = videoWidth;
videoHolder.width = videoWidth;
video.height = videoHeight;
videoHolder.height = videoHeight;
}
}
private function determineHowToDisplayVideo():void {
if (btnActualSize.selected) {
fitToActualSize();
btnActualSize.toolTip = ResourceUtil.getInstance().getString('bbb.screenshareView.fitToWindow');
btnActualSize.label = ResourceUtil.getInstance().getString('bbb.screenshareView.fitToWindow');
} else {
fitToWindow();
btnActualSize.toolTip = ResourceUtil.getInstance().getString('bbb.screenshareView.actualSize');
btnActualSize.label = ResourceUtil.getInstance().getString('bbb.screenshareView.actualSize');
}
}
private function closeWindow():void {
dispatchEvent(new ViewWindowEvent(ViewWindowEvent.CLOSE));
}
override protected function resourcesChanged():void{
super.resourcesChanged();
this.title = ResourceUtil.getInstance().getString('bbb.screenshareView.title');
if (windowControls != null) {
minimizeBtn.toolTip = ResourceUtil.getInstance().getString("bbb.window.minimizeBtn.toolTip");
minimizeBtn.accessibilityName = ResourceUtil.getInstance().getString("bbb.screenshareView.minimizeBtn.accessibilityName");
maximizeRestoreBtn.toolTip = ResourceUtil.getInstance().getString("bbb.window.maximizeRestoreBtn.toolTip");
maximizeRestoreBtn.accessibilityName = ResourceUtil.getInstance().getString("bbb.screenshareView.maximizeRestoreBtn.accessibilityName");
closeBtn.toolTip = ResourceUtil.getInstance().getString("bbb.window.closeBtn.toolTip");
closeBtn.accessibilityName = ResourceUtil.getInstance().getString("bbb.screenshareView.closeBtn.accessibilityName");
}
}
private function localeChanged(e:Event):void{
resourcesChanged();
}
]]>
</mx:Script>
<mx:HBox id="bottomBar" visible="true" height="30" horizontalAlign="center" paddingTop="0" paddingBottom="0" width="100%" >
<mx:Button id="btnActualSize" paddingTop="0" paddingBottom="0" styleName="deskshareControlButtonStyle"
toggle="true"
click="determineHowToDisplayVideo()"
selected="false"
height="90%"
label="{btnActualSize.selected ? ResourceUtil.getInstance().getString('bbb.screenshareView.fitToWindow') : ResourceUtil.getInstance().getString('bbb.screenshareView.actualSize')}"
toolTip="{btnActualSize.selected ? ResourceUtil.getInstance().getString('bbb.screenshareView.fitToWindow') : ResourceUtil.getInstance().getString('bbb.screenshareView.actualSize')}"
tabIndex="{baseIndex+4}"/>
</mx:HBox>
</MDIWindow>

View File

@ -0,0 +1,131 @@
<?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 program is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
Foundation; 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 BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-->
<mx:Button xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:mate="http://mate.asfusion.com/"
styleName="deskshareDefaultButtonStyle"
height="24"
toolTip="{ResourceUtil.getInstance().getString('bbb.toolbar.deskshare.toolTip.start')}"
click="requestToStarSharing()"
mouseOver = "mouseOverHandler(event)"
mouseOut = "mouseOutHandler(event)"
implements="org.bigbluebutton.common.IBbbToolbarComponent">
<mate:Listener type="{ShortcutEvent.SHARE_DESKTOP}" method="remoteClick" />
<mate:Listener type="{ShareWindowEvent.CLOSE}" method="closeFocus" />
<mx:Script>
<![CDATA[
import com.asfusion.mate.events.Dispatcher;
import org.bigbluebutton.main.events.ShortcutEvent;
import org.bigbluebutton.main.views.MainToolbar;
import org.bigbluebutton.modules.screenshare.events.RequestToStartSharing;
import org.bigbluebutton.modules.screenshare.events.RequestToStopSharing;
import org.bigbluebutton.modules.screenshare.events.ShareWindowEvent;
import org.bigbluebutton.util.i18n.ResourceUtil;
public const OFF_STATE:Number = 0;
public const ON_STATE:Number = 1;
public const STOP_SHARING:Number = 0;
public const START_SHARING:Number = 1;
private var _currentState:Number = OFF_STATE;
private var dispatcher:Dispatcher = new Dispatcher();
public function deskshareStatus(status:Number):void {
if(status == START_SHARING) {
_currentState = ON_STATE;
this.selected = true;
this.enabled = true;
this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.deskshare.toolTip.stop');
styleName="deskshareOnButtonStyle"
}
else {
_currentState = OFF_STATE;
this.selected = false;
this.enabled = true;
this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.deskshare.toolTip.start');
styleName="deskshareDefaultButtonStyle"
}
}
public function remoteClick(e:ShortcutEvent):void{
requestToStarSharing();
dispatchEvent(new ShortcutEvent(ShortcutEvent.REMOTE_FOCUS_DESKTOP));
}
private function requestToStarSharing():void {
if(_currentState == OFF_STATE) {
this.selected = true;
this.enabled = true;
this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.deskshare.toolTip.stop');
styleName="deskshareOnButtonStyle"
_currentState = ON_STATE;
dispatchEvent(new RequestToStartSharing());
}
else {
this.selected = false;
this.enabled = true;
this.toolTip = ResourceUtil.getInstance().getString('bbb.toolbar.deskshare.toolTip.start');
styleName="deskshareDefaultButtonStyle"
_currentState = ON_STATE;
dispatcher.dispatchEvent(new RequestToStopSharing());
}
}
//OLD - CAN BE DELETED
public function stopDeskshare():void {
styleName="deskshareDefaultButtonStyle"
}
private function mouseOverHandler(event:MouseEvent):void {
if(_currentState == ON_STATE)
styleName="deskshareOffButtonStyle"
else
styleName="deskshareOnButtonStyle"
}
private function mouseOutHandler(event:MouseEvent):void {
if(_currentState == ON_STATE)
styleName="deskshareOnButtonStyle"
else
styleName="deskshareDefaultButtonStyle"
}
public function getAlignment():String{
return MainToolbar.ALIGN_LEFT;
}
public function theory():String{
return "Screenshare button";
}
// Moves focus back to the toolbar button when the desktop sharing window closes, for accessibility
public function closeFocus(e:ShareWindowEvent):void{
this.setFocus();
}
]]>
</mx:Script>
</mx:Button>