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