diff --git a/bigbluebutton-client/.actionScriptProperties b/bigbluebutton-client/.actionScriptProperties index 85fe3888f119b39e49dfc8d72cf1874d73788584..76f856227212d5808adfc66d268d7806f6a1365f 100755 --- a/bigbluebutton-client/.actionScriptProperties +++ b/bigbluebutton-client/.actionScriptProperties @@ -26,6 +26,7 @@ <applications> <application path="src/main.mxml"/> <application path="MessagingUnitTests.mxml"/> + <application path="org/bigbluebutton/modules/settings/SettingsPanel.mxml"/> <application path="BigBlueButton.mxml"/> <application path="BigBlueButtonUnitTests.mxml"/> <application path="DeskshareStandalone.mxml"/> @@ -45,12 +46,10 @@ <module application="src/BigBlueButton.mxml" destPath="BreakoutModule.swf" optimize="true" sourcePath="src/BreakoutModule.mxml"/> <module application="src/BigBlueButton.mxml" destPath="SharedNotesModule.swf" optimize="true" sourcePath="src/SharedNotesModule.mxml"/> <module application="src/BigBlueButton.mxml" destPath="ClassroomAudioModule.swf" optimize="true" sourcePath="src/ClassroomAudioModule.mxml"/> + <module application="src/BigBlueButton.mxml" destPath="SettingsModule.swf" optimize="true" sourcePath="src/SettingsModule.mxml"/> </modules> <buildCSSFiles> <buildCSSFileEntry destPath="bin" sourcePath="src/branding/css/logo_basic.css"/> <buildCSSFileEntry destPath="bin" sourcePath="src/branding/css/theme.css"/> </buildCSSFiles> </actionScriptProperties> - - - diff --git a/bigbluebutton-client/.flexProperties b/bigbluebutton-client/.flexProperties index e755f4434677941788ac612dc147949d680fc159..afb930671bcf77c496834ff0e190ffdebf61e78a 100755 --- a/bigbluebutton-client/.flexProperties +++ b/bigbluebutton-client/.flexProperties @@ -1,5 +1,2 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <flexProperties enableServiceManager="false" flexServerFeatures="0" flexServerType="0" toolCompile="true" useServerFlexSDK="false" version="1"/> - - - diff --git a/bigbluebutton-client/locale/en_US/bbbResources.properties b/bigbluebutton-client/locale/en_US/bbbResources.properties index 1cabc8de0482639d6d33121cf75352a361f5b7e9..b413893f29e03fd514052ee9a564166b564765e2 100755 --- a/bigbluebutton-client/locale/en_US/bbbResources.properties +++ b/bigbluebutton-client/locale/en_US/bbbResources.properties @@ -20,6 +20,8 @@ bbb.oldlocalewindow.windowTitle=Warning: Old Language Translations bbb.mainToolbar.helpBtn = Help bbb.mainToolbar.logoutBtn = Logout bbb.mainToolbar.logoutBtn.toolTip = Log out +bbb.mainToolbar.settingsBtn = Settings +bbb.mainToolbar.settingsBtn.toolTip = Open Settings ###### modules ###### diff --git a/bigbluebutton-client/resources/config.xml.template b/bigbluebutton-client/resources/config.xml.template index 424452dedac018305c8dca682ff5ea2b8a81168a..360dc84c338f7b0c5927eff855f6b52a4edf6220 100755 --- a/bigbluebutton-client/resources/config.xml.template +++ b/bigbluebutton-client/resources/config.xml.template @@ -10,7 +10,15 @@ <debug showDebugWindow="false" /> <modules> - + + <module name="SettingsModule" url="SettingsModule.swf?v=VERSION" + voice="rtmp://demo.bigbluebutton.org/video" + video="rtmp://demo.bigbluebutton.org/video" + deskshare="rtmp://demo.bigbluebutton.org/deskShare" + java_required="1.6.0_22" + flash_required="10,0,0" + </module> + <module name="ChatModule" url="ChatModule.swf?v=VERSION" uri="rtmp://HOST/bigbluebutton" dependsOn="ViewersModule" diff --git a/bigbluebutton-client/src/SettingsModule.mxml b/bigbluebutton-client/src/SettingsModule.mxml new file mode 100755 index 0000000000000000000000000000000000000000..e9293487dbdec8301b4ad7d6faa2b20bf19ea819 --- /dev/null +++ b/bigbluebutton-client/src/SettingsModule.mxml @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- +BigBlueButton - http://www.bigbluebutton.org + +Copyright (c) 2008-2009 by respective authors (see below). All rights reserved. + +BigBlueButton 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 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, If not, see <http://www.gnu.org/licenses/>. + +$Id: $ +--> + +<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" + implements="org.bigbluebutton.common.IBigBlueButtonModule" + creationComplete="init()" xmlns:mate="http://mate.asfusion.com/"> + + <mx:Script> + <![CDATA[ + import com.asfusion.mate.events.Dispatcher; + + import mx.core.Application; + import mx.managers.PopUpManager; + + import org.bigbluebutton.common.LogUtil; + import org.bigbluebutton.main.events.SettingsEvent; + import org.bigbluebutton.modules.settings.SettingsPanel; + import org.bigbluebutton.modules.settings.util.Requirements; + + private var _moduleName:String = "Settings Module"; + private var _attributes:Object; + + private var globalDispatcher:Dispatcher; + + private function init():void{ + LogUtil.debug("SettingsModule::init"); + } + + public function get moduleName():String { + return _moduleName; + } + + public function get uri():String { + return _attributes.uri + "/" + _attributes.room; + } + + public function get username():String { + return _attributes.username; + } + + public function get connection():NetConnection { + return _attributes.connection; + } + + 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 { + _attributes = attributes; + globalDispatcher = new Dispatcher(); + Requirements.setRequirements(attributes); + + //var startEvent:StartWhiteboardModuleEvent = new StartWhiteboardModuleEvent(); + //startEvent.attributes = attributes; + //globalDispatcher.dispatchEvent(startEvent); + + } + + public function stop():void { + //globalDispatcher.dispatchEvent(new StopWhiteboardModuleEvent(StopWhiteboardModuleEvent.STOP_HIGHLIGHTER_MODULE_EVENT)); + } + + private function openSettingsPanel(e:SettingsEvent):void{ + var settingsPanel:SettingsPanel = SettingsPanel(PopUpManager.createPopUp(Application.application as DisplayObject, SettingsPanel, true)); + + var point1:Point = new Point(); + // Calculate position of TitleWindow in Application's coordinates. + settingsPanel.x = Application.application.width/2 - settingsPanel.width/2; + settingsPanel.y = Application.application.height/2 - settingsPanel.height/2 + } + ]]> + </mx:Script> + + <mate:Listener type="{SettingsEvent.OPEN_SETTINGS_PANEL}" method="openSettingsPanel" /> +</mx:Module> diff --git a/bigbluebutton-client/src/WhiteboardModule.mxml b/bigbluebutton-client/src/WhiteboardModule.mxml index be0aa0bdd0c276ec8fde2c49feada10b813eb0eb..97cc1645c79791186a4764b7ec7d6c9767831779 100755 --- a/bigbluebutton-client/src/WhiteboardModule.mxml +++ b/bigbluebutton-client/src/WhiteboardModule.mxml @@ -44,10 +44,6 @@ } public function get uri():String { - if (_attributes.mode == "PLAYBACK") { - return _attributes.uri + "/" + _attributes.playbackRoom; - } - return _attributes.uri + "/" + _attributes.room; } @@ -58,16 +54,6 @@ public function get connection():NetConnection { return _attributes.connection; } - - public function get mode():String { - if (_attributes.mode == null) { - //_attributes.mode = "PLAYBACK" - _attributes.mode = "LIVE" - LogUtil.debug('Setting HighlighterModule mode: ' + _attributes.mode); - } - LogUtil.debug('HighlighterModule mode: ' + _attributes.mode); - return _attributes.mode; - } public function get userid():Number { return _attributes.userid as Number; diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/events/SettingsEvent.as b/bigbluebutton-client/src/org/bigbluebutton/main/events/SettingsEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..1042e052036794bb5bd05a40851f5ca6dc9a245a --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/main/events/SettingsEvent.as @@ -0,0 +1,14 @@ +package org.bigbluebutton.main.events +{ + import flash.events.Event; + + public class SettingsEvent extends Event + { + public static const OPEN_SETTINGS_PANEL:String = "OPEN_SETTINGS_PANEL"; + + public function SettingsEvent(type:String) + { + super(type, true, false); + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/modules/ModuleDescriptor.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/modules/ModuleDescriptor.as index 852a9511c616dc9ab8311ea3d8861a91512aa503..3dd111ab29c8033f7fdf30a48d09a8fe13af020f 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/main/model/modules/ModuleDescriptor.as +++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/modules/ModuleDescriptor.as @@ -145,6 +145,8 @@ package org.bigbluebutton.main.model.modules } public function useProtocol(protocol:String):void { + if (_attributes.uri == null) return; + _attributes.uri = _attributes.uri.replace(/rtmp:/gi, protocol + ":"); LogUtil.debug(_attributes.name + " uri = " + _attributes.uri); } diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/MainToolbar.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/MainToolbar.mxml index 9a0df14838519045381dbd58d2a30f7010d9f9a4..a904056091cf86dfc2a0224f6184984f92c977fc 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/main/views/MainToolbar.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/MainToolbar.mxml @@ -45,6 +45,7 @@ import org.bigbluebutton.main.events.BBBEvent; import org.bigbluebutton.main.events.ConfigEvent; import org.bigbluebutton.main.events.LogoutEvent; + import org.bigbluebutton.main.events.SettingsEvent; import org.bigbluebutton.main.events.SuccessfulLoginEvent; import org.bigbluebutton.main.model.users.events.ConnectionFailedEvent; import org.bigbluebutton.util.i18n.ResourceUtil; @@ -119,6 +120,11 @@ d.dispatchEvent(e); } + private function openSettings():void{ + var d:Dispatcher = new Dispatcher(); + d.dispatchEvent(new SettingsEvent(SettingsEvent.OPEN_SETTINGS_PANEL)); + } + ]]> </mx:Script> <mx:HBox id="addedBtns"> @@ -126,6 +132,8 @@ <mx:Spacer width="100%"/> <views:LanguageSelector id="langSelector" visible="false" /> <mx:LinkButton label="{ResourceUtil.getInstance().getString('bbb.mainToolbar.helpBtn')}" click="onHelpButtonClicked()"/> + <mx:Button label="{ResourceUtil.getInstance().getString('bbb.mainToolbar.settingsBtn')}" id="btnSettings" + toolTip="{ResourceUtil.getInstance().getString('bbb.mainToolbar.settingsBtn.toolTip')}" right="10" click="openSettings()"/> <mx:Button label="{ResourceUtil.getInstance().getString('bbb.mainToolbar.logoutBtn')}" id="btnLogout" toolTip="{ResourceUtil.getInstance().getString('bbb.mainToolbar.logoutBtn.toolTip')}" right="10" click="doLogout()"/> </mx:ApplicationControlBar> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/SettingsPanel.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/SettingsPanel.mxml new file mode 100755 index 0000000000000000000000000000000000000000..9722152be97ebaef6861ce94af66fe4f5a9a369e --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/SettingsPanel.mxml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="utf-8"?> +<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="955" minHeight="600" xmlns:checkers="checkers.*" + creationComplete="init();" xmlns:uihelpers="uihelpers.*" xmlns:checkers1="org.bigbluebutton.modules.settings.checkers.*" + xmlns:uihelpers1="org.bigbluebutton.modules.settings.uihelpers.*" showCloseButton="true" close="onSaveClose()"> + + <mx:Script> + <![CDATA[ + import mx.managers.PopUpManager; + import mx.rpc.events.HeaderEvent; + + import org.bigbluebutton.modules.settings.uihelpers.JavaOKEvent; + import org.bigbluebutton.modules.settings.uihelpers.WarningEvent; + import org.bigbluebutton.modules.settings.util.Requirements; + + private var isJavaOk:Boolean = false; + + private function init():void{ + requirementsLoaded(); + setText(); + } + + private function setText():void{ + txtInstructions.text = "To start the test, click the Start button bellow. Accept the Flash prompt that asks you " + + "for camera permissions. If you can see yourself and hear yourself, your browser has been " + + "set up correctly. Other potentials issues are shown bellow. Click on each to find a possible" + + " solution."; + } + + private function requirementsLoaded():void{ + webcamCheck.addEventListener(WarningEvent.WARNING_EVENT, onWarningEvent); + micCheck.addEventListener(WarningEvent.WARNING_EVENT, onWarningEvent); + systemCheck.addEventListener(WarningEvent.WARNING_EVENT, onWarningEvent); + systemCheck.addEventListener(JavaOKEvent.JAVA_A_OK, onJavaOKEvent); + + systemCheck.init(); + } + + private function onWarningEvent(e:WarningEvent):void{ + warningsList.addWarning(e); + } + + private function onJavaOKEvent(e:JavaOKEvent):void{ + isJavaOk = true; + } + + private function startTest():void{ + webcamCheck.init(); + micCheck.init(); + deskshareCheck.startTheApplet(); + + btnStart.enabled = false; + } + + private function onSaveClose(e:Event = null):void{ + PopUpManager.removePopUp(this); + } + + ]]> + </mx:Script> + <mx:VBox x="338" y="10"> + <checkers1:WebcamChecker id="webcamCheck" /> + <checkers1:MicChecker id="micCheck" /> + </mx:VBox> + <checkers1:SystemCheck id="systemCheck" width="52" height="11" x="10" y="494"/> + <checkers1:DeskShareChecker id="deskshareCheck" x="540" y="20" /> + <uihelpers1:WarningsList id="warningsList" x="10" y="201" width="300" height="195"/> + <mx:Text x="10" y="10" width="300" + id="txtInstructions" height="108" paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10" + selectable="false"/> + <mx:Button id="btnStart" x="21" y="144" label="Start Test" click="startTest()"/> + + <mx:Button id="btnSaveClose" label="Save Settings and Close" click="onSaveClose()" bottom="15" horizontalCenter="0" /> + +</mx:TitleWindow> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/checkers/DeskShareChecker.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/checkers/DeskShareChecker.mxml new file mode 100755 index 0000000000000000000000000000000000000000..d385739724143fd205b7c8d56bafeed61bac7b8b --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/checkers/DeskShareChecker.mxml @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="utf-8"?> +<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" creationComplete="onCreationComplete()"> + + <mx:Script> + <![CDATA[ + import mx.core.UIComponent; + + import org.bigbluebutton.modules.settings.connectors.DeskShareConnector; + import org.bigbluebutton.modules.settings.util.Requirements; + + private var deskshareConnector:DeskShareConnector; + private var ns:NetStream; + private var video:Video; + private var videoHolder:UIComponent; + + private function onCreationComplete():void{ + deskshareConnector = new DeskShareConnector(appletStarted, startViewing, stopViewing); + } + + /** + * Call only if the Java check passed. Otherwise launching the applet definitely won't work. + */ + public function startTheApplet():void{ + ExternalInterface.call("startApplet", getCaptureServerUri(), deskshareConnector.room, true); + } + + private function appletStarted(videoWidth:Number, videoHeight:Number):void{ + startVideo(deskshareConnector.nc, deskshareConnector.room, videoWidth, videoHeight); + } + + private function startViewing(videoWidth:Number, videoHeight:Number):void{ + startVideo(deskshareConnector.nc, deskshareConnector.room, videoWidth, videoHeight); + } + + private function stopViewing():void{ + ns.close(); + } + + 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.width = this.height * (videoWidth/videoHeight); + + videoHolder = new UIComponent(); + calculateDisplayDimensions(video, videoHolder); + videoHolder.addChild(video); + //videoHolder.addChild(cursor); + //videoHolder.addChild(cursorImg); + centerVideo(); + ns.play(stream); + this.addChild(videoHolder); + } + + private function onAsyncError(e:AsyncErrorEvent):void{ + trace("VIdeoWindow::asyncerror " + e.toString()); + } + + private function onNetStatus(e:NetStatusEvent):void{ + switch(e.info.code){ + case "NetStream.Play.Start": + trace("NetStream.Publish.Start for deskshare broadcast test stream "); + trace("Dispatching start viewing event"); + deskshareConnector.sendStartedViewingNotification(); + break; + case "NetStream.Play.UnpublishNotify": + trace("NetStream.Play.UnpublishNotify for deskshare broadcast test stream "); + stopViewing(); + break; + } + } + + private function centerVideo():void { + videoHolder.x = this.width/2 - video.width/2; + videoHolder.y = this.height/2 - video.height/2; + } + + private function calculateDisplayDimensions(video:Video, videoHolder:UIComponent):void { + if (videoIsSmallerThanDisplay(video, videoHolder)) { + videoHolder.width = video.width; + videoHolder.height = video.height; + return; + } + + if (this.width < this.height) { + fitToWidthAndAdjustHeightToMaintainAspectRatio(); + } else { + fitToHeightAndAdjustWidthToMaintainAspectRatio(); + } + } + + private function videoIsSmallerThanDisplay(video:Video, videoHolder:UIComponent):Boolean { + return (video.height < this.height) && (video.width < this.width); + } + + private function fitToWidthAndAdjustHeightToMaintainAspectRatio():void { + var aspectRatio:Number = video.height/video.width; + video.width = this.width; + videoHolder.width = this.height; + // Maintain aspect-ratio + video.height = this.width * aspectRatio; + videoHolder.height = video.height; + } + + private function fitToHeightAndAdjustWidthToMaintainAspectRatio():void { + var aspectRatio:Number = video.width/video.height; + video.height = this.height; + videoHolder.height = video.height; + // Maintain aspect-ratio + video.width = aspectRatio * this.height; + videoHolder.width = video.width; + } + + public function getCaptureServerUri():String{ + var uri:String = Requirements.bbb_deskshare_url; + uri = uri.split("/")[2]; + return uri; + } + ]]> + </mx:Script> + +</mx:VBox> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/checkers/MicChecker.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/checkers/MicChecker.mxml new file mode 100755 index 0000000000000000000000000000000000000000..9dfc2747a5c52211e36b33f048aa79b9ac7317ec --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/checkers/MicChecker.mxml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="180" height="250" + paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" + horizontalAlign="center" visible="false" > + <mx:Script> + <![CDATA[ + import org.bigbluebutton.modules.settings.connectors.AudioConnector; + import org.bigbluebutton.modules.settings.util.PersistUserPreferences; + + private var timer:Timer; + private var mic:Microphone; + + private var audioConnector:AudioConnector; + + public function init():void{ + this.visible = true; + initMic(); + audioConnector = new AudioConnector(mic); + + timer = new Timer(100); + timer.addEventListener(TimerEvent.TIMER, updateMicLevel); + timer.start(); + } + + private function initMic():void{ + mic = Microphone.getMicrophone(); + if (mic == null) return; + + sldVolume.value = mic.gain; + } + + public function saveCurrentMic():void{ + PersistUserPreferences.saveMicrophonePreference(Microphone.names[cmbMicSelector.selectedIndex]); + } + + private function updateMicLevel(e:TimerEvent):void{ + micLevel.setProgress(mic.activityLevel,100); + } + + private function changeMic():void{ + mic = Microphone.getMicrophone(cmbMicSelector.selectedIndex); + if (mic == null) return; + + saveCurrentMic(); + } + + private function changeVolume():void{ + mic.gain = sldVolume.value; + PersistUserPreferences.saveMicrophoneGain(mic.gain); + } + ]]> + </mx:Script> + + <mx:ProgressBar id="micLevel" minimum="0" maximum="100" label="Microphone Activity" labelPlacement="top" + direction="right" mode="manual" visible="true" width="120"/> + <mx:HSlider id="sldVolume" minimum="0" maximum="100" change="changeVolume()" labels="[silent, loud]" /> + <mx:Label text="Adjust Volume" /> + <mx:ComboBox id="cmbMicSelector" dataProvider="{Microphone.names}" change="changeMic()" textAlign="left" width="150" /> +</mx:VBox> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/checkers/SystemCheck.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/checkers/SystemCheck.mxml new file mode 100755 index 0000000000000000000000000000000000000000..1924e486ea304d3ec394cd69a0f6b4629b3bee12 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/checkers/SystemCheck.mxml @@ -0,0 +1,156 @@ +<?xml version="1.0" encoding="utf-8"?> +<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" visible="false" > + <mx:Script> + <![CDATA[ + import flash.net.navigateToURL; + + import mx.core.Application; + import mx.managers.PopUpManager; + + import org.bigbluebutton.modules.settings.connectors.AppsConnector; + import org.bigbluebutton.modules.settings.uihelpers.JavaOKEvent; + import org.bigbluebutton.modules.settings.uihelpers.WarningEvent; + import org.bigbluebutton.modules.settings.util.JavaCheck; + import org.bigbluebutton.modules.settings.util.Requirements; + + public function init():void{ + checkFlash(); + checkOS(); + checkJava(); + } + + private function checkFlash():void{ + var flashVersion:String = Capabilities.version; + + var flashVersions:Array = (Capabilities.version.split(" ")[1] as String).split(","); + var flashRequired:Array = Requirements.flash_required_version.split(","); + + trace("version is: " + flashVersions); + trace("required is " + flashRequired); + + for (var i:Number = 0; i< flashRequired.length; i++){ + if (Number(flashRequired[i]) > Number(flashVersions[i])) showFlashError(flashVersion, Requirements.flash_required_version); + } + + } + + private function checkOS():void{ + trace("Operating System: " + Capabilities.os); + var os:Array = Capabilities.os.split(" "); + //Check for this bug: http://reviews.cnet.com/8301-13727_7-20022842-263.html + //Fix is to download new flash player 10.2 or above + if (os[0] == "Mac" && os[1] == "OS" && os[2] == "10.6.5"){ + showMacOS1065iSightError(); + } + } + + private function checkJava():void{ + var javas:Array = JavaCheck.getJREs(); + + if (javas.length == 0) showFlashError("NO JAVA INSTALLED", Requirements.java_required_version); + + trace("Java version required is: " + Requirements.java_required_version); + trace("Java versions installed: "); + var highestJava:String = javas[0]; + for each (var java:String in javas){ + trace("Found java " + java); + 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 = Requirements.java_required_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) showJavaError(highestJava, Requirements.java_required_version); + else sendJavaOK(); + } + + private function checkBBBApps():void{ + var appsConnector:AppsConnector = new AppsConnector(); + } + + private function sendJavaOK():void{ + dispatchEvent(new JavaOKEvent(JavaOKEvent.JAVA_A_OK)); + } + + private function showJavaError(hasVersion:String, needsVersion:String):void{ + var e:WarningEvent = new WarningEvent(WarningEvent.WARNING_EVENT); + e.warningLabel = "Java version error"; + e.warningText = javaError(hasVersion, needsVersion); + e.optionalCommandText = "Install newest Java"; + e.optionalCallbackFunction = installNewestJava; + dispatchEvent(e); + } + + private function installNewestJava():void{ + JavaCheck.installLatestJRE(); + } + + private function showFlashError(hasVersion:String, needsVersion:String):void{ + var e:WarningEvent = new WarningEvent(WarningEvent.WARNING_EVENT); + e.warningLabel = "Flash version error"; + e.warningText = flashError(hasVersion, needsVersion); + e.optionalCommandText = "Install newest Flash"; + e.optionalCallbackFunction = installNewestFlash; + dispatchEvent(e); + } + + private function installNewestFlash():void{ + navigateToURL(new URLRequest("http://get.adobe.com/flashplayer/"), "_self"); + } + + private function showMacOS1065iSightError():void{ + var e:WarningEvent = new WarningEvent(WarningEvent.WARNING_EVENT); + e.warningLabel = "iSight camera error"; + e.warningText = iSightErrorOSX1065(); + e.optionalCommandText = "Install Flash 10.2 RC2"; + e.optionalCallbackFunction = installFlash102RC2; + dispatchEvent(e); + } + + private function installFlash102RC2():void{ + navigateToURL(new URLRequest("http://labs.adobe.com/downloads/flashplayer10.html"), "_self"); + } + + private static function iSightErrorOSX1065():String{ + return "If you have problems with your iSight camera, it may be because you are running OS X 10.6.5, which is known" + + " to have a problem with Flash capturing video from the iSight camera. \n" + + "To correct this, click on the link bellow to install a newer version of Flash player,"+ + " or update your Mac to the newest version"; + } + + private static function javaError(hasVersion:String, needsVersion:String):String{ + return "You have Java " + hasVersion + " installed, but you need at least version " + needsVersion + + " to use the BigBlueButton desktop sharing feature. Click on the button bellow to install the newest" + + " Java JRE version."; + } + + private static function flashError(hasVersion:String, needsVersion:String):String{ + return "You have Flash " + hasVersion + " installed, but you need at least version " + needsVersion + + " to run BigBlueButton properly. Click on the button bellow to install the newest" + + " Adobe Flash version."; + } + ]]> + </mx:Script> + +</mx:VBox> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/checkers/WebcamChecker.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/checkers/WebcamChecker.mxml new file mode 100755 index 0000000000000000000000000000000000000000..3a6832cda037aaa58090c9df5bde7bb115ce2e68 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/checkers/WebcamChecker.mxml @@ -0,0 +1,156 @@ +<?xml version="1.0" encoding="utf-8"?> +<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="180" height="180" + paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" + visible="false"> + <mx:Script> + <![CDATA[ + import mx.core.Application; + import mx.managers.PopUpManager; + + import org.bigbluebutton.modules.settings.connectors.VideoConnector; + import org.bigbluebutton.modules.settings.uihelpers.WarningEvent; + import org.bigbluebutton.modules.settings.util.PersistUserPreferences; + import org.bigbluebutton.modules.settings.util.Requirements; + + private var video:Video; + private var camera:Camera; + + [Bindable] private var camWidth:Number = 160; + [Bindable] private var camHeight:Number = 120; + private var quality:Number = 0; + + private var videoConnector:VideoConnector; + private var ns:NetStream; + + public function init():void{ + this.visible = true; + this.videoConnector = new VideoConnector(onNetStatus); + + var isMac:Boolean = checkIfMacCamera(); + if (isMac) checkIfGoogleTalkPluginInstalled(); + } + + public function saveCurrentWebcam():void{ + PersistUserPreferences.saveWebcamPreference(Camera.names[cmbCameraSelector.selectedIndex]); + } + + private function checkIfMacCamera():Boolean{ + for (var i:int = 0; i<Camera.names.length; i++){ + if (Camera.names[i] == "USB Video Class Video" || Camera.names[i] == "Built-in iSight") { + /** + * Set as default for Macs + */ + cmbCameraSelector.selectedIndex = i; + return true; + } + } + return false; + } + + private function checkIfGoogleTalkPluginInstalled():void{ + for (var i:int = 0; i<Camera.names.length; i++){ + if (Camera.names[i] == "Google Camera Adapter 1" || Camera.names[i] == "Google Camera Adapter 0") { + showGoogleAdapterError(); + break; + } + } + } + + private function showCamera():void{ + camera = Camera.getCamera(cmbCameraSelector.selectedIndex.toString()); + if (camera == null) return; + + camera.setKeyFrameInterval(5); + camera.setMode(camWidth,camHeight,15); + camera.setQuality(0,quality); + + //The following few lines will just show the camera locally captured. What we want to do is stream it + /*video = new Video(camWidth, camHeight); + //Next two lines may seem redundant but they're not. Do not delete. They force the video to proper width & height + video.width = camWidth; + video.height = camHeight; + video.attachCamera(camera); + videoHolder.addChild(video);*/ + + videoConnector.connectVideo(camera, onNetStatus); + saveCurrentWebcam(); + + } + + public function onNetStatus(e:NetStatusEvent):void{ + trace("WebcamChecker::onNetStatus - " + e.info.code); + switch(e.info.code){ + case VideoConnector.CONNECT_SUCCESS: + showCamera(); + break; + case VideoConnector.NETSTREAM_PUBLISH: + startVideo(); + break; + case VideoConnector.CONNECT_FAILED: + showConnectionError(); + break; + case VideoConnector.CONNECT_REJECTED: + //showConnectionError(); + break; + case VideoConnector.CONNECT_CLOSED: + showConnectionError(); + break + default: + break; + } + } + + private function startVideo():void{ + ns = new NetStream(videoConnector.connection); + ns.client = this; + ns.bufferTime = 0; + ns.receiveVideo(true); + ns.receiveAudio(false); + + video = new Video(camWidth, camHeight); + video.width = camWidth; + video.height = camHeight; + video.attachNetStream(ns); + videoHolder.addChild(video); + ns.play(videoConnector.streamName); + } + + private function showGoogleAdapterError():void{ + var e:WarningEvent = new WarningEvent(WarningEvent.WARNING_EVENT); + e.warningLabel = "Google Camera Adapter Error"; + e.warningText = googleAdapterError(); + dispatchEvent(e); + } + + private function showConnectionError():void{ + var e:WarningEvent = new WarningEvent(WarningEvent.WARNING_EVENT); + e.warningLabel = "Connection Error"; + e.warningText = connectionError(Requirements.bbb_video_url); + dispatchEvent(e); + } + + private static function googleAdapterError():String{ + return "It seems like you have Google Voice and Video plugin installed. " + + "This plugin interferes with normal functioning of the Webcams on Macs with certain Flash versions. \n\n" + + "To fix this problem: \n" + + "- If you are using Google Chrome, try using Safari instead. \n" + + "Or, you can uninstall the Google Voice and Video plugin. To do this: \n" + + "- Go to /Library/Application Support/Google/ \n" + + "- You will see 'GoogleVoiceAndVideoUninstaller.app'. \n" + + "- Close all browser windows and then open this app."; + } + + private static function connectionError(serverUrl:String):String{ + return "The connection failed while trying to check video connectivity with the " + + "server at " + serverUrl + ". Please contact your server administrator."; + } + + ]]> + </mx:Script> + + <mx:UIComponent id="videoHolder" width="{camWidth}" height="{camHeight}" /> + <mx:HBox horizontalAlign="center" verticalAlign="middle" width="100%"> + <mx:ComboBox id="cmbCameraSelector" dataProvider="{Camera.names}" y="250" width="150" + change="showCamera()" textAlign="left"/> + </mx:HBox> +</mx:VBox> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/connectors/AppsConnector.as b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/connectors/AppsConnector.as new file mode 100755 index 0000000000000000000000000000000000000000..f25f61da29f3dc2d71a510df77daadedf621c9cb --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/connectors/AppsConnector.as @@ -0,0 +1,27 @@ +/** + * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ + * + * Copyright (c) 2010 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 2.1 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.settings.connectors +{ + public class AppsConnector + { + public function AppsConnector() + { + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/connectors/AudioConnector.as b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/connectors/AudioConnector.as new file mode 100755 index 0000000000000000000000000000000000000000..894e317b8343fc78fe0bb4723660183e62fcbd93 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/connectors/AudioConnector.as @@ -0,0 +1,132 @@ +/** + * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ + * + * Copyright (c) 2010 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 2.1 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.settings.connectors +{ + import flash.events.AsyncErrorEvent; + import flash.events.IOErrorEvent; + import flash.events.NetStatusEvent; + import flash.events.SecurityErrorEvent; + import flash.media.Microphone; + import flash.media.SoundCodec; + import flash.net.NetConnection; + import flash.net.NetStream; + + import mx.controls.Alert; + + import org.bigbluebutton.modules.settings.util.Requirements; + + public class AudioConnector + { + public static const CONNECT_SUCCESS:String = "NetConnection.Connect.Success"; + public static const CONNECT_FAILED:String = "NetConnection.Connect.Failed"; + public static const CONNECT_CLOSED:String = "NetConnection.Connect.Closed"; + public static const INVALID_APP:String = "NetConnection.Connect.InvalidApp"; + public static const APP_SHUTDOWN:String = "NetConnection.Connect.AppShutDown"; + public static const CONNECT_REJECTED:String = "NetConnection.Connect.Rejected"; + + private var audioCodec:String = "SPEEX"; + + private var connection:NetConnection; + private var outgoingStream:NetStream; + private var incomingStream:NetStream; + + private var streamName:String; + + private var mic:Microphone; + + public function AudioConnector(mic:Microphone) + { + this.mic = mic; + + connection = new NetConnection(); + connection.client = this; + connection.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus); + connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError); + connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError); + connection.addEventListener(IOErrorEvent.IO_ERROR, onIOError); + connection.connect(Requirements.bbb_voice_url); + } + + private function onNetStatus(e:NetStatusEvent):void{ + switch(e.info.code){ + case CONNECT_SUCCESS: + connectAudio(); + break; + case CONNECT_FAILED: + trace("AudioConnector::onNetStatus - connection to Audio App failed"); + break; + case CONNECT_CLOSED: + trace("AudioConnector::onNetStatus - connection to Audio App closed"); + break; + case CONNECT_REJECTED: + trace("AudioConnector::onNetStatus - connection to Audio App rejected"); + break; + default: + trace("AudioConnector::onNetStatus - something else happened: " + e.info.code); + break; + } + } + + private function onAsyncError(e:AsyncErrorEvent):void{ + trace("AudioConnector::onAsyncError - an async error occured on the audio connection"); + } + + private function onSecurityError(e:SecurityErrorEvent):void{ + trace("AudioConnector::onSecurityError - a security error occured on the audio connection"); + } + + private function onIOError(e:IOErrorEvent):void{ + trace("AudioConnector::onIOError - an IO error occured on the audio connection"); + } + + private function connectAudio():void{ + outgoingStream = new NetStream(connection); + outgoingStream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus); + + streamName = Math.random().toString(); + + setupMicrophone(); + outgoingStream.attachAudio(mic); + outgoingStream.publish(streamName, "live"); + } + + public function changeMic(mic:Microphone):void{ + this.mic = mic; + setupMicrophone(); + outgoingStream.attachAudio(mic); + } + + private function setupMicrophone():void { + mic.setUseEchoSuppression(true); + //TODO Set loopBack to false once this is connected to the Asterisk/Freeswitch echo application + mic.setLoopBack(true); + mic.setSilenceLevel(0,20000); + if (audioCodec == "SPEEX") { + mic.encodeQuality = 6; + mic.codec = SoundCodec.SPEEX; + mic.framesPerPacket = 1; + mic.rate = 16; + } else { + mic.codec = SoundCodec.NELLYMOSER; + mic.rate = 8; + } + mic.gain = 60; + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/connectors/DeskShareConnector.as b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/connectors/DeskShareConnector.as new file mode 100755 index 0000000000000000000000000000000000000000..bdb117cf89bde9190fc711117e29f4c55900aa57 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/connectors/DeskShareConnector.as @@ -0,0 +1,248 @@ +/** + * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ + * + * Copyright (c) 2010 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 2.1 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.settings.connectors +{ + import flash.events.AsyncErrorEvent; + import flash.events.IOErrorEvent; + import flash.events.NetStatusEvent; + import flash.events.SecurityErrorEvent; + import flash.net.NetConnection; + import flash.net.Responder; + import flash.net.SharedObject; + + import org.bigbluebutton.modules.settings.util.Requirements; + + /** + * The DeskShareProxy communicates with the Red5 deskShare server application + * @author Snap + * + */ + public class DeskShareConnector + { + public static const CONNECT_SUCCESS:String = "NetConnection.Connect.Success"; + public static const CONNECT_FAILED:String = "NetConnection.Connect.Failed"; + public static const CONNECT_CLOSED:String = "NetConnection.Connect.Closed"; + public static const INVALID_APP:String = "NetConnection.Connect.InvalidApp"; + public static const APP_SHUTDOWN:String = "NetConnection.Connect.AppShutDown"; + public static const CONNECT_REJECTED:String = "NetConnection.Connect.Rejected"; + public static const NETSTREAM_PUBLISH:String = "NetStream.Publish.Start"; + + public var nc:NetConnection; + private var deskSO:SharedObject; + private var responder:Responder; + + private var width:Number; + private var height:Number; + private var uri:String; + + public var room:String = Math.random().toString();; + + private var appletStartedCallback:Function; + private var startViewingCallback:Function; + private var stopViewingCallback:Function; + + public function DeskShareConnector(appletStartedCallback:Function, startViewingCallback:Function, stopViewingCallback:Function) + { + this.appletStartedCallback = appletStartedCallback; + this.startViewingCallback = startViewingCallback; + this.stopViewingCallback = stopViewingCallback; + + connect(); + } + + public function connect():void { + this.uri = Requirements.bbb_deskshare_url + "/" + this.room; + trace("Deskshare Service connecting to " + uri); + nc = new NetConnection() + nc.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus); + nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError); + nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError); + nc.addEventListener(IOErrorEvent.IO_ERROR, onIOError); + nc.connect(uri); + + responder = new Responder( + function(result:Object):void{ + if (result != null && (result.publishing as Boolean)){ + width = result.width as Number; + height = result.height as Number; + trace("Desk Share stream is streaming [" + width + "," + height + "]"); + + startViewingCallback(width, height); + } else { + trace("No deskshare stream being published"); + } + }, + function(status:Object):void{ + trace("Error while trying to call remote mathod on server"); + } + ); + } + + public function disconnect():void{ + if (nc != null) nc.close(); + } + + private function onNetStatus(e:NetStatusEvent):void{ + switch(e.info.code){ + case CONNECT_SUCCESS: + connectionSuccessHandler(); + break; + case CONNECT_FAILED: + trace("VideoConnector::onNetStatus - connection to Video App failed"); + break; + case CONNECT_CLOSED: + trace("VideoConnector::onNetStatus - connection to Video App closed"); + break; + case CONNECT_REJECTED: + trace("VideoConnector::onNetStatus - connection to Video App rejected"); + break; + case NETSTREAM_PUBLISH: + + break; + default: + trace("VideoConnector::onNetStatus - something else happened: " + e.info.code); + break; + } + } + + private function onAsyncError(e:AsyncErrorEvent):void{ + trace("VideoConnector::onAsyncError - an async error occured on the video connection"); + } + + private function onSecurityError(e:SecurityErrorEvent):void{ + trace("VideoConnector::onSecurityError - a security error occured on the video connection"); + } + + private function onIOError(e:IOErrorEvent):void{ + trace("VideoConnector::onIOError - an IO error occured on the video connection"); + } + + private function connectionSuccessHandler():void{ + trace("Successully connection to " + uri); + deskSO = SharedObject.getRemote("deskSO", uri, false); + deskSO.client = this; + deskSO.connect(nc); + + checkIfStreamIsPublishing(); + } + + public function getConnection():NetConnection{ + return nc; + } + + /** + * Called by server when client connects. + */ + public function onBWDone():void{ + // do nothing + } + + /** + * 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("Got applet started"); + + appletStartedCallback(videoWidth, videoHeight); + } + + /** + * 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){ + trace("error while trying to send start viewing notification"); + } + } + + public function sendStartedViewingNotification():void{ + trace("Sending start viewing to server"); + nc.call("deskshare.startedToViewStream", null); + } + + /** + * 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("startViewing invoked by server"); + + startViewingCallback(videoWidth, videoHeight); + } + + /** + * Sends a notification through the server to all the participants in the room to stop viewing the stream + * + */ + public function sendStopViewingNotification():void{ + trace("Sending stop viewing notification to other clients."); + try{ + deskSO.send("stopViewing"); + } catch(e:Error){ + trace("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("Received dekskshareStreamStopped"); + + stopViewingCallback(); + } + + 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); + } + + /** + * Check if anybody is publishing the stream for this room + * This method is useful for clients which have joined a room where somebody is already publishing + * + */ + private function checkIfStreamIsPublishing():void{ + trace("checking if desk share stream is publishing"); + nc.call("deskshare.checkIfStreamIsPublishing", responder); + } + + public function calculateEncodingDimensions(captureWidth:Number, captureHeight:Number):void{ + height = captureHeight; + width = captureWidth; + } + + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/connectors/VideoConnector.as b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/connectors/VideoConnector.as new file mode 100755 index 0000000000000000000000000000000000000000..e3983b51f6b108f28e548e015b90cef837c6f501 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/connectors/VideoConnector.as @@ -0,0 +1,119 @@ +/** + * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ + * + * Copyright (c) 2010 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 2.1 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.settings.connectors +{ + import flash.events.AsyncErrorEvent; + import flash.events.IOErrorEvent; + import flash.events.NetStatusEvent; + import flash.events.SecurityErrorEvent; + import flash.media.Camera; + import flash.media.Video; + import flash.net.NetConnection; + import flash.net.NetStream; + + import org.bigbluebutton.modules.settings.util.Requirements; + + public class VideoConnector + { + public static const CONNECT_SUCCESS:String = "NetConnection.Connect.Success"; + public static const CONNECT_FAILED:String = "NetConnection.Connect.Failed"; + public static const CONNECT_CLOSED:String = "NetConnection.Connect.Closed"; + public static const INVALID_APP:String = "NetConnection.Connect.InvalidApp"; + public static const APP_SHUTDOWN:String = "NetConnection.Connect.AppShutDown"; + public static const CONNECT_REJECTED:String = "NetConnection.Connect.Rejected"; + public static const NETSTREAM_PUBLISH:String = "NetStream.Publish.Start"; + + public var connection:NetConnection; + private var outgoingStream:NetStream; + private var incomingStream:NetStream; + + private var camera:Camera; + private var streamListener:Function; + + public var streamName:String; + + public function VideoConnector(connectionListener:Function) + { + connection = new NetConnection(); + connection.client = this; + connection.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus); + connection.addEventListener(NetStatusEvent.NET_STATUS, connectionListener); + connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError); + connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError); + connection.addEventListener(IOErrorEvent.IO_ERROR, onIOError); + + connectToServer(); + } + + public function connectToServer():void{ + connection.connect(Requirements.bbb_video_url); + } + + private function onNetStatus(e:NetStatusEvent):void{ + switch(e.info.code){ + case CONNECT_SUCCESS: + //connectVideo(); + break; + case CONNECT_FAILED: + trace("VideoConnector::onNetStatus - connection to Video App failed"); + break; + case CONNECT_CLOSED: + trace("VideoConnector::onNetStatus - connection to Video App closed"); + break; + case CONNECT_REJECTED: + trace("VideoConnector::onNetStatus - connection to Video App rejected"); + break; + case NETSTREAM_PUBLISH: + + break; + default: + trace("VideoConnector::onNetStatus - something else happened: " + e.info.code); + break; + } + } + + private function onAsyncError(e:AsyncErrorEvent):void{ + trace("VideoConnector::onAsyncError - an async error occured on the video connection"); + } + + private function onSecurityError(e:SecurityErrorEvent):void{ + trace("VideoConnector::onSecurityError - a security error occured on the video connection"); + } + + private function onIOError(e:IOErrorEvent):void{ + trace("VideoConnector::onIOError - an IO error occured on the video connection"); + } + + public function connectVideo(camera:Camera, streamListener:Function):void{ + outgoingStream = new NetStream(connection); + outgoingStream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus); + outgoingStream.addEventListener(NetStatusEvent.NET_STATUS, streamListener); + + streamName = Math.random().toString(); + + outgoingStream.attachCamera(camera); + outgoingStream.publish(streamName); + } + + public function changeCamera(camera:Camera):void{ + this.camera = camera; + outgoingStream.attachCamera(camera); + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/JavaOKEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/JavaOKEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..a122842d95e5f683d690179ccf9a9061f3bdbe7f --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/JavaOKEvent.as @@ -0,0 +1,14 @@ +package org.bigbluebutton.modules.settings.uihelpers +{ + import flash.events.Event; + + public class JavaOKEvent extends Event + { + public static const JAVA_A_OK:String = "Java is alright, sometimes"; + + public function JavaOKEvent(type:String) + { + super(type, true, false); + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/UserAlert.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/UserAlert.mxml new file mode 100644 index 0000000000000000000000000000000000000000..7487e9cbd4911b365ba60a9382d34035c7690bd0 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/UserAlert.mxml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="330"> + <mx:Script> + <![CDATA[ + import mx.managers.PopUpManager; + + private var callback:Function; + + public function setAlert(text:String, optionalButtonLabel:String = null, optionalButtonCallback:Function = null):void{ + txtAlert.htmlText = text; + if (optionalButtonLabel != null) { + btnOptionalAction.label = optionalButtonLabel; + btnOptionalAction.visible = true; + } + if (optionalButtonCallback != null) callback = optionalButtonCallback; + } + + public function closePopUp():void{ + PopUpManager.removePopUp(this); + } + + private function onOptionalButtonClick():void{ + callback(); + } + ]]> + </mx:Script> + + <mx:VBox horizontalAlign="center" width="100%" height="100%"> + <mx:Label text="Warning" fontSize="24" height="10%" color="red" /> + <mx:Text id="txtAlert" width="100%" height="65%" paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10" /> + <mx:Button id="btnOptionalAction" click="onOptionalButtonClick()" label="" visible="false" /> + <mx:Button id="btnClose" label="Close this Warning" click="closePopUp()" /> + </mx:VBox> + +</mx:TitleWindow> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/WarningEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/WarningEvent.as new file mode 100755 index 0000000000000000000000000000000000000000..affb6240f7256113161a69defa2cb264043f9be6 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/WarningEvent.as @@ -0,0 +1,19 @@ +package org.bigbluebutton.modules.settings.uihelpers +{ + import flash.events.Event; + + public class WarningEvent extends Event + { + public static const WARNING_EVENT:String = "BBB_CHECKER_WARNING"; + + public var warningLabel:String; + public var warningText:String; + public var optionalCommandText:String; + public var optionalCallbackFunction:Function; + + public function WarningEvent(type:String) + { + super(type, true, false); + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/WarningItem.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/WarningItem.mxml new file mode 100644 index 0000000000000000000000000000000000000000..98c3c9634fd300409830734dbe4894bdcebd6014 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/WarningItem.mxml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<mx:Button xmlns:mx="http://www.adobe.com/2006/mxml" width="250" + click="showWarning()" textAlign="left" > + <mx:Script> + <![CDATA[ + import mx.core.Application; + import mx.managers.PopUpManager; + + private var warningLabel:String; + private var warningText:String + private var optionalLabel:String; + private var optionalCallback:Function; + + public function setWarning(e:WarningEvent):void{ + this.warningLabel = e.warningLabel; + this.warningText = e.warningText; + this.optionalLabel = e.optionalCommandText; + this.optionalCallback = e.optionalCallbackFunction; + this.label = warningLabel; + } + + private function showWarning():void{ + var userAlert:UserAlert = UserAlert(PopUpManager.createPopUp(this.parent, UserAlert, true)); + userAlert.setAlert(warningText, optionalLabel, optionalCallback); + + userAlert.x = Application.application.width/2 - userAlert.width/2; + userAlert.y = Application.application.height/2 - userAlert.height/2; + } + ]]> + </mx:Script> + +</mx:Button> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/WarningsList.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/WarningsList.mxml new file mode 100644 index 0000000000000000000000000000000000000000..6acb4e762cf3e23c515e050721f69036995b436c --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/uihelpers/WarningsList.mxml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="300" height="300" + paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10"> + <mx:Script> + <![CDATA[ + + public function addWarning(e:WarningEvent):void{ + //Remove the No Issues label if an issue comes in. + if (lblNoIssues.visible){ + //here i'm just using visible as a flag so I don't have to create another local variable. + lblNoIssues.visible = false; + this.removeChild(lblNoIssues); + } + var warningItem:WarningItem = new WarningItem(); + this.addChild(warningItem); + warningItem.setWarning(e); + } + + ]]> + </mx:Script> + + <mx:Label text="Possible Issues:" /> + <mx:Label id="lblNoIssues" text="No outstanding issues have been detected." /> +</mx:VBox> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/util/FlashCheck.as b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/util/FlashCheck.as new file mode 100755 index 0000000000000000000000000000000000000000..ed97c8b6c22c1911d01ea1cedf2e7271d652b963 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/util/FlashCheck.as @@ -0,0 +1,9 @@ +package org.bigbluebutton.modules.settings.util +{ + public class FlashCheck + { + public function FlashCheck() + { + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/util/JavaCheck.as b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/util/JavaCheck.as new file mode 100755 index 0000000000000000000000000000000000000000..b5c2692b352ce710fcf9351b5e34cbf5cf1e3bef --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/util/JavaCheck.as @@ -0,0 +1,97 @@ +package org.bigbluebutton.modules.settings.util +{ + import flash.external.ExternalInterface; + + public class JavaCheck + { + public static function createWebStartLaunchButton(jnlp:String, minimumVersion:String):void{ + var response:Object = ExternalInterface.call("deployJava.createWebStartLaunchButton", jnlp, minimumVersion); + + if (response == null) throw new Error("Javascript files not found."); + } + + public static function createWebStartLaunchButtonEx(jnlp:String, minimumVersion:String):void{ + var response:Object = ExternalInterface.call("deployJava.createWebStartLaunchButtonEx", jnlp, minimumVersion); + + if (response == null) throw new Error("Javascript files not found."); + } + + public static function getBrowser():String{ + var browser:String = ExternalInterface.call("deployJava.getBrowser"); + + if (browser == null) throw new Error("Javascript files not found."); + + return browser; + } + + public static function getJREs():Array{ + var installedJREs:Array = ExternalInterface.call("deployJava.getJREs"); + + if (installedJREs == null) throw new Error("Javascript files not found."); + + return installedJREs; + } + + public static function installJRE(requestVersion:String):void{ + var response:Object = ExternalInterface.call("deployJava.installJRE", requestVersion); + + if (response == null) throw new Error("Javascript files not found."); + } + + public static function installLatestJRE():void{ + var response:Object = ExternalInterface.call("deployJava.installLatestJRE"); + + if (response == null) throw new Error("Javascript files not found."); + } + + public static function isPlugin2():Boolean{ + var plugin2:String = ExternalInterface.call("deployJava.isPlugin2"); + + if (plugin2 == null) throw new Error("Javascript files not found."); + + if (plugin2 == "true") return true; + else return false; + } + + public static function isWebStartInstalled(minimumVersion:String):Boolean{ + var webstartInstalled:String = ExternalInterface.call("deployJava.isWebStartInstalled", minimumVersion); + + if (webstartInstalled == null) throw new Error("Javascript files not found."); + + if (webstartInstalled == "true") return true; + else return false; + } + + public static function runApplet(attributes:Object, parameters:Object, minimumVersion:String):void{ + var response:Object = ExternalInterface.call("deployJava.runApplet", attributes, parameters, minimumVersion); + + if (response == null) throw new Error("Javascript files not found."); + } + + public static function setAdditionalPackages(packageList:Object):void{ + var response:Object = ExternalInterface.call("deployJava.setAdditionalPackages", packageList); + + if (response == null) throw new Error("Javascript files not found."); + } + + public static function setInstallerType(type:String):void{ + var response:Object = ExternalInterface.call("deployJava.setInstallerType", type); + + if (response == null) throw new Error("Javascript files not found."); + } + + public static function versionCheck(version:String):String{ + var version:String = ExternalInterface.call("deployJava.versionCheck", version); + + if (version == null) throw new Error("Javascript files not found."); + + return version; + } + + public static function writeAppletTag(attributes:Object, parameters:Object = null):void{ + var response:Object = ExternalInterface.call("deployJava.writeAppletTag", attributes, parameters); + + if (response == null) throw new Error("Javascript files not found."); + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/util/PersistUserPreferences.as b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/util/PersistUserPreferences.as new file mode 100755 index 0000000000000000000000000000000000000000..a725632e5810d5ee38212f1ad90246ec1f8fbcce --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/util/PersistUserPreferences.as @@ -0,0 +1,47 @@ +package org.bigbluebutton.modules.settings.util +{ + import flash.net.SharedObject; + + public class PersistUserPreferences + { + private static var sharedObject:SharedObject = SharedObject.getLocal("bbbUserProperties", "/"); + + public static function storeData(preference:String, data:String):void{ + sharedObject.data[preference] = data; + try{ + sharedObject.flush(1000); + } catch(err:Error){ + trace("Could not flush shared object"); + } + } + + public static function saveWebcamPreference(webcam:String):void{ + sharedObject.data["webcam"] = webcam; + try{ + sharedObject.flush(1000); + } catch(err:Error){ + trace("Could not flush shared object"); + } + } + + public static function saveMicrophonePreference(microphone:String):void{ + sharedObject.data["microphone"] = microphone; + try{ + sharedObject.flush(1000); + } catch(err:Error){ + trace("Could not flush shared object"); + } + } + + public static function saveMicrophoneGain(gain:Number):void{ + if (gain > 100 || gain < 0) return; + + sharedObject.data["gain"] = gain; + try{ + sharedObject.flush(1000); + } catch(err:Error){ + trace("Could not flush shared object"); + } + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/settings/util/Requirements.as b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/util/Requirements.as new file mode 100755 index 0000000000000000000000000000000000000000..36dc3f83770655e811469f203f44a248a57df371 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/settings/util/Requirements.as @@ -0,0 +1,39 @@ +package org.bigbluebutton.modules.settings.util +{ + import flash.events.Event; + import flash.net.URLLoader; + import flash.net.URLRequest; + import flash.net.URLRequestHeader; + import flash.net.URLRequestMethod; + + import mx.collections.ArrayCollection; + + public class Requirements + { + public static var bbb_apps_url:String; + public static var bbb_voice_url:String; + public static var bbb_video_url:String; + public static var bbb_deskshare_url:String; + public static var flash_required_version:String; + public static var java_required_version:String; + + private static var loader:URLLoader; + private static var isLoaded:Boolean = false; + private static var loadingStarted:Boolean = false; + + + public static function setRequirements(attributes:Object):void{ + isLoaded = true; + + //bbb_apps_url = xml.bigbluebutton_apps.@url; + bbb_video_url = attributes.video; + bbb_voice_url = attributes.voice; + bbb_deskshare_url = attributes.deskshare; + + flash_required_version = attributes.flash_required; + java_required_version = attributes.java_required; + + } + + } +} \ No newline at end of file