diff --git a/bigbluebutton-client/.actionScriptProperties b/bigbluebutton-client/.actionScriptProperties index f961238f3def16abb982d3fa8cbf8ca1271ef40d..24eb9b380726d05b25fbe4c1365382d1aa0273c6 100755 --- a/bigbluebutton-client/.actionScriptProperties +++ b/bigbluebutton-client/.actionScriptProperties @@ -15,6 +15,7 @@ </compiler> <applications> <application path="BigBlueButton.mxml"/> + <application path="ScreenshareStandalone.mxml"/> </applications> <modules/> <workers/> diff --git a/bigbluebutton-client/branding/default/style/css/BBBDefault.css b/bigbluebutton-client/branding/default/style/css/BBBDefault.css index d67999954d4751d36b2a9f99c02103e1adc18bce..44862eb493be0b7d07acae249311eabdce576649 100755 --- a/bigbluebutton-client/branding/default/style/css/BBBDefault.css +++ b/bigbluebutton-client/branding/default/style/css/BBBDefault.css @@ -512,7 +512,7 @@ TitleWindow { } .chromeJavaHelpImage { - imageSource: Embed(source='assets/images/chromePluginBlocked.png'); + imageSource: Embed(source='assets/images/jnlp-run-chrome.png'); } .webcamSettingsWindowTitleStyle, .micSettingsWindowTitleStyle { diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/jnlp-run-chrome.png b/bigbluebutton-client/branding/default/style/css/assets/images/jnlp-run-chrome.png new file mode 100644 index 0000000000000000000000000000000000000000..33ab2ac4085fa3b40f79ee53a3207320cd006ba8 Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/jnlp-run-chrome.png differ diff --git a/bigbluebutton-client/build.xml b/bigbluebutton-client/build.xml index e1358dec712b012b5a89a3ac8d5c815e2c078287..ecddec11d362cc34e378addda18fdafded8482c0 100755 --- a/bigbluebutton-client/build.xml +++ b/bigbluebutton-client/build.xml @@ -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"/> diff --git a/bigbluebutton-client/locale/en_US/bbbResources.properties b/bigbluebutton-client/locale/en_US/bbbResources.properties index e190ea76da54d2a4d4bf20351802fd1efa77d532..3316378b4ade645647b7a40aac8e69494f0375fe 100755 --- a/bigbluebutton-client/locale/en_US/bbbResources.properties +++ b/bigbluebutton-client/locale/en_US/bbbResources.properties @@ -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 diff --git a/bigbluebutton-client/resources/config.xml.template b/bigbluebutton-client/resources/config.xml.template index 82ce7a363cf8fca6d8e8b27097d6b9f82f932149..f2df5d4c5ab962775eaa8df02b7eed13a786404b 100755 --- a/bigbluebutton-client/resources/config.xml.template +++ b/bigbluebutton-client/resources/config.xml.template @@ -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" diff --git a/bigbluebutton-client/resources/prod/BigBlueButton.html b/bigbluebutton-client/resources/prod/BigBlueButton.html index 11d299b705e80ec9c19fb346f03d04843e4c7864..1a6c2f77dddcc8df28c2a765cdd4d88c4767d70b 100755 --- a/bigbluebutton-client/resources/prod/BigBlueButton.html +++ b/bigbluebutton-client/resources/prod/BigBlueButton.html @@ -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> diff --git a/bigbluebutton-client/resources/prod/ScreenshareStandalone.html b/bigbluebutton-client/resources/prod/ScreenshareStandalone.html new file mode 100755 index 0000000000000000000000000000000000000000..cb5c9f48c2f1a85ddb2125569658d1d79525e78d --- /dev/null +++ b/bigbluebutton-client/resources/prod/ScreenshareStandalone.html @@ -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> diff --git a/bigbluebutton-client/resources/prod/lib/bbb_screenshare.js b/bigbluebutton-client/resources/prod/lib/bbb_screenshare.js new file mode 100644 index 0000000000000000000000000000000000000000..3797ed239c35c9d0d852e99409d74178e651bbec --- /dev/null +++ b/bigbluebutton-client/resources/prod/lib/bbb_screenshare.js @@ -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; +} diff --git a/bigbluebutton-client/src/ScreenshareModule.mxml b/bigbluebutton-client/src/ScreenshareModule.mxml new file mode 100755 index 0000000000000000000000000000000000000000..606745dfc9749cdf14e4bce53c1dcdc2f60ba8fa --- /dev/null +++ b/bigbluebutton-client/src/ScreenshareModule.mxml @@ -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> diff --git a/bigbluebutton-client/src/ScreenshareStandalone.mxml b/bigbluebutton-client/src/ScreenshareStandalone.mxml new file mode 100755 index 0000000000000000000000000000000000000000..c612a4968423290cb47b99fe625b821ff8f60647 --- /dev/null +++ b/bigbluebutton-client/src/ScreenshareStandalone.mxml @@ -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> diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/UsersUtil.as b/bigbluebutton-client/src/org/bigbluebutton/core/UsersUtil.as index b22c1017315a7e1df15bab306ae4bf69c7413ab0..59f17d5f1c2e6a0b423cc4a81f95f9fad9eb5142 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/core/UsersUtil.as +++ b/bigbluebutton-client/src/org/bigbluebutton/core/UsersUtil.as @@ -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(); } diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as old mode 100644 new mode 100755 index d1b16dad8663ce34f9366faa543194387cb233e5..bbce32837cb97f57192d20159ed8e0e968527001 --- a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as +++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as @@ -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"); diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/images/Cursor.png b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/images/Cursor.png new file mode 100755 index 0000000000000000000000000000000000000000..6e29c43729b8711191d7120348e15bbcfa236dd0 Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/images/Cursor.png differ diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/images/Cursor2.png b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/images/Cursor2.png new file mode 100755 index 0000000000000000000000000000000000000000..34322af4391a5c275bc878054f37ef6f9efb855d Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/images/Cursor2.png differ diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/images/cursor3.png b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/images/cursor3.png new file mode 100755 index 0000000000000000000000000000000000000000..c4c180383d8f15ef91e096b37290c1f770b9c746 Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/images/cursor3.png differ diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/images/cursor4.png b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/images/cursor4.png new file mode 100755 index 0000000000000000000000000000000000000000..44e22e16ad38641af8ffffbc18612a96d3162e19 Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/assets/images/cursor4.png differ diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/AppletStartedEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/AppletStartedEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..7d397a05b011b04bddb9328fb7da0c9c67ea8951 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/AppletStartedEvent.as @@ -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); + } + + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/CursorEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/CursorEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..32955021edb4da64df217ae6fd70cffef9a95f36 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/CursorEvent.as @@ -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); + } + + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/IsSharingScreenEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/IsSharingScreenEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..f8799a657eb2ea6f7bb091690a607134f5135e06 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/IsSharingScreenEvent.as @@ -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; + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ModuleEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ModuleEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..370694f7760ac3873252116599725daf1bde1b0b --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ModuleEvent.as @@ -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); + } + + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/RecordingStatusEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/RecordingStatusEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..9e710a34b3f8c7e9f3ec36857e92f34cb47ef970 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/RecordingStatusEvent.as @@ -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); + } + + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/RequestToStartSharing.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/RequestToStartSharing.as new file mode 100755 index 0000000000000000000000000000000000000000..36e9144c40ef3a91396c55f0005565fb46f55a8c --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/RequestToStartSharing.as @@ -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); + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/RequestToStopSharing.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/RequestToStopSharing.as new file mode 100755 index 0000000000000000000000000000000000000000..d5d5683eb7e2ec8e6f04819f06a34e87eeea1f39 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/RequestToStopSharing.as @@ -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); + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ScreenshareAppletLaunchedEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ScreenshareAppletLaunchedEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..913ff80c41156bc7b192ee7f65f449213a350a38 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ScreenshareAppletLaunchedEvent.as @@ -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); + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..4f07471be3060460ce18f1cb4394d10f0aee384b --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareEvent.as @@ -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); + } + + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareStartRequestResponseEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareStartRequestResponseEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..d7a43ca7597eeadcba62b34e3a2733adc9fda849 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareStartRequestResponseEvent.as @@ -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; + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareStartedEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareStartedEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..86c2a01b7c1f593eb25a07dd5ce7b941d17783bb --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareStartedEvent.as @@ -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; + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareStoppedEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareStoppedEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..80394165e6a00ae896fc86e24b727a932fa582eb --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareStoppedEvent.as @@ -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; + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareWindowEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareWindowEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..72c5447f930f6b3a90a5f189b320c33c8d4190f4 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ShareWindowEvent.as @@ -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); + } + + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StartShareRequestFailedEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StartShareRequestFailedEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..40a9a15004238fa0315e44827e2c23b46bf9f24b --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StartShareRequestFailedEvent.as @@ -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); + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StartShareRequestSuccessEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StartShareRequestSuccessEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..862a852e602056f5940bd1f35a2472e4a23a2403 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StartShareRequestSuccessEvent.as @@ -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; + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StartedViewingEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StartedViewingEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..cc9d73b80f5864e545edc5dd30bc1cdd785497c0 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StartedViewingEvent.as @@ -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); + } + + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StopSharingButtonEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StopSharingButtonEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..69ef5b12a57e7bf10bcade3eae892a8d5957f80e --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StopSharingButtonEvent.as @@ -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); + } + + } +} diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StreamEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StreamEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..2defbb494f3b4354318c5609d299ace461342b78 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StreamEvent.as @@ -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); + } + + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StreamStartedEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StreamStartedEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..b589922ffe3ff79f71d3d1c895f4fc19e96c44ae --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StreamStartedEvent.as @@ -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; + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StreamStoppedEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StreamStoppedEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..3a73ce6c81ab96baec5686aa1f226333685f3d9c --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/StreamStoppedEvent.as @@ -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; + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ViewStreamEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ViewStreamEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..f68bf73998a7e7706ca7363a1cee57190dd54877 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ViewStreamEvent.as @@ -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); + } + + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ViewWindowEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ViewWindowEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..60d39bbf671f88d73a23ed67d42055ca4347cd4d --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/events/ViewWindowEvent.as @@ -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); + } + + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/PublishWindowManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/PublishWindowManager.as new file mode 100755 index 0000000000000000000000000000000000000000..d446b5cdf7e15c7a0ddaa11487f13a4238105afb --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/PublishWindowManager.as @@ -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); + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/ScreenshareManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/ScreenshareManager.as new file mode 100755 index 0000000000000000000000000000000000000000..6bf523ca7ad20b8681e3d84f3368e2558a33b54e --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/ScreenshareManager.as @@ -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); + } + + + } +} diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/ToolbarButtonManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/ToolbarButtonManager.as new file mode 100755 index 0000000000000000000000000000000000000000..71cd46cc7586a55fe9bac4cb33f3fdb284defdb2 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/ToolbarButtonManager.as @@ -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); + } + } +} diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/ViewerWindowManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/ViewerWindowManager.as new file mode 100755 index 0000000000000000000000000000000000000000..804ebe1231e8c24403465b26dd3cae7718ea0588 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/managers/ViewerWindowManager.as @@ -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; + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/maps/ScreenshareEventMap.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/maps/ScreenshareEventMap.mxml new file mode 100755 index 0000000000000000000000000000000000000000..617f6d9726a3c642b922b2b1495e89ca54c6845c --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/maps/ScreenshareEventMap.mxml @@ -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> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/model/ScreenshareModel.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/model/ScreenshareModel.as new file mode 100755 index 0000000000000000000000000000000000000000..3a9c75d1780d539f74ac52a4c0af7b60d74551fb --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/model/ScreenshareModel.as @@ -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{} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/model/ScreenshareOptions.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/model/ScreenshareOptions.as new file mode 100755 index 0000000000000000000000000000000000000000..da7e8f3fc51b8b5db12909ee5cde5555f0c598d6 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/model/ScreenshareOptions.as @@ -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; + } + } + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/model/ScreenshareStream.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/model/ScreenshareStream.as new file mode 100755 index 0000000000000000000000000000000000000000..1bc8529fbade1f6930a563f495abaae6de4d7d0d --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/model/ScreenshareStream.as @@ -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; + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/MessageReceiver.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/MessageReceiver.as new file mode 100755 index 0000000000000000000000000000000000000000..f73ac5901016335a8b62bb6536812cf8b59eb5d8 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/MessageReceiver.as @@ -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); + } + } + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/MessageSender.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/MessageSender.as new file mode 100755 index 0000000000000000000000000000000000000000..a76fe86ec31ee290a93950d54c3f4516ecef6564 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/MessageSender.as @@ -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); + } + + + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/ScreenshareService.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/ScreenshareService.as new file mode 100755 index 0000000000000000000000000000000000000000..b189930c3c361ea587d32469c48b75ab4acaf5b3 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/ScreenshareService.as @@ -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); + } + + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/red5/Connection.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/red5/Connection.as new file mode 100755 index 0000000000000000000000000000000000000000..a6bb09e6c9489ea4557f6697b971575a61003764 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/red5/Connection.as @@ -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)); + } + + + } +} diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/red5/ConnectionEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/red5/ConnectionEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..02821391e82a03daedf8a1dc04ed810f46d48111 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/red5/ConnectionEvent.as @@ -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); + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/red5/IMessageListener.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/red5/IMessageListener.as new file mode 100755 index 0000000000000000000000000000000000000000..4a5b955822756dda834ae72a3f429fc06842a5aa --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/red5/IMessageListener.as @@ -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; + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/utils/JavaCheck.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/utils/JavaCheck.as new file mode 100755 index 0000000000000000000000000000000000000000..ae92afe72a2deee445014b56f295ade1d6c408b8 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/utils/JavaCheck.as @@ -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; + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreensharePublishWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreensharePublishWindow.mxml new file mode 100755 index 0000000000000000000000000000000000000000..3ed641f5b4bbd5c843b0d31112df0641efd866fb --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreensharePublishWindow.mxml @@ -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> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreenshareViewWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreenshareViewWindow.mxml new file mode 100755 index 0000000000000000000000000000000000000000..b34b79205aa483e5c5c1353ea785334f50c63686 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ScreenshareViewWindow.mxml @@ -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> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ToolbarButton.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ToolbarButton.mxml new file mode 100755 index 0000000000000000000000000000000000000000..98a489bfb7c738eece104a3c1dbc19461e4c17a4 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/view/components/ToolbarButton.mxml @@ -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>