diff --git a/bigbluebutton-apps/src/main/java/org/bigbluebutton/conference/BigBlueButtonService.java b/bigbluebutton-apps/src/main/java/org/bigbluebutton/conference/BigBlueButtonService.java
new file mode 100755
index 0000000000000000000000000000000000000000..52baf7218b4c1f58d32016336d8f3d296c43ad8f
--- /dev/null
+++ b/bigbluebutton-apps/src/main/java/org/bigbluebutton/conference/BigBlueButtonService.java
@@ -0,0 +1,33 @@
+package org.bigbluebutton.conference;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.red5.server.api.Red5;
+
+public class BigBlueButtonService {
+	private ConnectionInvokerService connInvokerService;
+	
+	public void sendMessage(HashMap<String, Object> params) {
+		
+		Map<String, Object> messageToSend = new HashMap<String, Object>();
+		
+	    for (Iterator<String> it = params.keySet().iterator(); it.hasNext();) {
+	        String key = it.next();
+	        messageToSend.put(key, params.get(key));
+	    }
+	    		
+		ClientMessage m = new ClientMessage(ClientMessage.BROADCAST, getMeetingId(), (String) params.get("messageID"), messageToSend);
+		connInvokerService.sendMessage(m);
+	}
+	
+	private String getMeetingId(){
+		return Red5.getConnectionLocal().getScope().getName();
+	}
+	
+	public void setConnInvokerService(ConnectionInvokerService connInvokerService) {
+		this.connInvokerService = connInvokerService;
+	}
+	
+}
diff --git a/bigbluebutton-apps/src/main/java/org/bigbluebutton/webconference/voice/freeswitch/FreeswitchApplication.java b/bigbluebutton-apps/src/main/java/org/bigbluebutton/webconference/voice/freeswitch/FreeswitchApplication.java
index 9c6a6149e41022427dc7701e030d142ad691ba12..b2461e344ad71f30d4f64d14f67b6dadaa2811ff 100755
--- a/bigbluebutton-apps/src/main/java/org/bigbluebutton/webconference/voice/freeswitch/FreeswitchApplication.java
+++ b/bigbluebutton-apps/src/main/java/org/bigbluebutton/webconference/voice/freeswitch/FreeswitchApplication.java
@@ -58,10 +58,12 @@ public class FreeswitchApplication extends Observable implements ConferenceServi
     private FreeswitchHeartbeatMonitor heartbeatMonitor;
     private boolean debug = false;
  
+    private String icecastProtocol = "shout";
     private String icecastHost = "localhost";
     private int icecastPort = 8000;
     private String icecastUsername = "source";
     private String icecastPassword = "hackme";
+    private String icecastStreamExtension = ".mp3";
     private Boolean icecastBroadcast = false;
     
     private final Integer USER = 0; /* not used for now */
@@ -180,8 +182,8 @@ public class FreeswitchApplication extends Observable implements ConferenceServi
     }
     
     private void broadcastToIcecast(String room, String meetingid) {
-    	String shoutPath = "shout://" + icecastUsername + ":" + icecastPassword + "@" + icecastHost + ":" + icecastPort 
-    			+ File.separatorChar + meetingid + ".mp3";       
+    	String shoutPath = icecastProtocol + "://" + icecastUsername + ":" + icecastPassword + "@" + icecastHost + ":" + icecastPort 
+    			+ File.separatorChar + meetingid + "." + icecastStreamExtension;       
     	
     	if (log.isDebugEnabled())
     		log.debug("Broadcast to {}", shoutPath);
@@ -364,7 +366,11 @@ public class FreeswitchApplication extends Observable implements ConferenceServi
     public void setDebugNullConferenceAction(boolean enabled) {
         this.debug = enabled;
     }
-  
+    
+    public void setIcecastProtocol(String protocol) {
+    	icecastProtocol = protocol;
+    }
+    
     public void setIcecastHost(String host) {
     	icecastHost = host;
     }
@@ -384,6 +390,10 @@ public class FreeswitchApplication extends Observable implements ConferenceServi
     public void setIcecastBroadcast(Boolean broadcast) {
     	icecastBroadcast = broadcast;
     }
+
+    public void setIcecastStreamExtension(String ext) {
+    	icecastStreamExtension = ext;
+    }
     
     private Integer getMemberIdFromEvent(EslEvent e)
     {
diff --git a/bigbluebutton-apps/src/main/webapp/WEB-INF/bbb-apps.xml b/bigbluebutton-apps/src/main/webapp/WEB-INF/bbb-apps.xml
index 6f44100ea8efc5ac43021464e91885304042a2bc..9eab28be4d2fcf23e812f3a5e08feff674659028 100755
--- a/bigbluebutton-apps/src/main/webapp/WEB-INF/bbb-apps.xml
+++ b/bigbluebutton-apps/src/main/webapp/WEB-INF/bbb-apps.xml
@@ -12,7 +12,11 @@
 		<property name="messagingService" ref="messagingService"></property>
 		<property name="conversionUpdatesMessageListener" ref="conversionUpdatesMessageListener"></property>
 	</bean>
-			
+	
+	<bean id="bigbluebutton.service" class="org.bigbluebutton.conference.BigBlueButtonService">
+      <property name="connInvokerService"> <ref bean="connInvokerService"/></property>
+    </bean>
+  		
 	<bean id="participantsHandler" class="org.bigbluebutton.conference.service.participants.ParticipantsHandler">
 		<property name="participantsApplication"> <ref local="participantsApplication"/></property>
 		<property name="recorderApplication"> <ref local="recorderApplication"/></property>
diff --git a/bigbluebutton-apps/src/main/webapp/WEB-INF/bbb-voice-freeswitch.xml b/bigbluebutton-apps/src/main/webapp/WEB-INF/bbb-voice-freeswitch.xml
index 72a64f3e192bb5e593bb83d6a53ab0e3e8152dea..b4d9d7623985ad19454c484edd829ab6c6c64d42 100755
--- a/bigbluebutton-apps/src/main/webapp/WEB-INF/bbb-voice-freeswitch.xml
+++ b/bigbluebutton-apps/src/main/webapp/WEB-INF/bbb-voice-freeswitch.xml
@@ -14,6 +14,7 @@
 	<beans:bean id="freeswitchApplication" class="org.bigbluebutton.webconference.voice.freeswitch.FreeswitchApplication">
 		<beans:property name="managerConnection" ref="eslConnection"/>
     <beans:property name="DebugNullConferenceAction" value="true"/>
+    <beans:property name="icecastProtocol" value="${icecast.protocol}"/>
     <beans:property name="icecastHost" value="${icecast.host}"/>
     <beans:property name="icecastPort" value="${icecast.port}"/>
     <beans:property name="icecastUsername" value="${icecast.username}"/>
diff --git a/bigbluebutton-apps/src/main/webapp/WEB-INF/bigbluebutton.properties b/bigbluebutton-apps/src/main/webapp/WEB-INF/bigbluebutton.properties
index 5127e693c51804f21f42047eef4b5a0c46293d05..094ee6db58fdf4fd823869282a2365aa93fffe99 100755
--- a/bigbluebutton-apps/src/main/webapp/WEB-INF/bigbluebutton.properties
+++ b/bigbluebutton-apps/src/main/webapp/WEB-INF/bigbluebutton.properties
@@ -31,6 +31,8 @@ version=0.63
 redis.host=127.0.0.1
 redis.port=6379
 
+icecast.protocol=shout
+icecast.streamExt=mp3
 icecast.host=127.0.0.1
 icecast.port=8000
 icecast.username=source
diff --git a/bigbluebutton-client/branding/README b/bigbluebutton-client/branding/README
new file mode 100644
index 0000000000000000000000000000000000000000..aeb8e83436fbf7c301670cf05c73c190287d05d4
--- /dev/null
+++ b/bigbluebutton-client/branding/README
@@ -0,0 +1,3 @@
+This is the directory where you should put your custom skinning/styling.
+
+
diff --git a/bigbluebutton-client/branding/default/README b/bigbluebutton-client/branding/default/README
new file mode 100644
index 0000000000000000000000000000000000000000..83731d116814f02866d6528e7052fd5f7861c958
--- /dev/null
+++ b/bigbluebutton-client/branding/default/README
@@ -0,0 +1 @@
+ This is the default BigBlueButton style.
diff --git a/bigbluebutton-client/branding/default/build.xml b/bigbluebutton-client/branding/default/build.xml
new file mode 100755
index 0000000000000000000000000000000000000000..9f2653eeea7264438df5f80714cc4faa6b6692b4
--- /dev/null
+++ b/bigbluebutton-client/branding/default/build.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- BigBlueButton Branding build.xml for use by Hudson builds.   -->
+<project name="BigBlueButton Branding" basedir="../.." default="branding" >
+	<property environment="env" />
+	<property name="DEBUG" value="true" />
+	<property name="BUILD_ENV" value="DEV" />
+	<property name="FLEX_HOME" value="${env.FLEX_HOME}" />
+	<property name="themeFile" value="BBBDefault.css" />
+	<property name="BASE_DIR" value="${basedir}" />
+	<property name="SRC_DIR" value="${BASE_DIR}/src" />
+		
+	<property name="OUTPUT_DIR" value="${BASE_DIR}/bin" />
+	<taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />
+	
+	<target name="init-ant-contrib">
+		<property name="ant-contrib.jar" location="${BASE_DIR}/build/lib/ant-contrib-0.6.jar"/>
+		<taskdef resource="net/sf/antcontrib/antcontrib.properties" classpath="${ant-contrib.jar}"/>
+	</target>
+	  	
+	<target name="branding" depends="init-ant-contrib">
+		<sequential>
+			<mxmlc file="${BASE_DIR}/branding/default/style/css/${themeFile}" 
+				output="${OUTPUT_DIR}/branding/css/${themeFile}.swf" 
+				debug="${DEBUG}" 
+				mxml.compatibility-version="3.0.0" 
+				swf-version="13" 
+				optimize="true">
+			</mxmlc>
+		</sequential>
+	</target>
+</project>
diff --git a/bigbluebutton-client/branding/default/style/css/BBBDefault.css b/bigbluebutton-client/branding/default/style/css/BBBDefault.css
new file mode 100755
index 0000000000000000000000000000000000000000..aca09e5462861917ddd556e7adf99c1a03672c1d
--- /dev/null
+++ b/bigbluebutton-client/branding/default/style/css/BBBDefault.css
@@ -0,0 +1,504 @@
+Application {
+  backgroundColor: #ffffff;
+}
+
+ApplicationControlBar {
+  highlightAlphas: 0.1, 0;
+  fillAlphas: 0, 0;
+  fillColors: #32343b, #32343b;
+  backgroundColor: #42444c;
+  backgroundAlpha: 1;
+  cornerRadius: 0;
+  dropShadowEnabled: true;
+  shadowDistance: 1;
+  shadowDirection: center;
+  dropShadowColor: #000000;
+}
+
+Panel {
+  borderColor: #dfdfdf;
+  borderAlpha: 1;
+  shadowDistance: 1;
+  dropShadowColor: #666666;
+  titleStyleName: "mypanelTitle";
+}
+
+.mypanelTitle {
+  color: #444444;
+  fontFamily: Arial;
+  fontSize: 12;
+}
+
+.whiteboardToolbarStyle {
+  backgroundColor: #CCCCCC;
+  cornerRadius: 5;
+  borderStyle: solid;
+  borderThickness: 1;
+  paddingBottom: 3;
+  paddingTop: 3;
+  paddingLeft: 3;
+  paddingRight: 3;
+}
+
+Button {
+  textIndent: 0;
+  paddingLeft: 1;
+  paddingRight: 1;
+  paddingTop: 1;
+  paddingBottom: 1;
+  highlightAlphas: 0.4, 0;
+  fillAlphas: 1, 1, 1, 1;
+  fillColors: #fefeff, #e1e2e5, #ffffff, #eeeeee;
+  color: #5e5f63;
+  textRollOverColor: #5e5f63;
+  textSelectedColor: #5e5f63;
+  borderColor: #b9babc;
+  themeColor: haloBlue;
+  fontFamily: Arial;
+  fontSize: 12;
+}
+
+.chatSendButtonStyle {
+  cornerRadius: 0;
+  highlightAlphas: 0, 0;
+  fillAlphas: 1, 1, 1, 1;
+  fillColors: #262626, #262626, #454545, #454545;
+  color: #ffffff;
+  textRollOverColor: #ffffff;
+  textSelectedColor: #262626;
+  borderColor: #000000;
+  themeColor: haloBlue;
+  fontFamily: Arial;
+  fontSize: 12;
+}
+
+.logoutButtonStyle {
+  cornerRadius: 0;
+  highlightAlphas: 0, 0;
+  fillAlphas: 1, 1, 1, 1;
+  fillColors: #262626, #262626, #454545, #454545;
+  color: #ffffff;
+  textRollOverColor: #ffffff;
+  textSelectedColor: #262626;
+  borderColor: #000000;
+  themeColor: haloBlue;
+  fontFamily: Arial;
+  fontSize: 12;
+}
+
+.helpLinkButtonStyle {
+  rollOverColor: #cccccc;
+  selectionColor: #999999;
+  color: #ffffff;
+  textRollOverColor: #504f3d;
+  textSelectedColor: #504f3d;
+}
+
+DataGrid {
+  backgroundColor: #e1e2e5;
+  rollOverColor: #f3f3f3;
+  textRollOverColor: #5e5f63;
+  selectionColor: #e1e2e5;
+  color: #5e5f63;
+  textSelectedColor: #5e5f63;
+  dropShadowEnabled: false;
+  fontFamily: arial;
+  fontSize: 11;
+  headerStyleName: "mydataGridHeaderStyle";
+}
+
+.mydataGridHeaderStyle {
+  color: #5e5f63;
+  fontFamily: arial;
+  fontSize: 12;
+}
+
+
+.whiteboardUndoButtonStyle, .whiteboardCircleButtonStyle, .whiteboardClearButtonStyle,
+.whiteboardTriangleButtonStyle, .whiteboardTextButtonStyle, .whiteboardRectangleButtonStyle,
+.whiteboardPanZoomButtonStyle, .whiteboardLineButtonStyle, .whiteboardScribbleButtonStyle
+{
+  textIndent: 0;
+  paddingLeft: 0;
+  paddingRight: 0;
+  paddingTop: 5;
+  paddingBottom: 5;
+  highlightAlphas: 0.4, 0;
+  fillAlphas: 1, 1, 1, 1;
+  fillColors: #fefeff, #e1e2e5, #ffffff, #eeeeee;
+  color: #5e5f63;
+  textRollOverColor: #5e5f63;
+  textSelectedColor: #5e5f63;
+  borderColor: #b9babc;
+  themeColor: haloBlue;
+  fontFamily: Arial;
+  fontSize: 12;
+}
+
+.whiteboardUndoButtonStyle 
+{
+  icon: Embed('assets/images/undo.png');
+}
+
+.whiteboardCircleButtonStyle {
+  icon: Embed('assets/images/ellipse.png');  
+}
+
+.whiteboardClearButtonStyle {
+  icon: Embed('assets/images/delete.png');    
+}
+
+.whiteboardScribbleButtonStyle{
+  icon: Embed('assets/images/pencil.png');  
+}
+
+.whiteboardLineButtonStyle {
+  icon: Embed('assets/images/line.png');    
+}
+
+.whiteboardPanZoomButtonStyle {
+  icon: Embed('assets/images/hand.png');   
+}
+
+.whiteboardRectangleButtonStyle {
+  icon: Embed('assets/images/square.png');   
+}
+
+.whiteboardTextButtonStyle {
+  icon: Embed('assets/images/text.png');   
+}
+
+.whiteboardTriangleButtonStyle {
+  icon: Embed('assets/images/triangle.png');    
+}
+
+.presentationUploadButtonStyle, .presentationBackButtonStyle, .presentationForwardButtonStyle,
+.presentationFitToWidthButtonStyle, .presentationFitToPageButtonStyle 
+{
+  textIndent: 0;
+  paddingLeft: 10;
+  paddingRight: 10;
+  paddingTop: 5;
+  paddingBottom: 5;
+  highlightAlphas: 0.4, 0;
+  fillAlphas: 1, 1, 1, 1;
+  fillColors: #fefeff, #e1e2e5, #ffffff, #eeeeee;
+  color: #5e5f63;
+  textRollOverColor: #5e5f63;
+  textSelectedColor: #5e5f63;
+  borderColor: #b9babc;
+  themeColor: haloBlue;
+  fontFamily: Arial;
+  fontSize: 12;
+}
+
+.presentationUploadButtonStyle {
+  icon:   Embed('assets/images/upload.png');   
+}
+
+.presentationBackButtonStyle {
+  icon:   Embed('assets/images/left-arrow.png'); 
+}
+
+.presentationForwardButtonStyle {
+  icon:   Embed('assets/images/right-arrow.png'); 
+}
+
+.presentationFitToWidthButtonStyle {
+  icon:   Embed('assets/images/fit-to-width.png'); 
+}
+
+.presentationFitToPageButtonStyle {
+  icon:   Embed('assets/images/fit-to-screen.png'); 
+}
+
+.presentationZoomSliderStyle{
+  labelOffset: 0;
+  thumbOffset: 3;
+  dataTipOffset: -1;
+  tickOffset: 2;
+  tickLength: 5;
+  tickThickness: 2;
+  tickColor: #6cccff;
+  showTrackHighlight: true;
+  invertThumbDirection: false;
+  borderColor: #b9babc;
+  trackColors: #aaaaaa, #aaaaaa;
+  themeColor: haloBlue;
+  fillAlphas: 1, 1, 1, 1;
+  fillColors: #fefeff, #e1e2e5, #ffffff, #eeeeee;
+  labelStyleName: "presentationZoomSliderLabelStyle";
+}
+
+.presentationZoomSliderLabelStyle {
+  color: #5e5f63;
+  fontFamily: Arial;
+}
+
+.videoMuteButtonStyle, .videoUnmutedButtonStyle, .videoSwitchPresenterButtonStyle, .videoEjectUserButtonStyle, .videoPrivateChatButtonStyle {
+  fillAlphas: 1, 1, 1, 1;
+  fillColors: #fefeff, #e1e2e5, #ffffff, #eeeeee;
+  color: #5e5f63;
+  textRollOverColor: #ffffff;
+  textSelectedColor: #ffffff;
+  borderColor: #b9babc;  
+  cornerRadius: 17;
+}
+
+.videoMutedButtonStyle {
+  /* Need to duplicate info here as the styleName is programatically changed. Extracting it out doesn't have any effect. */
+  fillAlphas: 1, 1, 1, 1;
+  fillColors: #96c7e6, #50a6d7, #ffffff, #eeeeee;
+  color: #ffffff;
+  textRollOverColor: #ffffff;
+  textSelectedColor: #ffffff;
+  borderColor: #50a6d7;  
+  cornerRadius: 17;
+  icon:   Embed('assets/images/webcam-muted.png');
+}
+
+.videoUnmutedButtonStyle {
+  icon:   Embed('assets/images/webcam-unmuted.png');
+}
+
+.videoSwitchPresenterButtonStyle {
+  icon:   Embed('assets/images/webcam-switch-presenter.png');
+}
+
+.videoEjectUserButtonStyle {
+  icon:   Embed('assets/images/webcam-eject-user.png');
+}
+
+.videoPrivateChatButtonStyle {
+  icon:   Embed('assets/images/webcam-private-chat.png');
+}
+
+MDIWindow {
+  
+}
+
+.mdiWindowFocus, .presentationWindowStyleFocus, .videoDockStyleFocus
+{
+  headerHeight: 26;
+  roundedBottomCorners: true;
+  backgroundAlpha: 1;
+  backgroundColor: #b9babc;
+  backgroundSize: '100%';
+  
+  borderStyle: solid;
+  borderColor: #b9babc;
+  borderAlpha: 1;
+  borderThickness: 1;
+  borderThicknessLeft: 1;
+  borderThicknessTop: 1;
+  borderThicknessBottom: 1;
+  borderThicknessRight: 1;
+  cornerRadius: 0;
+  dropShadowEnabled: false;
+  titleStyleName: "mypanelTitle";
+  
+  cornerResizeImg: Embed(source="assets/swf/Blue.swf", symbol="Corner_Resize");
+  cornerResizeWidth: 2;
+  cornerResizeHeight: 2;
+  cornerResizePaddingRight: 2;
+  cornerResizePaddingBottom: 2;
+  
+  controlButtonWidth: 10;
+  controlButtonHeight: 10;
+  controlButtonGap: 4;
+}
+
+.mdiWindowNoFocus, .presentationWindowStyleNoFocus, .videoDockStyleNoFocus
+{
+  headerHeight: 26;
+  roundedBottomCorners: false;
+  backgroundAlpha: 0.5;
+  backgroundColor: #b9babc;
+  backgroundSize: '100%';
+  
+  borderStyle: solid;
+  borderColor: #b9babc;
+  borderAlpha: 0.5;
+  borderThickness: 1;
+  borderThicknessLeft: 1;
+  borderThicknessTop: 1;
+  borderThicknessBottom: 1;
+  borderThicknessRight: 1;
+  cornerRadius: 0;
+  dropShadowEnabled: false;
+  titleStyleName: "mypanelTitle";
+  
+  cornerResizeImg: Embed(source="assets/swf/Blue.swf", symbol="Corner_Resize");
+  cornerResizeWidth: 2;
+  cornerResizeHeight: 2;
+  cornerResizePaddingRight: 2;
+  cornerResizePaddingBottom: 2;
+  
+  controlButtonWidth: 10;
+  controlButtonHeight: 10;
+  controlButtonGap: 4;
+}
+
+.presentationSlideViewStyle {
+  backgroundColor: #b9babc;
+}
+
+.presentationWindowControlsStyle {
+  paddingBottom: 5;
+  paddingTop: 3;
+  paddingLeft: 3;
+  paddingRight: 3;
+  bottom: 5;
+  cornerRadius: 0;
+  dropShadowEnabled: false;
+}
+
+.videoViewStyleNoFocus 
+{
+  borderColor: #b9babc;
+  borderAlpha: 0.5;
+  borderThicknessLeft: 5;
+  borderThicknessTop: 5;
+  borderThicknessBottom: 5;
+  borderThicknessRight: 5;
+  roundedBottomCorners: true;
+  cornerRadius: 5;
+  headerHeight: 20;
+  backgroundColor: #b9babc;
+  backgroundAlpha: 0.5;
+  dropShadowEnabled: false;
+  titleStyleName: "mypanelTitle";
+}
+
+.videoViewStyleFocus 
+{
+  borderColor: #b9babc;
+  borderAlpha: 1;
+  borderThicknessLeft: 5;
+  borderThicknessTop: 5;
+  borderThicknessBottom: 5;
+  borderThicknessRight: 5;
+  roundedBottomCorners: true;
+  cornerRadius: 5;
+  headerHeight: 20;
+  backgroundColor: #b9babc;
+  backgroundAlpha: 1;
+  dropShadowEnabled: false;
+  titleStyleName: "mypanelTitle";
+}
+
+.videoPublishStyleNoFocus 
+{
+  borderColor: #b9babc;
+  borderAlpha: 0.5;
+  borderThicknessLeft: 5;
+  borderThicknessTop: 5;
+  borderThicknessBottom: 5;
+  borderThicknessRight: 5;
+  roundedBottomCorners: true;
+  cornerRadius: 5;
+  headerHeight: 20;
+  backgroundColor: #b9babc;
+  backgroundAlpha: 0.5;
+  dropShadowEnabled: false;
+  titleStyleName: "mypanelTitle";
+}
+
+.videoPublishStyleFocus 
+{
+  borderColor: #b9babc;
+  borderAlpha: 1;
+  borderThicknessLeft: 5;
+  borderThicknessTop: 5;
+  borderThicknessBottom: 5;
+  borderThicknessRight: 5;
+  roundedBottomCorners: true;
+  cornerRadius: 5;
+  headerHeight: 20;
+  backgroundColor: #b9babc;
+  backgroundAlpha: 1;
+  dropShadowEnabled: false;
+  titleStyleName: "mypanelTitle";
+}
+
+.videoAvatarStyleNoFocus 
+{
+  borderColor: #b9babc;
+  borderAlpha: 0.5;
+  borderThicknessLeft: 5;
+  borderThicknessTop: 5;
+  borderThicknessBottom: 5;
+  borderThicknessRight: 5;
+  roundedBottomCorners: true;
+  cornerRadius: 5;
+  headerHeight: 20;
+  backgroundColor: #b9babc;
+  backgroundAlpha: 0.5;
+  dropShadowEnabled: false;
+  titleStyleName: "mypanelTitle";
+}
+
+.videoAvatarStyleFocus 
+{
+  borderColor: #b9babc;
+  borderAlpha: 1;
+  borderThicknessLeft: 5;
+  borderThicknessTop: 5;
+  borderThicknessBottom: 5;
+  borderThicknessRight: 5;
+  roundedBottomCorners: true;
+  cornerRadius: 5;
+  headerHeight: 20;
+  backgroundColor: #b9babc;
+  backgroundAlpha: 1;
+  dropShadowEnabled: false;
+  titleStyleName: "mypanelTitle";
+}
+
+.mypanelTitle {
+  color: #5e5f63;
+  fontFamily: Arial;
+  fontSize: 12;
+}
+
+.closeBtnFocus, .closeBtnNoFocus
+{
+  upSkin:        Embed('assets/images/3_closeButton.png');
+  overSkin:      Embed('assets/images/3_closeButton.png');
+  downSkin:      Embed('assets/images/3_closeButton.png');
+  disabledSkin:  Embed('assets/images/3_closeButton.png');
+}
+
+
+.increaseBtnFocus, .increaseBtnNoFocus
+{
+  upSkin:        Embed('assets/images/3_increaseButton.png');
+  overSkin:      Embed('assets/images/3_increaseButton.png');
+  downSkin:      Embed('assets/images/3_increaseButton.png');
+  disabledSkin:  Embed('assets/images/3_increaseButton.png');
+}
+
+.decreaseBtnFocus, .decreaseBtnNoFocus  
+{
+  upSkin:        Embed('assets/images/3_decreaseButton.png');
+  overSkin:      Embed('assets/images/3_decreaseButton.png');
+  downSkin:      Embed('assets/images/3_decreaseButton.png');
+  disabledSkin:  Embed('assets/images/3_decreaseButton.png');
+}
+
+.minimizeBtnFocus 
+{
+  upSkin:        Embed('assets/images/3_minimizeButton.png');
+  overSkin:      Embed('assets/images/3_minimizeButton.png');
+  downSkin:      Embed('assets/images/3_minimizeButton.png');
+  disabledSkin:  Embed('assets/images/3_minimizeButton.png');
+}
+
+
+.resizeHndlr 
+{
+  upSkin:        Embed('assets/images/resizeHandler.png');
+  overSkin:      Embed('assets/images/resizeHandler.png');
+  downSkin:      Embed('assets/images/resizeHandler.png');
+  disabledSkin:  Embed('assets/images/resizeHandler.png');
+}
diff --git a/bigbluebutton-client/src/branding/css/assets/img/3_closeButton.png b/bigbluebutton-client/branding/default/style/css/assets/images/3_closeButton.png
similarity index 100%
rename from bigbluebutton-client/src/branding/css/assets/img/3_closeButton.png
rename to bigbluebutton-client/branding/default/style/css/assets/images/3_closeButton.png
diff --git a/bigbluebutton-client/src/branding/css/assets/img/3_decreaseButton.png b/bigbluebutton-client/branding/default/style/css/assets/images/3_decreaseButton.png
similarity index 100%
rename from bigbluebutton-client/src/branding/css/assets/img/3_decreaseButton.png
rename to bigbluebutton-client/branding/default/style/css/assets/images/3_decreaseButton.png
diff --git a/bigbluebutton-client/src/branding/css/assets/img/3_increaseButton.png b/bigbluebutton-client/branding/default/style/css/assets/images/3_increaseButton.png
similarity index 100%
rename from bigbluebutton-client/src/branding/css/assets/img/3_increaseButton.png
rename to bigbluebutton-client/branding/default/style/css/assets/images/3_increaseButton.png
diff --git a/bigbluebutton-client/src/branding/css/assets/img/3_minimizeButton.png b/bigbluebutton-client/branding/default/style/css/assets/images/3_minimizeButton.png
similarity index 100%
rename from bigbluebutton-client/src/branding/css/assets/img/3_minimizeButton.png
rename to bigbluebutton-client/branding/default/style/css/assets/images/3_minimizeButton.png
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/delete.png b/bigbluebutton-client/branding/default/style/css/assets/images/delete.png
new file mode 100755
index 0000000000000000000000000000000000000000..0059eaa72ce11f79b11fb2fa0d5c3e225ca6c11a
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/delete.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/ellipse.png b/bigbluebutton-client/branding/default/style/css/assets/images/ellipse.png
new file mode 100755
index 0000000000000000000000000000000000000000..3252b6aa957f272a4c0ae8ea14213464681cba7d
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/ellipse.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/fit-to-screen.png b/bigbluebutton-client/branding/default/style/css/assets/images/fit-to-screen.png
new file mode 100755
index 0000000000000000000000000000000000000000..afbfdbfc06c5b284df1580abe083dd486d4c2e69
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/fit-to-screen.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/fit-to-width.png b/bigbluebutton-client/branding/default/style/css/assets/images/fit-to-width.png
new file mode 100755
index 0000000000000000000000000000000000000000..25be501f1eb1578ee1ae71f85f2335caa42152c4
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/fit-to-width.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/hand.png b/bigbluebutton-client/branding/default/style/css/assets/images/hand.png
new file mode 100755
index 0000000000000000000000000000000000000000..d923194e5ed2ccd5ac57a456540474727d6531b4
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/hand.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/icons-license.txt b/bigbluebutton-client/branding/default/style/css/assets/images/icons-license.txt
new file mode 100755
index 0000000000000000000000000000000000000000..9f25609678fefd389d8e80e4ea4b0243b685c2b4
--- /dev/null
+++ b/bigbluebutton-client/branding/default/style/css/assets/images/icons-license.txt
@@ -0,0 +1,38 @@
+Silk icon set 1.3
+
+_________________________________________
+Mark James
+http://www.famfamfam.com/lab/icons/silk/
+_________________________________________
+
+This work is licensed under a
+Creative Commons Attribution 2.5 License.
+[ http://creativecommons.org/licenses/by/2.5/ ]
+
+This means you may use it for any purpose,
+and make any changes you like.
+All I ask is that you include a link back
+to this page in your credits.
+
+Are you using this icon set? Send me an email
+(including a link or picture if available) to
+mjames@gmail.com
+
+Any other questions about this icon set please
+contact mjames@gmail.com
+
+==================================================
+Diagona Icons
+
+Copyright (C) 2007 Yusuke Kamiyamane. All rights reserved.
+The icons are licensed under a Creative Commons Attribution
+3.0 license. <http://creativecommons.org/licenses/by/3.0/>
+
+If you can't or don't want to provide a link back, please
+purchase a royalty-free license.
+<http://p.yusukekamiyamane.com/>
+
+I'm unavailable for custom icon design work. But your
+suggestions are always welcome!
+<mailto:p@yusukekamiyamane.com>
+====================
\ No newline at end of file
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/left-arrow.png b/bigbluebutton-client/branding/default/style/css/assets/images/left-arrow.png
new file mode 100755
index 0000000000000000000000000000000000000000..e6abeb60d45d8a2a2b0f85b741f1af14683a4c4c
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/left-arrow.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/line.png b/bigbluebutton-client/branding/default/style/css/assets/images/line.png
new file mode 100755
index 0000000000000000000000000000000000000000..175174a0ea5ebb32535ad19ccd0a86a319496bb9
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/line.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/marker.png b/bigbluebutton-client/branding/default/style/css/assets/images/marker.png
new file mode 100755
index 0000000000000000000000000000000000000000..7a026099e3685ceb87505f5b1292f48b714da566
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/marker.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/pencil.png b/bigbluebutton-client/branding/default/style/css/assets/images/pencil.png
new file mode 100755
index 0000000000000000000000000000000000000000..dd979748baebc063f532af178489732ab0c4548f
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/pencil.png differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/resizeHandler.png b/bigbluebutton-client/branding/default/style/css/assets/images/resizeHandler.png
similarity index 100%
rename from bigbluebutton-client/src/branding/css/assets/img/resizeHandler.png
rename to bigbluebutton-client/branding/default/style/css/assets/images/resizeHandler.png
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/right-arrow.png b/bigbluebutton-client/branding/default/style/css/assets/images/right-arrow.png
new file mode 100755
index 0000000000000000000000000000000000000000..6eab9f047a5ecd05d65ac1dae3f226b80009347d
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/right-arrow.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/square.png b/bigbluebutton-client/branding/default/style/css/assets/images/square.png
new file mode 100755
index 0000000000000000000000000000000000000000..48b5280bdb794d3d5de562af781f3affeda59ffc
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/square.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/text.png b/bigbluebutton-client/branding/default/style/css/assets/images/text.png
new file mode 100755
index 0000000000000000000000000000000000000000..21858b8ca4c28e93acb3eddd665860cf214d3bcf
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/text.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/trash.png b/bigbluebutton-client/branding/default/style/css/assets/images/trash.png
new file mode 100755
index 0000000000000000000000000000000000000000..2b95a3faa6ff838bff79a0c8e53a8a0c83bdb9e5
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/trash.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/triangle.png b/bigbluebutton-client/branding/default/style/css/assets/images/triangle.png
new file mode 100755
index 0000000000000000000000000000000000000000..f629ee6aebb3c600c700ef3eb54cbf59917dd70b
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/triangle.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/undo.png b/bigbluebutton-client/branding/default/style/css/assets/images/undo.png
new file mode 100755
index 0000000000000000000000000000000000000000..f65e9db3edf0cd4f2ee09b2a463e8436c19894d3
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/undo.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/upload.png b/bigbluebutton-client/branding/default/style/css/assets/images/upload.png
new file mode 100755
index 0000000000000000000000000000000000000000..724a094ae6974c1fd6e451ed492a06955e538ed2
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/upload.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/webcam-eject-user.png b/bigbluebutton-client/branding/default/style/css/assets/images/webcam-eject-user.png
new file mode 100755
index 0000000000000000000000000000000000000000..561edc8d9b00d9c97c9acd82b4bf121bc3a77426
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/webcam-eject-user.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/webcam-muted.png b/bigbluebutton-client/branding/default/style/css/assets/images/webcam-muted.png
new file mode 100755
index 0000000000000000000000000000000000000000..3be5bd19cf8cf09beb6c7c7758b21b5deabab69b
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/webcam-muted.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/webcam-private-chat.png b/bigbluebutton-client/branding/default/style/css/assets/images/webcam-private-chat.png
new file mode 100755
index 0000000000000000000000000000000000000000..9fdff988a3cfa2f6ef81f0a2d0de135dd199371e
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/webcam-private-chat.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/webcam-switch-presenter.png b/bigbluebutton-client/branding/default/style/css/assets/images/webcam-switch-presenter.png
new file mode 100755
index 0000000000000000000000000000000000000000..e7cfff5e97381b5a88d0b96b35508e52e850960e
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/webcam-switch-presenter.png differ
diff --git a/bigbluebutton-client/branding/default/style/css/assets/images/webcam-unmuted.png b/bigbluebutton-client/branding/default/style/css/assets/images/webcam-unmuted.png
new file mode 100755
index 0000000000000000000000000000000000000000..32a685732f0073772bb782662fe37e30a83d5220
Binary files /dev/null and b/bigbluebutton-client/branding/default/style/css/assets/images/webcam-unmuted.png differ
diff --git a/bigbluebutton-client/src/branding/css/assets/swf/Blue.swf b/bigbluebutton-client/branding/default/style/css/assets/swf/Blue.swf
similarity index 100%
rename from bigbluebutton-client/src/branding/css/assets/swf/Blue.swf
rename to bigbluebutton-client/branding/default/style/css/assets/swf/Blue.swf
diff --git a/bigbluebutton-client/src/branding/css/assets/swf/BrushedMetal.swf b/bigbluebutton-client/branding/default/style/css/assets/swf/BrushedMetal.swf
similarity index 100%
rename from bigbluebutton-client/src/branding/css/assets/swf/BrushedMetal.swf
rename to bigbluebutton-client/branding/default/style/css/assets/swf/BrushedMetal.swf
diff --git a/bigbluebutton-client/src/branding/css/assets/swf/WindowsAssets.swf b/bigbluebutton-client/branding/default/style/css/assets/swf/WindowsAssets.swf
similarity index 100%
rename from bigbluebutton-client/src/branding/css/assets/swf/WindowsAssets.swf
rename to bigbluebutton-client/branding/default/style/css/assets/swf/WindowsAssets.swf
diff --git a/bigbluebutton-client/build.xml b/bigbluebutton-client/build.xml
index 2491cdb00df46798fba1472a31e734bb015f8bdf..c24eb067206a4cf6043a75b8100ba12d1d61d2b7 100755
--- a/bigbluebutton-client/build.xml
+++ b/bigbluebutton-client/build.xml
@@ -3,11 +3,14 @@
 <project name="BigBlueButton Client" basedir="." default="clean-build-all" >
     	<property environment="env" />
     	<property name="STATIC_RSL" value="true" />
+	     <property name="DEBUG" value="true" />
     	<property name="BUILD_ENV" value="DEV" />
     	<property name="FLEX_HOME" value="${env.FLEX_HOME}" />
     	<property name="LOCALE_DIR" value="${FLEX_HOME}/frameworks/locale"/>
     	<property name="BASE_DIR" value="${basedir}" />
-	<property name="RESOURCES_DIR" value="${BASE_DIR}/resources" />	
+      <property name="themeFile" value="BBBDefault.css"/>
+	
+	     <property name="RESOURCES_DIR" value="${BASE_DIR}/resources" />	
 	<property name="PROD_RESOURCES_DIR" value="${RESOURCES_DIR}/prod" />	
 	<property name="SRC_DIR" value="${BASE_DIR}/src" />
 		
@@ -15,21 +18,20 @@
 	<taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />
 
 	<!-- Declare module names here -->
-	<property name="BBB_MAIN_TEST" value="BigBlueButtonTest" />
 	<property name="BBB_MAIN" value="BigBlueButton" />
+	<property name="BROADCAST" value="BroadcastModule" />
 	<property name="CHAT" value="ChatModule" />
 	<property name="VIEWERS" value="ViewersModule" />
 	<property name="LISTENERS" value="ListenersModule" />
 	<property name="PRESENT" value="PresentModule" />
 	<property name="DESKSHARE" value="DeskShareModule" />
 	<property name="DESKSHARE_SA" value="DeskshareStandalone" />
+	<property name="CAM_PREVIEW_SA" value="WebcamPreviewStandalone" />
+	<property name="CAM_VIEW_SA" value="WebcamViewStandalone" />
 	<property name="PHONE" value="PhoneModule" />
+	<property name="NOTES" value="NotesModule" />
 	<property name="VIDEO" value="VideoconfModule" />
 	<property name="WHITEBOARD" value="WhiteboardModule" />
-	<property name="DYN_INFO" value="DynamicInfoModule" />
-	<property name="BREAKOUT" value="BreakoutModule" />
-	<property name="CLASSROOM_AUDIO" value="ClassroomAudioModule" />
-	<property name="SETTINGS" value="SettingsModule" />
 	<property name="VIDEO_DOCK" value="VideodockModule" />
 	<property name="LAYOUT" value="LayoutModule" />
 	
@@ -69,9 +71,9 @@
 		
 	<target name="branding" depends="init-ant-contrib">
 		<sequential>
-			<mxmlc file="${SRC_DIR}/branding/css/${themeFile}" 
+			<mxmlc file="${BASE_DIR}/branding/default/style/css/${themeFile}" 
 				output="${OUTPUT_DIR}/branding/css/${themeFile}.swf" 
-				debug="false" 
+				debug="${DEBUG}" 
 				mxml.compatibility-version="3.0.0" 
 				swf-version="13" 
 				optimize="true">
@@ -162,14 +164,18 @@
 			<fileset dir="${BASE_DIR}/src/org/bigbluebutton/common/assets/images/" />
 		</copy>		
 	</target>
-	
-	<target name="build-breakout" description="Compile Breakout Module" >
-		<build-module src="${SRC_DIR}" target="${BREAKOUT}" />
-	</target>
-	
+
+  <target name="build-broadcast" description="Compile Broadcast Module" >
+    <build-module src="${SRC_DIR}" target="${BROADCAST}" />
+  </target>
+  	
 	<target name="build-chat" description="Compile Chat Module">
 		<build-module src="${SRC_DIR}" target="${CHAT}" />
 	</target>
+  
+  <target name="build-notes" description="Compile Notes Module">
+    <build-module src="${SRC_DIR}" target="${NOTES}" />
+  </target>
 	
 	<target name="build-viewers" description="Compile Viewers Module">
 		<build-module src="${SRC_DIR}" target="${VIEWERS}" />
@@ -183,16 +189,26 @@
 		<build-module src="${SRC_DIR}" target="${PRESENT}" />
 	</target>
 
-	<target name="build-deskshare-standalone" depends="build-deskshare-no-linker" description="Compile Deskshare Standalone Module">
+	<target name="build-deskshare-standalone" depends="build-deskshare-no-linker" description="Compile Deskshare Standalone Application">
 		<echo message="Compiling deskshare standalone without optimization." />
 		<build-module-no-link src="${SRC_DIR}" target="${DESKSHARE_SA}" />
 	</target>
-	
-	<target name="build-deskshare-no-linker" description="Compile Deskshare Module without the linker">
-		<echo message="Compiling deskshare without optimization." />
-		<build-module-no-link src="${SRC_DIR}" target="${DESKSHARE}" />	
-	</target>
-	
+  
+  <target name="build-deskshare-no-linker" description="Compile Deskshare Module without the linker">
+    <echo message="Compiling deskshare without optimization." />
+    <build-module-no-link src="${SRC_DIR}" target="${DESKSHARE}" /> 
+  </target>
+    
+  <target name="build-webcam-preview-standalone" description="Compile Webcam Preview Standalone Application">
+    <echo message="Compiling webcam preview standalone without optimization." />
+    <build-module-no-link src="${SRC_DIR}" target="${CAM_PREVIEW_SA}" />
+  </target>
+
+  <target name="build-webcam-view-standalone" description="Compile Webcam View Standalone Application">
+    <echo message="Compiling webcam view standalone without optimization." />
+    <build-module-no-link src="${SRC_DIR}" target="${CAM_VIEW_SA}" />
+  </target>
+    	
 	<target name="build-deskshare" description="Compile Deskshare Module">
 		<build-module src="${SRC_DIR}" target="${DESKSHARE}" />
 		<echo message="Copying deskshare applet for Deskshare Module" />
@@ -207,14 +223,6 @@
 			<fileset dir="${BASE_DIR}/src/org/bigbluebutton/modules/phone/views/assets/images/" />
 		</copy>		
 	</target>
-
-	<target name="build-classroom-audio" description="Compile Classroom Audio Module">
-		<build-module src="${SRC_DIR}" target="${CLASSROOM_AUDIO}" />
-	</target>
-	
-	<target name="build-settings" description="Compile Settings Module">
-		<build-module src="${SRC_DIR}" target="${SETTINGS}" />
-	</target>
 	
 	<target name="build-video" description="Compile Video Module">
 		<build-module src="${SRC_DIR}" target="${VIDEO}" />
@@ -228,24 +236,20 @@
 		<build-module src="${SRC_DIR}" target="${WHITEBOARD}" />
 	</target>
 	
-	<target name="build-dyn" description="Compile Dynamic Info Module">
-		<build-module src="${SRC_DIR}" target="${DYN_INFO}" />
-	</target>
-	
 	<target name="build-layout" description="Compile Layout Module">
 		<build-module src="${SRC_DIR}" target="${LAYOUT}" />
 	</target>
 	
 	<!-- just a grouping of modules to compile -->
 	<target name="build-main-chat-viewers-listeners-present" 
-			depends="build-bbb-main, build-bbb-main-test, build-chat, build-viewers, build-listeners, build-present, build-breakout, build-layout"
-			description="Compile main, chat, viewers, listeners, present, breakout modules">
+			depends="build-bbb-main, build-chat, build-viewers, build-listeners, build-present, build-layout, build-broadcast"
+			description="Compile main, chat, viewers, listeners, present modules">
 	</target>
 	
 	<!-- just a grouping of modules to compile -->
 	<target name="build-deskshare-phone-video-whiteboard-dyn" 
-			depends="build-deskshare, build-phone, build-video, build-videodock, build-whiteboard, build-dyn, build-classroom-audio, build-settings"
-			description="Compile deskshare, phone, video, whiteboard, dynamic info modules">
+			depends="build-deskshare, build-phone, build-video, build-videodock, build-whiteboard, build-notes"
+			description="Compile deskshare, phone, video, whiteboard modules">
 	</target>
 	
 	<macrodef name="build-main">
@@ -254,7 +258,7 @@
 			<attribute name="app" default="."/>
 			<attribute name="src" default="${SRC_DIR}" description="Path to the module to compile" />
 			<sequential>
-				<mxmlc file="@{src}/@{target}.mxml" output="${OUTPUT_DIR}/@{target}.swf" debug="false" mxml.compatibility-version="3.0.0" swf-version="13" optimize="true" link-report="linker-report.xml">
+				<mxmlc file="@{src}/@{target}.mxml" output="${OUTPUT_DIR}/@{target}.swf" debug="${DEBUG}" mxml.compatibility-version="3.0.0" swf-version="13" optimize="true" link-report="linker-report.xml">
 					<target-player>11</target-player>
 					<load-config filename="@{flex}/frameworks/flex-config.xml" />
 					<source-path path-element="@{flex}/frameworks" />
@@ -293,7 +297,7 @@
 		<attribute name="app" default="."/>
 		<attribute name="src" default="${SRC_DIR}" description="Path to the module to compile" />
 		<sequential>
-			<mxmlc file="@{src}/@{target}.mxml" output="${OUTPUT_DIR}/@{target}.swf" debug="false" mxml.compatibility-version="3.0.0" swf-version="13">
+			<mxmlc file="@{src}/@{target}.mxml" output="${OUTPUT_DIR}/@{target}.swf" debug="${DEBUG}" mxml.compatibility-version="3.0.0" swf-version="13">
 				<target-player>11</target-player>
 				<load-config filename="@{flex}/frameworks/flex-config.xml" />
 				<source-path path-element="@{flex}/frameworks" />
@@ -320,7 +324,7 @@
 		<attribute name="app" default="."/>
 		<attribute name="src" default="${SRC_DIR}" description="Path to the module to compile" />
 		<sequential>
-			<mxmlc file="@{src}/@{target}.mxml" output="${OUTPUT_DIR}/@{target}.swf" debug="false" mxml.compatibility-version="3.0.0" swf-version="13" optimize="true" load-externs="linker-report.xml">
+			<mxmlc file="@{src}/@{target}.mxml" output="${OUTPUT_DIR}/@{target}.swf" debug="${DEBUG}" mxml.compatibility-version="3.0.0" swf-version="13" optimize="true" load-externs="linker-report.xml">
 				<target-player>11</target-player>
 				<load-config filename="@{flex}/frameworks/flex-config.xml" />
 				<source-path path-element="@{flex}/frameworks" />
@@ -378,7 +382,8 @@
 		<copy file="${PROD_RESOURCES_DIR}/BigBlueButtonTest.html" todir="${OUTPUT_DIR}" overwrite="true"/>
 		<copy file="${PROD_RESOURCES_DIR}/BigBlueButton.html" todir="${OUTPUT_DIR}" overwrite="true"/>
 		<copy file="${PROD_RESOURCES_DIR}/DeskshareStandalone.html" todir="${OUTPUT_DIR}" overwrite="true"/>
-		<copy file="${PROD_RESOURCES_DIR}/bbb.gif" todir="${OUTPUT_DIR}" overwrite="true"/>		
+		<copy file="${PROD_RESOURCES_DIR}/bbb.gif" todir="${OUTPUT_DIR}" overwrite="true"/>	
+		<copy file="${PROD_RESOURCES_DIR}/avatar.png" todir="${OUTPUT_DIR}" overwrite="true"/>
 		<copy file="${PROD_RESOURCES_DIR}/locales.xml" todir="${OUTPUT_DIR}/conf" overwrite="true"/>	
 		<copy file="${PROD_RESOURCES_DIR}/expressInstall.swf" todir="${OUTPUT_DIR}" overwrite="true"/>	
 		<copy file="${PROD_RESOURCES_DIR}/example-info-data.xml" todir="${OUTPUT_DIR}/conf" overwrite="true"/>
@@ -455,13 +460,16 @@
 
 	<!-- NOTE: compile-deskshare-standalone MUST come first before compile-bbb as we need the deskshare-standalone
 				to be compiled withouth being optimized by using the linker -->
-	<target name="clean-build-bbb" depends="clean, init-ant-contrib, generate-html-wrapper, compile-deskshare-standalone, compile-bbb" 
+	<target name="clean-build-bbb" depends="clean, init-ant-contrib, generate-html-wrapper, compile-deskshare-standalone, 
+	                                        build-webcam-preview-standalone, build-webcam-view-standalone, compile-bbb" 
 			description="Build BBB client skipping compiling of locales"/>	
-	<target name="clean-build-all" depends="clean, init-ant-contrib, generate-html-wrapper, compile-deskshare-standalone, compile-bbb" 
+	<target name="clean-build-all" depends="clean, init-ant-contrib, generate-html-wrapper, compile-deskshare-standalone, 
+	                                         build-webcam-preview-standalone, build-webcam-view-standalone, compile-bbb, branding" 
 			description="Build BBB client including locales"/>
-	<target name="modules" depends="init-ant-contrib, generate-html-wrapper, compile-deskshare-standalone, compile-bbb"
+	<target name="modules" depends="init-ant-contrib, generate-html-wrapper, compile-deskshare-standalone, 
+	                                         build-webcam-preview-standalone, build-webcam-view-standalone, compile-bbb"
                         description="Build BBB client without locales"/>		
 	<target name="cleanandmake" depends="clean-build-all" description="Build BBB client including locales"/>
 
-	<target name="build-custom" depends="init-ant-contrib, build-classroom-audio" description="Build a custom defined module only, to save time as each build takes several minutes" />
+	<target name="build-custom" depends="init-ant-contrib" description="Build a custom defined module only, to save time as each build takes several minutes" />
 </project>
diff --git a/bigbluebutton-client/locale/en_US/bbbResources.properties b/bigbluebutton-client/locale/en_US/bbbResources.properties
index 67840f912d0c5a136ec0682b8090d8fe21ab9744..851c982dffd006e55e933c9943d2bc009cc28741 100755
--- a/bigbluebutton-client/locale/en_US/bbbResources.properties
+++ b/bigbluebutton-client/locale/en_US/bbbResources.properties
@@ -173,6 +173,10 @@ bbb.logout.rejected = The connection to the server has been rejected
 bbb.logout.invalidapp = The red5 app does not exist
 bbb.logout.unknown = Your client has lost connection with the server
 bbb.logout.usercommand = You have logged out of the conference
+bbb.notes.title = Notes
+bbb.notes.cmpColorPicker.toolTip = Text Color
+bbb.notes.saveBtn = Save
+bbb.notes.saveBtn.toolTip = Save Note
 bbb.settings.deskshare.instructions = Click Allow on the prompt that pops up to check that desktop sharing is working properly for you
 bbb.settings.deskshare.start = Check Desktop Sharing
 bbb.settings.voice.volume = Microphone Activity
@@ -217,6 +221,8 @@ bbb.accessibility.chat.plustab.fontsize = Font size
 bbb.accessibility.chat.chatView.publicTabNew = NEW MESSAGE IN PUBLIC CHAT
 bbb.accessibility.chat.chatView.privateTabNew = NEW MESSAGE IN PRIVATE CHAT WITH {0}
 
+bbb.accessibility.notes.notesview.input = Notes input
+
 bbb.shortcuthelp.title = Shortcut glossary
 bbb.shortcuthelp.dropdown.all = All shortcuts
 bbb.shortcuthelp.dropdown.general = General shortcuts
diff --git a/bigbluebutton-client/resources/config.xml.template b/bigbluebutton-client/resources/config.xml.template
index d5548397b7a6fd3c6352e38a1d490b80ce79cad7..895e2428f7c642f5b6ce5fbf093abbc4d29d9050 100755
--- a/bigbluebutton-client/resources/config.xml.template
+++ b/bigbluebutton-client/resources/config.xml.template
@@ -6,7 +6,7 @@
     <porttest host="HOST" application="video" timeout="10000"/>    
     <application uri="rtmp://HOST/bigbluebutton" host="http://HOST/bigbluebutton/api/enter" />
     <language userSelectionEnabled="true" />
-    <skinning enabled="false" url="branding/css/theme.css.swf" />
+    <skinning enabled="true" url="http://HOST/client/branding/css/BBBDefault.css.swf" />
     <layout showLogButton="false" showVideoLayout="false" showResetLayout="true" defaultLayout="Default"
             showToolbar="true" showFooter="true" showHelpButton="true" showLogoutWindow="true"/>
             
@@ -25,13 +25,11 @@
 			uri="rtmp://HOST/bigbluebutton" 
 			host="http://HOST/bigbluebutton/api/enter"
 			allowKickUser="false"
-			windowVisible="true"
 		/>
 			
 		<module name="ListenersModule" url="http://HOST/client/ListenersModule.swf?v=VERSION" 
 			uri="rtmp://HOST/bigbluebutton" 
 			recordingHost="http://HOST"
-			windowVisible="true"
 			position="bottom-left"
 		/>
 		
@@ -74,7 +72,8 @@
 			filterDivisor="4"
 			enableH264 = "true"
 			h264Level = "2.1"
-			h264Profile = "main"			
+			h264Profile = "main"		
+			displayAvatar = "false"	
 		/>
 		
 		<module name="WhiteboardModule" url="http://HOST/client/WhiteboardModule.swf?v=VERSION" 
@@ -94,6 +93,7 @@
 			uri="rtmp://HOST/bigbluebutton" 
 			dependsOn="VideoconfModule, ViewersModule"
 			autoDock="true"
+			showControls="true"
 			maximizeWindow="false"
 			position="bottom-right"
 			width="172"
@@ -107,24 +107,22 @@
 			layoutConfig="http://HOST/client/conf/layout.xml"
 			enableEdit="true"
 		/>
-
-		<!-- new module in development: 
-		<module name="DynamicInfoModule" url="http://HOST/client/DynamicInfoModule.swf?v=VERSION" 
-			uri="rtmp://HOST/bigbluebutton" 
-			host="http://HOST" 
-			infoURL="http://HOST/client/conf/example-info-data.xml?user={userID}&role={role}&meetingID={meetingID}"
-		/>
-		-->
-		
-		<!--<module name="ExampleChatModule" url="http://HOST/client/ExampleChatModule.swf?v=56" 
-			uri="rtmp://HOST/bigbluebutton" 
-			host="http://HOST"
-		/>-->
-		
-		<!--<module name="SharedNotesModule" url="http://HOST/client/SharedNotesModule.swf?v=VERSION" 
-			uri="http://192.168.0.225/bigbluebutton" 
-			dependsOn="ViewersModule"
-		/>-->
 		
+<!--
+    <module name="NotesModule" url="http://HOST/client/NotesModule.swf?v=VERSION"
+      saveURL="http://HOST"
+      position="top-left"
+    />
+    
+    <module name="BroadcastModule" url="http://HOST/client/BroadcastModule.swf?v=VERSION"
+      uri="rtmp://HOST/bigbluebutton"
+      streamsUri="http://HOST/streams.xml"
+      position="top-left"
+      showStreams="true"
+      autoPlay="false"
+      dependsOn="ViewersModule"
+    />
+-->
+    		
 	</modules>
 </config>
diff --git a/bigbluebutton-client/resources/prod/3rd-party.html b/bigbluebutton-client/resources/prod/3rd-party.html
index 2e10d69223620f52cfd9463ecc393be96b52bba9..aff8ceb2485e25a4522c9f1e438d85a3809f81ee 100755
--- a/bigbluebutton-client/resources/prod/3rd-party.html
+++ b/bigbluebutton-client/resources/prod/3rd-party.html
@@ -11,6 +11,8 @@
     <script type="text/javascript" src="http://192.168.0.249/client/swfobject/swfobject.js"></script>
     <script type="text/javascript">
       swfobject.registerObject("BigBlueButton", "11", "expressInstall.swf");
+      swfobject.registerObject("WebcamPreviewStandalone", "11", "expressInstall.swf");
+      swfobject.registerObject("WebcamViewStandalone", "11", "expressInstall.swf");
     </script>
     <script src="http://192.168.0.249/client/lib/jquery-1.5.1.min.js" language="javascript"></script>
     <script src="http://192.168.0.249/client/lib/bigbluebutton.js" language="javascript"></script>
@@ -18,12 +20,21 @@
     <script src="http://192.168.0.249/client/lib/bbb_blinker.js" language="javascript"></script>
     <script src="http://192.168.0.249/client/lib/bbb_deskshare.js" language="javascript"></script>
     <script type="text/javascript" src="http://192.168.0.249/client/lib/bbb_api_bridge.js"></script>
+    <script type="text/javascript" src="http://192.168.0.249/client/lib/bbb_api_cam_preview.js"></script>
+    <script type="text/javascript" src="http://192.168.0.249/client/lib/bbb_api_cam_view.js"></script>
     <script type="text/javascript" src="http://192.168.0.235/3rd-party.js"></script>
     <script>
       window.displayBBBClient = function() {
         var bbbc = document.getElementById("flashclient");
+        var wcpc = document.getElementById("webcampreviewclient");
+        wcpc.style.display = "none";
         bbbc.style.display = "block";
       }
+      window.displayWCClient = function() {
+        console.log("Displaying webcam preview client");
+        var wcpc = document.getElementById("webcampreview");
+        wcpc.style.display = "block";
+      }
       window.onload = function() {
          registerListeners();
       }
@@ -31,24 +42,77 @@
   </head>
   <body>
     <div id="controls">
-      <button type="button" onclick="displayBBBClient()">Show Client</button>
-      <button type="button" onclick="BBB.shareVideoCamera()">Webcam</button>
+      <button type="button" onclick="registerListeners()">Listen for Events</button>
+      <button type="button" onclick="displayBBBClient()">Show BBB Client</button>
+      <button type="button" onclick="displayWCClient()">Show WC Client</button>
+      <button type="button" onclick="BBB.shareVideoCamera()">Share Webcam</button>
+      <button type="button" onclick="BBB.stopSharingCamera()">Stop Webcam</button>
+      <button type="button" onclick="BBB.switchPresenter('x8hxeozsqbk1')">Switch Presenter</button>
       <button type="button" onclick="joinVoiceConference2()">Join Voice</button>
+      <button type="button" onclick="leaveVoiceConference2()">Leave Voice</button>
+      <button type="button" onclick="getMyUserID()">Get My UserID</button>
+      <button type="button" onclick="getMeetingID()">Get MeetingID</button>
       <button type="button" onclick="getMyRoleAsynch()">Get My Role Asynch</button>
       <button type="button" onclick="getMyRoleSynch()">Get My Role Synch</button>
       <button type="button" onclick="muteMe()">Mute Me</button>
       <button type="button" onclick="unmuteMe()">Unmute Me</button>
       <button type="button" onclick="muteAll()">Mute All</button>
       <button type="button" onclick="unmuteAll()">Unmute All</button>
-      <button type="button" onclick="switchLayout('Video Chat')">Switch Video Layout</button>
-      <button type="button" onclick="switchLayout('Lecture')">Switch Present Layout</button>
+      <button type="button" onclick="switchLayout('S2SVideoChat')">Switch Video Layout</button>
+      <button type="button" onclick="switchLayout('S2SPresentation')">Switch Present Layout</button>
       <button type="button" onclick="lockLayout(true)">Lock Layout</button>
       <button type="button" onclick="lockLayout(false)">Unlock Layout</button>
       <button type="button" onclick="sendPublicChat()">Send Public Chat</button>
       <button type="button" onclick="sendPrivateChat()">Send Private Chat</button>
+      <button type="button" onclick="amIPresenterSync()">Am I Presenter Sync</button>
+      <button type="button" onclick="amIPresenterAsync()">Am I Presenter Async</button>
     </div>
-      <div id="flashclient" style="display: none">
-        <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="90%" id="BigBlueButton" name="BigBlueButton" align="middle">
+    <div id="webcampreview" style="background-color:#FFD700;height:240px;width:320px;float:left;">
+        <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540001" width="320" height="240" id="WebcamPreviewStandalone" name="WebcamPreviewStandalone" align="middle">
+          <param name="movie" value="http://192.168.0.249/client/WebcamPreviewStandalone.swf?v=VERSION" />
+          <param name="quality" value="high" />
+          <param name="allowfullscreen" value="true" />
+          <param name="bgcolor" value="#869ca7" />
+          <param name="wmode" value="window" />
+          <param name="allowScriptAccess" value="always" />
+          <!--[if !IE]>-->
+            <object type="application/x-shockwave-flash" data="http://192.168.0.249/client/WebcamPreviewStandalone.swf?v=VERSION" width="100%" height="90%" align="middle">
+              <param name="quality" value="high" />
+              <param name="bgcolor" value="#869ca7" />
+              <param name="allowScriptAccess" value="always" />
+              <!--<![endif]-->
+                <a href="http://www.adobe.com/go/getflashplayer">
+                  <img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
+                </a>
+              <!--[if !IE]>-->
+           </object>
+        <!--<![endif]-->
+        </object>
+     </div>
+    <div id="webcamview" style="background-color:#FFD700;height:240px;width:320px;float:left;">
+        <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540002" width="320" height="240" id="WebcamViewStandalone" name="WebcamViewStandalone" align="middle">
+          <param name="movie" value="http://192.168.0.249/client/WebcamViewStandalone.swf?v=VERSION" />
+          <param name="quality" value="high" />
+          <param name="allowfullscreen" value="true" />
+          <param name="bgcolor" value="#869ca7" />
+          <param name="wmode" value="window" />
+          <param name="allowScriptAccess" value="always" />
+          <!--[if !IE]>-->
+            <object type="application/x-shockwave-flash" data="http://192.168.0.249/client/WebcamViewStandalone.swf?v=VERSION" width="100%" height="90%" align="middle">
+              <param name="quality" value="high" />
+              <param name="bgcolor" value="#869ca7" />
+              <param name="allowScriptAccess" value="always" />
+              <!--<![endif]-->
+                <a href="http://www.adobe.com/go/getflashplayer">
+                  <img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
+                </a>
+              <!--[if !IE]>-->
+           </object>
+        <!--<![endif]-->
+        </object>
+     </div>
+     <div id="flashclient" style="background-color:#EEEEEE;height:900px;width:1200px;float:left;">
+        <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="50%" height="50%" id="BigBlueButton" name="BigBlueButton" align="middle">
           <param name="movie" value="http://192.168.0.249/client/BigBlueButton.swf?v=VERSION" />
           <param name="quality" value="high" />
           <param name="allowfullscreen" value="true" />
@@ -68,7 +132,7 @@
            </object>
         <!--<![endif]-->
         </object>
-      </div>
+    </div>
     <div id="update-display"/>
     <div id="notifications" aria-live="polite" role="region" aria-label="Chat Notifications"></div>
   </body>
diff --git a/bigbluebutton-client/resources/prod/avatar.png b/bigbluebutton-client/resources/prod/avatar.png
new file mode 100644
index 0000000000000000000000000000000000000000..2e9f8151f4083aece663009ae40d9271104dbb41
Binary files /dev/null and b/bigbluebutton-client/resources/prod/avatar.png differ
diff --git a/bigbluebutton-client/resources/prod/layout.xml b/bigbluebutton-client/resources/prod/layout.xml
index 638e1f12dd473c162468ca9f8b2a6894fe1ca594..8ea77513a2d31d31f11eb6de6c80a6e7d36f1fa3 100755
--- a/bigbluebutton-client/resources/prod/layout.xml
+++ b/bigbluebutton-client/resources/prod/layout.xml
@@ -1,6 +1,8 @@
 <?xml version="1.0"?>
 <layouts>
   <layout name="Video Chat">
+    <window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
     <window name="ViewersWindow" minimized="true" order="3" hidden="true" />
     <window name="VideoDock" width="1" height="1" x="0" y="0" order="0"/>
     <window name="ChatWindow" width="0.303125" height="0.9955703211517165" x="0.3229166666666667" y="0.9656699889258029" order="4" hidden="true" />
@@ -8,6 +10,8 @@
     <window name="ListenersWindow" minimized="true" hidden="true" order="2"/>
   </layout>
   <layout name="Default"  default="true">
+    <window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
     <window name="ViewersWindow" width="0.1772793053545586" height="0.33643617021276595" x="0" y="0" />
     <window name="ListenersWindow" width="0.1772793053545586" height="0.33643617021276595" x="0" y="0.34308510638297873" />
     <window name="PresentationWindow" width="0.5137481910274964" height="0.9946808510638298" x="0.18017366136034732" y="0" />
@@ -15,6 +19,8 @@
     <window name="ChatWindow" width="0.3031837916063676" height="0.9960106382978723" x="0.6968162083936325" y="0" />
   </layout>
   <layout name="Meeting">
+    <window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
     <window name="VideoDock" width="0.6570188133140377" height="0.9960106382978723" x="0" y="0" />
     <window name="ChatWindow" width="0.3393632416787265" height="0.5305851063829787" x="0.658465991316932" y="0" />
     <window name="ListenersWindow" hidden="true" />
@@ -22,6 +28,8 @@
     <window name="PresentationWindow" width="0.34008683068017365" height="0.4601063829787234" x="0.658465991316932" y="0.535904255319149" />
   </layout>
   <layout name="Webinar">
+    <window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
     <window name="ViewersWindow" minimized="true" />
     <window name="VideoDock" width="0.2923611111111111" height="0.4640957446808511" x="0.7048611111111112" y="0.535904255319149" />
     <window name="ListenersWindow" minimized="true" />
@@ -29,6 +37,8 @@
     <window name="ChatWindow" width="0.2923611111111111" height="0.5305851063829787" x="0.7048611111111112" y="0" />
   </layout>
   <layout name="Lecture assistant">
+    <window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
     <window name="ChatWindow" width="0.4597222222222222" height="0.9958677685950413" x="0.2263888888888889" y="0" />
     <window name="ListenersWindow" width="0.2222222222222222" height="0.4765840220385675" x="0" y="0.5179063360881543" />
     <window name="ViewersWindow" width="0.22152777777777777" height="0.5055096418732782" x="0" y="0" />
@@ -36,6 +46,8 @@
     <window name="VideoDock" width="0.30972222222222223" height="0.4256198347107438" x="0.6902777777777778" y="0.568870523415978" />
   </layout>	
   <layout name="Lecture">
+    <window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
     <window name="ViewersWindow" hidden="true" />
     <window name="VideoDock" width="0.2923611111111111" height="0.4640957446808511" x="0.7048611111111112" y="0.535904255319149" />
     <window name="ListenersWindow" hidden="true" />
@@ -43,6 +55,8 @@
     <window name="ChatWindow" width="0.2923611111111111" height="0.5305851063829787" x="0.7048611111111112" y="0" />
   </layout>	
   <layout name="Lecture" role="presenter">
+    <window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
     <window name="ChatWindow" hidden="true" />
     <window name="ListenersWindow" hidden="true" />
     <window name="ViewersWindow" hidden="true" />
@@ -50,10 +64,48 @@
     <window name="VideoDock" hidden="true" />
   </layout>	
   <layout name="Lecture" role="moderator">
+    <window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
     <window name="ChatWindow" width="0.4597222222222222" height="0.9958677685950413" x="0.2263888888888889" y="0" />
     <window name="ListenersWindow" width="0.2222222222222222" height="0.4765840220385675" x="0" y="0.5179063360881543" />
     <window name="ViewersWindow" width="0.22152777777777777" height="0.5055096418732782" x="0" y="0" />
     <window name="PresentationWindow" width="0.3104166666666667" height="0.5537190082644629" x="0.6895833333333333" y="0" />
     <window name="VideoDock" width="0.30972222222222223" height="0.4256198347107438" x="0.6902777777777778" y="0.568870523415978" />
   </layout>	
+  <layout name="S2SPresentation">
+    <window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
+    <window name="ChatWindow" hidden="true" draggable="false" resizable="false"/>
+    <window name="ListenersWindow" hidden="true" draggable="false" resizable="false"/>
+    <window name="ViewersWindow" hidden="true" draggable="false" resizable="false"/>
+    <window name="PresentationWindow" width="0.8" height="1" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="VideoDock" hidden="true" draggable="false" resizable="false"/>
+  </layout>
+  <layout name="S2SVideoChat">
+    <window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
+    <window name="ViewersWindow" hidden="true" draggable="false" resizable="false"/>
+    <window name="VideoDock" width="1" height="1" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="ChatWindow" hidden="true" draggable="false" resizable="false"/>
+    <window name="PresentationWindow" hidden="true" draggable="false" resizable="false"/>
+    <window name="ListenersWindow" hidden="true" draggable="false" resizable="false"/>
+  </layout>
+    <layout name="Notes">
+    <window name="NotesWindow" hidden="false" width="0.7" height="0.4" x="0" y="0.6" draggable="false" resizable="false"/>
+    <window name="BroadcastWindow" hidden="false" width="0.7" height="0.6" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="ViewersWindow" hidden="true" draggable="false" resizable="false"/>
+    <window name="VideoDock" hidden="true" draggable="false" resizable="false"/>
+    <window name="ChatWindow" width="0.3" height="1" x="0.7" y="0" draggable="false" resizable="false"/>
+    <window name="PresentationWindow" hidden="true" draggable="false" resizable="false"/>
+    <window name="ListenersWindow" hidden="true" draggable="false" resizable="false"/>
+  </layout>
+  <layout name="Broadcast">
+    <window name="NotesWindow" hidden="false" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="BroadcastWindow" hidden="false" width="0.7" height="0.9" x="0" y="0" draggable="false" resizable="false"/>
+    <window name="ViewersWindow" hidden="true" draggable="false" resizable="false"/>
+    <window name="VideoDock" hidden="true" draggable="false" resizable="false"/>
+    <window name="ChatWindow" width="0.3" height="1" x="0.7" y="0" draggable="false" resizable="false"/>
+    <window name="PresentationWindow" hidden="true" draggable="false" resizable="false"/>
+    <window name="ListenersWindow" hidden="true" draggable="false" resizable="false"/>
+  </layout>
 </layouts>
diff --git a/bigbluebutton-client/resources/prod/lib/3rd-party.js b/bigbluebutton-client/resources/prod/lib/3rd-party.js
index 71f69259841a9911dfd4e2d073581b2766fc5354..0c874d4c0dfaad882cf61607f56aff6fa090d0d2 100755
--- a/bigbluebutton-client/resources/prod/lib/3rd-party.js
+++ b/bigbluebutton-client/resources/prod/lib/3rd-party.js
@@ -1,26 +1,67 @@
 
 var registerListeners = function() {
+  console.log("Listening for events.");
   BBB.listen("UserLeftEvent", function(bbbEvent) {
     console.log("User [" + bbbEvent.userID + "] has left.");
   });
   BBB.listen("UserJoinedEvent", function(bbbEvent) {
     console.log("User [" + bbbEvent.userID + ", [" + bbbEvent.userName + "] has joined.");
   });
-  BBB.listen("UserJoinedVoiceEvent", function(bbbEvent) {
-    console.log("Received userHasJoinedVoiceConference event");
-  });
   BBB.listen("NewPublicChatEvent", function(bbbEvent) {
     console.log("Received NewPublicChatEvent [" + bbbEvent.message + "]");
   });
   BBB.listen("NewPrivateChatEvent", function(bbbEvent) {
     console.log("Received NewPrivateChatEvent event");
   });
+  BBB.listen("UserJoinedVoiceEvent", function(bbbEvent) {
+    console.log("User [" + bbbEvent.userID + "] had joined the voice conference.");
+  });
+  BBB.listen("UserLeftVoiceEvent", function(bbbEvent) {
+    console.log("User [" + bbbEvent.userID + "has left the voice conference.");
+  });
+  BBB.listen("UserVoiceMutedEvent", function(bbbEvent) {
+    console.log("User [" + bbbEvent.userID + "] is muted [" + bbbEvent.muted + "]");
+  });
+  BBB.listen("UserLockedVoiceEvent", function(bbbEvent) {
+    console.log("User [" + bbbEvent.userID + "] is locked [" + bbbEvent.locked + "]");
+  });
+  BBB.listen("CamStreamSharedEvent", function(bbbEvent) {
+    console.log("User CamStreamSharedEvent [" + bbbEvent.uri + "," + bbbEvent.streamName + "]");
+    CAM_VIEW.viewWebcamStream(bbbEvent.uri, bbbEvent.streamName);
+  });
+  BBB.listen("BroadcastingCameraStartedEvent", function(bbbEvent) {
+    console.log("User BroadcastingCameraStartedEvent [" + bbbEvent.camIndex + "] [" + bbbEvent.camWidth + "]");
+    CAM_PREVIEW.previewCamera(bbbEvent.camIndex, bbbEvent.camWidth, bbbEvent.camHeight, bbbEvent.camKeyFrameInterval,
+                              bbbEvent.camModeFps, bbbEvent.camQualityBandwidth, bbbEvent.camQualityPicture);
+  });
+  BBB.listen("BroadcastingCameraStoppedEvent", function(bbbEvent) {
+    console.log("User BroadcastingCameraStoppedEvent ]");
+    CAM_PREVIEW.stopPreviewCamera();
+  });
+}
+
+var leaveVoiceConference2 = function () {
+  BBB.leaveVoiceConference();
 }
 
 var joinVoiceConference2 = function () {
   BBB.joinVoiceConference();
 }
 
+var amIPresenterAsync = function() {
+  BBB.listen("AmIPresenterQueryResponse", function(bbbEvent) {
+    console.log("Received AmIPresenterQueryResponse event [" + bbbEvent.amIPresenter + "]");
+  });
+
+  BBB.amIPresenter();
+}
+
+var amIPresenterSync = function() {
+  BBB.amIPresenter(function(amIPresenter) {
+    console.log("Am I Presenter = " + amIPresenter);
+  });
+}
+
 var getMyRoleAsynch = function() {
   BBB.listen("GetMyRoleResponse", function(bbbEvent) {
     console.log("Received GetMyRoleResponse event");
@@ -35,6 +76,18 @@ var getMyRoleSynch = function() {
   });
 }
 
+var getMyUserID = function() {
+  BBB.getMyUserID(function(userID) {
+    console.log("My user ID  = [" + userID + "]");
+  });
+}
+
+var getMeetingID = function() {
+  BBB.getMeetingID(function(meetingID) {
+    console.log("Meeting ID  = [" + meetingID + "]");
+  });
+}
+
 var muteMe = function() {
   BBB.muteMe();
 }
diff --git a/bigbluebutton-client/resources/prod/lib/bbb_api_bridge.js b/bigbluebutton-client/resources/prod/lib/bbb_api_bridge.js
index 14cd569d54fc846e09b41ef85b7ef3b41914ea9e..9b7bb3557979e39a0fed21d6aad4a7cfa71d3318 100755
--- a/bigbluebutton-client/resources/prod/lib/bbb_api_bridge.js
+++ b/bigbluebutton-client/resources/prod/lib/bbb_api_bridge.js
@@ -12,6 +12,33 @@
       return swfobject.getObjectById("BigBlueButton");
     }
 
+    BBB.switchPresenter = function(newPresenterUserID) {
+      var swfObj = getSwfObj();
+      if (swfObj) {
+        console.log("Request to switch presenter to [" + newPresenterUserID + "]");
+        swfObj.switchPresenterRequest(newPresenterUserID);
+      }    
+    }
+
+    /**
+     * Query the Flash client if user is presenter.
+     * Params:
+     *    callback - function if you want a callback as response. Otherwise, you need to listen
+     *               for the response as an event.
+     */
+    BBB.amIPresenter = function(callback) {
+      var swfObj = getSwfObj();
+      if (swfObj) {
+        if (arguments.length == 0) {
+          swfObj.amIPresenterRequestAsync();
+        } else {
+          if (typeof callback === 'function') {
+            callback(swfObj.amIPresenterRequestSync());
+          }
+        }
+      }
+    }
+            
     /**
      * Query the Flash client for the user's role.
      * Params:
@@ -31,6 +58,32 @@
       }
     }
 
+    /**
+     * Get external meetingID.
+     */  
+    BBB.getMyUserID = function(callback) {
+      var swfObj = getSwfObj();
+      if (swfObj) {
+        console.log("Getting my userID");
+        if (typeof callback === 'function') {
+          callback(swfObj.getMyUserID());
+        }
+      }
+    }
+    
+    /**
+     * Get external meetingID.
+     */  
+    BBB.getMeetingID = function(callback) {
+      var swfObj = getSwfObj();
+      if (swfObj) {
+        console.log("Getting external meetingID");
+        if (typeof callback === 'function') {
+          callback(swfObj.getExternalMeetingID());
+        }
+      }
+    }
+    
     /**
      * Join the voice conference.
      */  
@@ -42,16 +95,35 @@
       }
     }
     
+    BBB.leaveVoiceConference = function() {
+      var swfObj = getSwfObj();
+      if (swfObj) {
+        console.log("Leave voice");
+        swfObj.leaveVoiceRequest();
+      }
+    }
+    
     /**
      * Share user's webcam.
      */    
-    BBB.shareVideoCamera = function() {
+    BBB.shareVideoCamera = function(publishInClient) {
       var swfObj = getSwfObj();
       if (swfObj) {
-        swfObj.shareVideoCamera(); 
+        if (typeof publishInClient === 'boolean') {
+          swfObj.shareVideoCamera(publishInClient);
+        } else {
+          swfObj.shareVideoCamera();
+        }        
       }
     }
 
+    BBB.stopSharingCamera = function() {
+      var swfObj = getSwfObj();
+      if (swfObj) {
+        swfObj.stopShareCameraRequest();
+      }    
+    }
+    
     BBB.muteMe = function() {
       var swfObj = getSwfObj();
       if (swfObj) {
@@ -187,16 +259,32 @@
     
     /************************************************
      * EVENT NAME CONSTANTS
+     *
+     * See https://github.com/bigbluebutton/bigbluebutton/blob/master/bigbluebutton-client/src/org/bigbluebutton/core/EventConstants.as
+     *
      ************************************************/
-    var GET_MY_ROLE_REQ             = 'GetMyRoleRequest';
-    var SWITCH_LAYOUT_REQ           = 'SwitchLayoutRequest';
-    var JOIN_VOICE_REQ              = 'JoinVoiceRequest';
-    var MUTE_ALL_REQ                = 'MuteAllRequest';
-    var MUTE_ME_REQ                 = 'MuteMeRequest';
-    var SHARE_CAM_REQ               = 'ShareCameraRequest';
-    
-    
-    
+    var GET_MY_ROLE_RESP:String           = 'GetMyRoleResponse';
+    var AM_I_PRESENTER_RESP:String        = 'AmIPresenterQueryResponse';
+    var AM_I_SHARING_CAM_RESP:String      = 'AmISharingCamQueryResponse';
+    var BROADCASTING_CAM_STARTED:String   = 'BroadcastingCameraStartedEvent';
+    var BROADCASTING_CAM_STOPPED:String   = 'BroadcastingCameraStoppedEvent';
+    var I_AM_SHARING_CAM:String           = 'IAmSharingCamEvent';
+    var CAM_STREAM_SHARED:String          = 'CamStreamSharedEvent';
+    var USER_JOINED:String                = 'UserJoinedEvent';
+    var USER_LEFT:String                  = 'UserLeftEvent';
+    var SWITCHED_PRESENTER:String         = 'SwitchedPresenterEvent';
+    var NEW_PRIVATE_CHAT:String           = 'NewPrivateChatEvent';
+    var NEW_PUBLIC_CHAT:String            = 'NewPublicChatEvent';
+    var SWITCHED_LAYOUT:String            = 'SwitchedLayoutEvent';
+    var REMOTE_LOCKED_LAYOUT:String       = 'RemoteLockedLayoutEvent';
+    var REMOTE_UNLOCKED_LAYOUT:String     = 'RemoteUnlockedLayoutEvent';
+    var USER_JOINED_VOICE:String          = 'UserJoinedVoiceEvent';
+    var USER_LEFT_VOICE:String            = 'UserLeftVoiceEvent';
+    var USER_MUTED_VOICE:String           = 'UserVoiceMutedEvent';
+    var USER_TALKING:String               = 'UserTalkingEvent';
+    var USER_LOCKED_VOICE:String          = 'UserLockedVoiceEvent';
+    var START_PRIVATE_CHAT:String         = "StartPrivateChatEvent";
+           
     window.BBB = BBB;
 })(this);
 
diff --git a/bigbluebutton-client/resources/prod/lib/bbb_api_cam_preview.js b/bigbluebutton-client/resources/prod/lib/bbb_api_cam_preview.js
new file mode 100755
index 0000000000000000000000000000000000000000..fbff68dfaf5ddc776d4042f95980ec5915deb3bb
--- /dev/null
+++ b/bigbluebutton-client/resources/prod/lib/bbb_api_cam_preview.js
@@ -0,0 +1,44 @@
+(function(window, undefined) {
+
+    var CAM_PREVIEW = {};
+
+    /**
+     * Internal function to get the BBB embed object. Seems like we have to do this
+     * each time and can't create a var for it.
+     *
+     * To get the object, see https://code.google.com/p/swfobject/wiki/api
+     */
+    function getSwfObj() {
+      return swfobject.getObjectById("WebcamPreviewStandalone");
+    }
+
+   
+    /**
+     * Preview user's webcam.
+     */    
+    CAM_PREVIEW.previewCamera = function(camIndex, camWidth, camHeight, 
+                                          camKeyFrameInterval, camModeFps, 
+                                          camQualityBandwidth, camQualityPicture) {
+      console.log("CAM_PREVIEW::previewCamera [" + camIndex + "]");
+      var swfObj = getSwfObj();
+      if (swfObj) {
+          swfObj.startPreviewCamera(camIndex, camWidth, camHeight, camKeyFrameInterval, camModeFps, 
+                               camQualityBandwidth, camQualityPicture);    
+      }
+    }
+
+    /**
+     * Stop previewing user's webcam.
+     */ 
+    CAM_PREVIEW.stopPreviewCamera = function() {
+      var swfObj = getSwfObj();
+      if (swfObj) {
+          swfObj.stopPreviewCamera();    
+      }
+    }
+    
+    console.log("CAM_PREVIEW INITIALIZED");
+        
+    window.CAM_PREVIEW = CAM_PREVIEW;
+})(this);
+
diff --git a/bigbluebutton-client/resources/prod/lib/bbb_api_cam_view.js b/bigbluebutton-client/resources/prod/lib/bbb_api_cam_view.js
new file mode 100755
index 0000000000000000000000000000000000000000..6d950886c40db881ce4dd35eedc9259aea1b082a
--- /dev/null
+++ b/bigbluebutton-client/resources/prod/lib/bbb_api_cam_view.js
@@ -0,0 +1,42 @@
+(function(window, undefined) {
+
+    var CAM_VIEW = {};
+
+    /**
+     * Internal function to get the BBB embed object. Seems like we have to do this
+     * each time and can't create a var for it.
+     *
+     * To get the object, see https://code.google.com/p/swfobject/wiki/api
+     */
+    function getSwfObj() {
+      return swfobject.getObjectById("WebcamViewStandalone");
+    }
+
+   
+    /**
+     * View user's webcam.
+     */    
+    CAM_VIEW.viewWebcamStream = function(url, streamName) {
+      console.log("CAM_VIEW::viewWebcamStream [" + url + "," + streamName + "]");
+      
+      var swfObj = getSwfObj();
+      if (swfObj) {
+          console.log("CAM_VIEW::viewWebcamStream 2 [" + url + "," + streamName + "]");
+          swfObj.startViewCameraStream(url, streamName);    
+      }
+    }
+
+    /**
+     * Stop viewing user's webcam.
+     */ 
+    CAM_VIEW.stopViewWebcamStream = function() {
+      var swfObj = getSwfObj();
+      if (swfObj) {
+          swfObj.stopViewCameraStream();    
+      }
+    }
+    
+    console.log("CAM_VIEW INITIALIZED");    
+    window.CAM_VIEW = CAM_VIEW;
+})(this);
+
diff --git a/bigbluebutton-client/resources/streams.xml b/bigbluebutton-client/resources/streams.xml
new file mode 100755
index 0000000000000000000000000000000000000000..40142888eac86d0d747a1680d14186fa7e9d4e4c
--- /dev/null
+++ b/bigbluebutton-client/resources/streams.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" ?>
+<streams>
+    <stream url="rtmp://192.168.153.128/oflaDemo" id="hobbit_vp6" name="The Hobbit"/>
+    <stream url="rtmp://192.168.153.128/oflaDemo" id="startrekintodarkness_vp6" name="Star Trek"/>
+</streams>
diff --git a/bigbluebutton-client/src/BigBlueButton.mxml b/bigbluebutton-client/src/BigBlueButton.mxml
index 256721b1be52171decd04b3984985a33ff7b8ecd..ec02dad430848f8ded23378a81e91846a843d192 100755
--- a/bigbluebutton-client/src/BigBlueButton.mxml
+++ b/bigbluebutton-client/src/BigBlueButton.mxml
@@ -25,12 +25,11 @@
   xmlns:apimap="org.bigbluebutton.main.api.maps.*"
   xmlns:coreMap="org.bigbluebutton.core.controllers.maps.*"
   xmlns:mate="http://mate.asfusion.com/"
-  xmlns:m="library://melomel/2010"
   pageTitle="BigBlueButton" 
   layout="absolute" preinitialize="init()"
   preloader="org.bigbluebutton.main.model.BigBlueButtonPreloader"
   applicationComplete="hotkeyCapture()">
-  
+ 
   <mx:Script>
     <![CDATA[
       import com.asfusion.mate.events.Dispatcher;      
@@ -50,7 +49,6 @@
       import org.bigbluebutton.util.i18n.ResourceUtil;
       private var langResources:ResourceUtil = null; //ResourceUtil.getInstance();
 
-      public var myFoo:String = "bar";
 
     /**
      * Thse two lines are workaround for this. (ralam - Nov 8, 2008)
@@ -63,147 +61,8 @@
     /** another workaround - for this issue: https://bugs.adobe.com/jira/browse/SDK-13121*/
     private var hist:HistoryManager
 
-    private function handleChatEvent(e:Event):void {
-      trace('Got CHAT_EVENT');
-    }
-
-    public function setFoo(f:String):void {
-      myFoo = f;
-    }
-
-    /******************************
-     * Testing
-     ******************************/
-
     private var globalDispatcher:Dispatcher = new Dispatcher();
 
-    // Login test
-    private static var isLoggedIn:Boolean = false;	// flag to indicate if we successfully logged in
-    
-    // Chat test
-    private static var chatMessageSent:String = "";
-    private static var chatTestSucceeded:Boolean = false;
-  
-    // Voice test
-    private static var didUserJoin:Boolean = false;
-    
-    // Presentation test
-    private static var didPresentationConvert:Boolean = false;
-
-    // Video test
-    private static var didVideoStart:Boolean = false;
-
-
-    public  function handleLoginEvent(event:BBBEvent):void {
-      LogUtil.debug("******************* Received loggedin event");
-      isLoggedIn = true;
-      LogUtil.debug("******************* Received loggedin event " + isLoggedIn.toString());
-    }
-
-    public function checkLogin():String {
-      LogUtil.debug("******************* " + isLoggedIn.toString());
-      return isLoggedIn.toString();
-    }
-
-    public function checkChat():String {
-      if (chatTestSucceeded)
-      {
-          chatTestSucceeded = false;
-          return "true";
-      } else {
-        return chatTestSucceeded.toString();
-      }
-    }
-
-    public function handleReceivedPublicChatMessageEvent(event:BBBEvent):void {
-      if (event.message.search(chatMessageSent) != -1) {
-        chatTestSucceeded = true;
-      }
-    }
-
-    // Creates a random string and sends it as a chat message.
-    public function sendRandomChatMessage():void {
-      chatMessageSent = generateRandomString(15);
-      globalDispatcher.dispatchEvent(new BBBEvent(BBBEvent.SEND_PUBLIC_CHAT_MESSAGE_EVENT, chatMessageSent));
-    }
-
-    /**
-     * Voice
-     */ 
-    public function joinVoiceConference():void {
-      globalDispatcher.dispatchEvent(new BBBEvent(BBBEvent.JOIN_VOICE_CONFERENCE));
-    }
-
-    public function checkVoice():String {
-      return didUserJoin.toString();
-    }
-
-    public function handleAddedListenerEvent(event:BBBEvent):void {
-      // if (event.message == _attributes.username) {
-      didUserJoin = true;
-      // }
-    }
-  
-    /**
-     * Presentation
-     */ 
-
-    public function checkPresentation():String {
-      if (didPresentationConvert) {
-        didPresentationConvert = false;
-        return "true";
-      } else {
-        return "false";
-      }
-    }
-      
-    public function handlePresentationConversion(event:Event):void {
-      didPresentationConvert = true;
-    }
-
-    // Obtained from: http://www.zedia.net/2008/generate-random-strings-in-as2-or-as3/
-    private function generateRandomString(newLength:uint = 1, userAlphabet:String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"):String{
-      var alphabet:Array = userAlphabet.split("");
-      var alphabetLength:int = alphabet.length;
-      var randomLetters:String = "";
-      for (var i:uint = 0; i < newLength; i++){
-        randomLetters += alphabet[int(Math.floor(Math.random() * alphabetLength))];
-      }
-      return randomLetters;
-    }
-
-
-    /**
-      * Video
-      */
-
-    public function startVideoConnection():String {
-      globalDispatcher.dispatchEvent(new BBBEvent(BBBEvent.START_VIDEO_CONNECTION));
-      return "true";
-    }
-
-    public function playVideo():String {
-      globalDispatcher.dispatchEvent(new BBBEvent(BBBEvent.START_VIDEO_STREAM, "640x480avatar.flv"));
-      return "true";
-    }
-
-    public function videoHasStarted(e:Event):void {
-      didVideoStart = true;
-    }
-  
-    public function checkVideo():String {
-      return didVideoStart.toString();
-    }
-
-    /**
-     * Desktop Sharing
-     */
-
-    public function startDeskshare():String {
-      globalDispatcher.dispatchEvent(new BBBEvent(BBBEvent.START_DESKSHARE));
-      return "true";
-    }
-
     protected function init():void {
       setupAPI();
       EventBroadcaster.getInstance().addEventListener("configLoadedEvent", configLoadedEventHandler);
@@ -226,17 +85,13 @@
       
       private function determineHTMLURL():String {
         var serverName:String = "*";
-        if(ExternalInterface.available) // import flash.external.ExternalInterface;
-        {
-          try
-          {
+        if(ExternalInterface.available) {
+          try {
             var htmlURL:String = String(ExternalInterface.call("window.location.href.toString"));
             serverName = URLUtil.getServerName(htmlURL);
-//            Alert.show("HTML URL [" + htmlURL + "]");
-          }
-          catch(s:Error)
-          {
-//            Alert.show("Cannot determine HTML URL");
+            trace("HTML URL [" + htmlURL + "]");
+          } catch(s:Error) {
+            trace("Cannot determine HTML URL");
           }
         }
         
@@ -263,10 +118,10 @@
     }
 
     public function hotkeyCapture():void{
-      LogUtil.debug("Entering hotkeyCapture");
+      trace("Entering hotkeyCapture");
       stage.addEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
       ResourceUtil.getInstance().addEventListener(Event.CHANGE, localeChanged); // Listen for locale changing
-      LogUtil.debug("Leaving hotkeyCapture");
+      trace("Leaving hotkeyCapture");
     }
 
     public function handleKeyDown(e:KeyboardEvent) :void
@@ -277,7 +132,7 @@
 
       if (keyCombos[keyPress])
       {
-        LogUtil.debug("Chad keypress " + keyPress);
+        trace("Chad keypress " + keyPress);
         globalDispatcher.dispatchEvent(new ShortcutEvent(keyCombos[keyPress]));
       }
     }
@@ -289,9 +144,4 @@
   <maps:ApplicationEventMap />	
   <views:MainApplicationShell id="mainShell"/>	
   
-  <mate:Listener type="{BBBEvent.LOGIN_EVENT}" method="handleLoginEvent"/>
-  <mate:Listener type="{BBBEvent.RECEIVED_PUBLIC_CHAT_MESSAGE_EVENT}" method="handleReceivedPublicChatMessageEvent"/>
-  <mate:Listener type="{BBBEvent.ADDED_LISTENER}" method="handleAddedListenerEvent"/>
-  <mate:Listener type="{BBBEvent.PRESENTATION_CONVERTED}" method="handlePresentationConversion"/>
-  <mate:Listener type="{BBBEvent.VIDEO_STARTED}" method="videoHasStarted"/>
 </mx:Application>
diff --git a/bigbluebutton-client/src/BigBlueButtonTest.mxml b/bigbluebutton-client/src/BigBlueButtonTest.mxml
index 2271a1cd1b30d54a5c1e8da28f1027645946c31d..4a123eaf57f7282f77c0ff82716c11f68245ffc5 100755
--- a/bigbluebutton-client/src/BigBlueButtonTest.mxml
+++ b/bigbluebutton-client/src/BigBlueButtonTest.mxml
@@ -206,7 +206,7 @@
 	
 	<mate:Listener type="{BBBEvent.LOGIN_EVENT}" method="handleLoginEvent"/>
 	<mate:Listener type="{BBBEvent.RECEIVED_PUBLIC_CHAT_MESSAGE_EVENT}" method="handleReceivedPublicChatMessageEvent"/>
-	<mate:Listener type="{BBBEvent.ADDED_LISTENER}" method="handleAddedListenerEvent"/>
+	<mate:Listener type="{BBBEvent.USER_VOICE_JOINED}" method="handleAddedListenerEvent"/>
 	<mate:Listener type="{BBBEvent.PRESENTATION_CONVERTED}" method="handlePresentationConversion"/>
 	<mate:Listener type="{BBBEvent.VIDEO_STARTED}" method="videoHasStarted"/>
 	
diff --git a/bigbluebutton-client/src/BroadcastModule.mxml b/bigbluebutton-client/src/BroadcastModule.mxml
new file mode 100755
index 0000000000000000000000000000000000000000..3c0048c5bf676fb9661a6ea0f9f448d8c974ea7a
--- /dev/null
+++ b/bigbluebutton-client/src/BroadcastModule.mxml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  BigBlueButton open source conferencing system - http://www.bigbluebutton.org
+  
+  Copyright (c) 2010 BigBlueButton Inc. and by respective authors (see below).
+  
+  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 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/>.
+ 
+  $Id: $
+-->
+
+<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" 
+ 	xmlns:maps="org.bigbluebutton.modules.broadcast.maps.*"
+	xmlns:mate="http://mate.asfusion.com/"
+	implements="org.bigbluebutton.common.IBigBlueButtonModule"
+	creationComplete="onCreationComplete()">
+	
+	<maps:BroadcastEventMap id="broadcastEventMap" />
+	
+	<mx:Script>
+		<![CDATA[
+			import com.asfusion.mate.events.Dispatcher;			
+			import org.bigbluebutton.common.LogUtil;
+
+			private var _moduleName:String = "Broadcast Module";			
+			private var _attributes:Object;
+			private var dispatcher:Dispatcher = new Dispatcher();
+			
+			private function onCreationComplete():void {
+				LogUtil.debug("BrodcastModule Initialized");			
+			}
+			
+			public function get moduleName():String {
+				return _moduleName;
+			}
+
+			public function start(attributes:Object):void {	
+				LogUtil.debug("***Starting BroadcastModule");
+				dispatcher.dispatchEvent(new Event("BroadcastModuleStartEvent"));	
+			}
+		
+			public function stop():void {
+				LogUtil.debug("Stop Broadcast Module");
+				
+			}
+
+		]]>
+	</mx:Script>
+</mx:Module>
diff --git a/bigbluebutton-client/src/DeskshareStandalone.mxml b/bigbluebutton-client/src/DeskshareStandalone.mxml
index 002e1199a96f089d63a3be19cd6663bd846c4346..829c14967705685a5cc325ca6474b6327dc59f3f 100755
--- a/bigbluebutton-client/src/DeskshareStandalone.mxml
+++ b/bigbluebutton-client/src/DeskshareStandalone.mxml
@@ -34,7 +34,6 @@
 	<mx:Script>
 		<![CDATA[
 			import mx.controls.Image;
-
 			import org.bigbluebutton.modules.deskshare.events.CursorEvent;
 			import org.bigbluebutton.modules.deskshare.events.ViewStreamEvent;
 			import mx.controls.Button;
diff --git a/bigbluebutton-client/src/NotesModule.mxml b/bigbluebutton-client/src/NotesModule.mxml
new file mode 100755
index 0000000000000000000000000000000000000000..a4a8eed9ca7f537b794780877a6fcd04f0ed007f
--- /dev/null
+++ b/bigbluebutton-client/src/NotesModule.mxml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+
+  Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+
+  This program is free software; you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free Software
+  Foundation; either version 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/>.
+
+  Author: Felipe Cecagno <felipe@mconf.org>
+
+  $Id: $
+-->
+<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"
+			xmlns:maps="org.bigbluebutton.modules.notes.maps.*" 
+			implements="org.bigbluebutton.common.IBigBlueButtonModule">
+
+
+	<maps:NotesEventMap id="notesEventMap" />
+
+  
+	<mx:Script>
+		<![CDATA[
+      import com.asfusion.mate.events.Dispatcher;
+      
+      import org.bigbluebutton.common.LogUtil;
+      import org.bigbluebutton.modules.notes.events.NotesModuleStartEvent;
+			
+			private var _moduleName:String = "Layout Module";
+			private var _dispatcher:Dispatcher = new Dispatcher();
+      
+			private function onCreationComplete():void {
+				LogUtil.debug(_moduleName + " initialized");	
+			}
+			
+			public function get moduleName():String {
+				return _moduleName;
+			}
+			
+			public function start(attributes:Object):void {
+        _dispatcher.dispatchEvent(new NotesModuleStartEvent());
+			}
+			
+			public function stop():void {
+
+			}
+			
+		]]>
+	</mx:Script>
+</mx:Module>
\ No newline at end of file
diff --git a/bigbluebutton-client/src/VideoconfModule.mxml b/bigbluebutton-client/src/VideoconfModule.mxml
index 7b1578361c6b68f81d19be48203dbc8b40ae06eb..3ea6ac8494415776cbdb7582a62d839635146490 100755
--- a/bigbluebutton-client/src/VideoconfModule.mxml
+++ b/bigbluebutton-client/src/VideoconfModule.mxml
@@ -3,22 +3,20 @@
 	xmlns:maps="org.bigbluebutton.modules.videoconf.maps.*" implements="org.bigbluebutton.common.IBigBlueButtonModule">
 	<mx:Script>
 		<![CDATA[
-			import org.bigbluebutton.modules.videoconf.events.ShareCameraRequestEvent;
-			import com.asfusion.mate.events.Dispatcher;
-			
-			import mx.controls.Alert;
-			
-			import org.bigbluebutton.common.LogUtil;
-			import org.bigbluebutton.common.events.CloseWindowEvent;
-			import org.bigbluebutton.common.events.OpenWindowEvent;
-			import org.bigbluebutton.modules.videoconf.business.VideoProxy;
-			import org.bigbluebutton.modules.videoconf.events.CloseAllWindowsEvent;
+      import com.asfusion.mate.events.Dispatcher;
+      
+      import org.bigbluebutton.common.LogUtil;
+      import org.bigbluebutton.common.events.CloseWindowEvent;
+      import org.bigbluebutton.common.events.OpenWindowEvent;
+      import org.bigbluebutton.modules.videoconf.business.VideoProxy;
+      import org.bigbluebutton.modules.videoconf.events.CloseAllWindowsEvent;
+      import org.bigbluebutton.modules.videoconf.events.ShareCameraRequestEvent;
+      import org.bigbluebutton.modules.videoconf.events.VideoModuleStartEvent;
+      import org.bigbluebutton.modules.videoconf.events.VideoModuleStopEvent;
 			
 			private var _moduleName:String = "Videoconf Module";			
 			private var _attributes:Object; 
-			private var proxy:VideoProxy;
-			private var mockProxy:VideoProxy;
-			
+		
 			private function onCreationComplete():void {
 				LogUtil.debug("VideoconfModule initialized");	
 			}
@@ -38,15 +36,7 @@
 			public function get username():String {
 				return _attributes.username;
 			}
-			
-			public function get connection():NetConnection {
-				return proxy.connection;
-			}
-			
-			public function get mockConnection():NetConnection {
-				return mockProxy.connection;
-			}
-			
+					
 			public function get mode():String {
 				if (_attributes.mode == null) {					
 					//_attributes.mode = "PLAYBACK"
@@ -79,27 +69,16 @@
 			}
 			
 			public function start(attributes:Object):void {	
-				LogUtil.debug("Videoconf attr: " + attributes.username);
-				_attributes = attributes;
-				proxy = new VideoProxy(uri);
-				
-				eventMap.module = this;
-				eventMap.proxy = proxy;
-				eventMap.addToolbarButton();
-				
-				if (proxy.videoOptions.autoStart) {
-					var dispatcher:Dispatcher = new Dispatcher();        
-					dispatcher.dispatchEvent(new ShareCameraRequestEvent());					
-				}
+        trace("Starting Video Module");
+        var globalDispatcher:Dispatcher = new Dispatcher();
+        globalDispatcher.dispatchEvent(new VideoModuleStartEvent(VideoModuleStartEvent.START));
 			}
 		
 			public function stop():void {
-				eventMap.stopModule();
+        var globalDispatcher:Dispatcher = new Dispatcher();
+        globalDispatcher.dispatchEvent(new VideoModuleStopEvent(VideoModuleStopEvent.STOP));
 			}
 			
-			public function mockConnect():void {
-				mockProxy = new VideoProxy(proxy.connection.uri.substring(0, proxy.connection.uri.indexOf("video") + 5));
-			}
 		]]>
 	</mx:Script>
 	
diff --git a/bigbluebutton-client/src/WebcamPreviewStandalone.mxml b/bigbluebutton-client/src/WebcamPreviewStandalone.mxml
new file mode 100755
index 0000000000000000000000000000000000000000..ff5a23afd306a19ea8f7d88879a4b8f8fec8e399
--- /dev/null
+++ b/bigbluebutton-client/src/WebcamPreviewStandalone.mxml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  BigBlueButton open source conferencing system - http://www.bigbluebutton.org
+  
+  Copyright (c) 2010 BigBlueButton Inc. and by respective authors (see below).
+  
+  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 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/>.
+ 
+  $Id: $
+-->
+
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
+	creationComplete="onCreationComplete()"
+	pageTitle="WebcamPreview" width="600" height="400" layout="absolute">	
+  <mx:Script>
+    <![CDATA[    
+      import mx.core.UIComponent;
+      import mx.utils.URLUtil;
+      
+      [Bindable] private var defaultWidth:Number = 320;
+      [Bindable] private var defaultHeight:Number = 240;
+      
+      private var _video:Video;
+      private var _videoHolder:UIComponent;
+      private var camIndex:int = 0;
+      private var camWidth:Number = 320;
+      private var camHeight:Number = 240;
+      private var _camera:Camera = null;
+      private var quality:Number = 0;
+      private var PADDING_HORIZONTAL:Number = 6;
+      private var PADDING_VERTICAL:Number = 29;
+      private var _minWidth:int = 160 + PADDING_HORIZONTAL;
+      private var _minHeight:int = 120 + PADDING_VERTICAL;
+      private var aspectRatio:Number = 1;
+                     
+      private function onCreationComplete():void{
+        _videoHolder = new UIComponent();
+        _videoHolder.width = camWidth;
+        _videoHolder.height = camHeight;
+        this.addChild(_videoHolder);				
+        
+        this.minWidth = _minWidth;
+        this.minHeight = _minHeight;
+
+        trace('WebcamPreviewSA::onCreationComplete');
+        Security.allowDomain(determineHTMLURL());
+        trace("WebcamPreviewSA:: Security.allowDomain(" + determineHTMLURL() + ");");
+        
+        initExternalInterface();
+//        displayCamera("0", 30, 10, 0, 90);
+      }
+      
+      private function determineHTMLURL():String {
+        var serverName:String = "*";
+        if(ExternalInterface.available) {
+          try {
+            var htmlURL:String = String(ExternalInterface.call("window.location.href.toString"));
+            serverName = URLUtil.getServerName(htmlURL);
+            trace("WebcamPreviewSA::determineHTMLURL HTML URL [" + htmlURL + "]");
+          } catch(s:Error) {
+            trace("WebcamPreviewSA::determineHTMLURL Cannot determine HTML URL");
+          }
+        }
+        
+        return serverName;
+      }
+      
+      private function initExternalInterface():void {
+        trace('WebcamPreviewSA::initExternalInterface');
+        if (ExternalInterface.available) {
+          ExternalInterface.addCallback("startPreviewCamera", handleStartPreviewCameraRequest);
+          ExternalInterface.addCallback("stopPreviewCamera", handleStopPreviewCamera);
+        }
+      }
+      
+      private function handleStartPreviewCameraRequest(camIndex:String, camWidth:int, camHeight:int,
+                                                                        camKeyFrameInterval:int, camModeFps:Number, 
+                                                                        camQualityBandwidth:int, camQualityPicture:int):void {
+        displayCamera(camIndex, camWidth, camHeight, camKeyFrameInterval, camModeFps, camQualityBandwidth, camQualityPicture);
+      }
+      
+      private function handleStopPreviewCamera():void {
+        stopCamera();
+      }
+          
+      public function displayCamera(camIndex:String, camWidth:int, camHeight:int, camKeyFrameInterval:int, camModeFps:Number, camQualityBandwidth:int, camQualityPicture:int):void {
+        trace('WebcamPreviewSA::displayCamera');
+        stopCamera();
+        
+        if (Camera.names.length == 0) {
+          trace('WebcamPreviewSA::bbb.video.publish.hint.noCamera');
+          return;
+        }
+        
+        _camera = Camera.getCamera(camIndex);
+        if (_camera == null) {
+          trace('WebcamPreviewSA::bbb.video.publish.hint.cantOpenCamera');
+          return;
+        }
+        
+        setResolution(camWidth, camHeight);
+        
+        _camera.setMotionLevel(5, 1000);
+               
+        _camera.setKeyFrameInterval(camKeyFrameInterval);
+        _camera.setMode(camWidth, camHeight, camModeFps);
+        _camera.setQuality(camQualityBandwidth, camQualityPicture);
+        
+        if (_camera.width != camWidth || _camera.height != camHeight) {
+          trace("WebcamPreviewSA::Resolution " + camWidth + "x" + camHeight + " is not supported, using " + _camera.width + "x" + _camera.height + " instead");
+          setResolution(_camera.width, _camera.height);
+        }				
+        
+        _video = new Video;
+        _video.attachCamera(_camera);
+        
+        if (aspectRatio > _videoHolder.width / _videoHolder.height) {
+          _video.width = _videoHolder.width;
+          _video.height = _videoHolder.width / aspectRatio;
+          _video.x = 0;
+          _video.y = (_videoHolder.height - _video.height) / 2;
+        } else {
+          _video.width = _videoHolder.height * aspectRatio;
+          _video.height = _videoHolder.height;
+          _video.x = (_videoHolder.width - _video.width) / 2;
+          _video.y = 0;
+        }				
+        
+        _videoHolder.addChild(_video);        
+      }
+              
+      private function stopCamera():void {
+        _camera = null;
+        if (_video != null) {
+          _videoHolder.removeChild(_video);
+          _video.attachCamera(null);
+          _video.clear();
+          _video = null;
+        }        
+      }
+      
+      private function setResolution(width:int, height:int):void {
+        camWidth  = width;
+        camHeight = height;
+        setAspectRatio(camWidth, camHeight);        
+      }
+      
+      private function setAspectRatio(width:int, height:int):void {
+        aspectRatio = (width/height);
+        this.minHeight = Math.floor((this.minWidth - PADDING_HORIZONTAL) / aspectRatio) + PADDING_VERTICAL;
+      }
+      
+      
+    ]]>
+  </mx:Script>
+   
+</mx:Application>
diff --git a/bigbluebutton-client/src/WebcamViewStandalone.mxml b/bigbluebutton-client/src/WebcamViewStandalone.mxml
new file mode 100755
index 0000000000000000000000000000000000000000..30cf9e97bf0f570c68c65d77d9a77f8333c80825
--- /dev/null
+++ b/bigbluebutton-client/src/WebcamViewStandalone.mxml
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+BigBlueButton open source conferencing system - http://www.bigbluebutton.org
+
+Copyright (c) 2010 BigBlueButton Inc. and by respective authors (see below).
+
+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 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/>.
+
+$Id: $
+-->
+
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
+                creationComplete="onCreationComplete()"
+                pageTitle="WebcamView" width="600" height="400" layout="absolute">	
+  <mx:Script>
+    <![CDATA[
+      import flash.net.NetConnection;
+      
+      import mx.core.UIComponent;
+      import mx.utils.URLUtil;
+      
+      private var _video:Video;
+      private var _videoHolder:UIComponent;      
+      private var ns:NetStream;			
+      private var nc:NetConnection;
+      private var PADDING_HORIZONTAL:Number = 6;
+      private var PADDING_VERTICAL:Number = 29;
+      private var _minWidth:int = 160 + PADDING_HORIZONTAL;
+      private var _minHeight:int = 120 + PADDING_VERTICAL;
+      private var aspectRatio:Number = 1;
+      private var camWidth:Number = 320;
+      private var camHeight:Number = 240;
+      
+      private var _url:String;
+      private var _stream:String;
+      
+      private var smoothVideo:Boolean = false;
+      private var applyConvolutionFilter:Boolean = false;
+      private var convolutionFilter:Array = [-1, 0, -1, 0, 6, 0, -1, 0, -1];
+      private var filterBias:Number = 0;
+      private var filterDivisor:Number = 4;
+      private var enableH264:Boolean = false;
+      private var h264Level:String = "2.1";	
+      private var h264Profile:String = "main";	
+      
+      private function onCreationComplete():void{
+        _videoHolder = new UIComponent();
+        _videoHolder.width = camWidth;
+        _videoHolder.height = camHeight;
+        this.addChild(_videoHolder);
+        
+        this.minWidth = _minWidth;
+        this.minHeight = _minHeight;
+        
+        Security.allowDomain(determineHTMLURL());
+        trace("WebcamViewSA:: Security.allowDomain(" + determineHTMLURL() + ");");
+        
+        initExternalInterface();
+      }
+      
+      private function determineHTMLURL():String {
+        var serverName:String = "*";
+        if(ExternalInterface.available) {
+          try {
+            var htmlURL:String = String(ExternalInterface.call("window.location.href.toString"));
+            serverName = URLUtil.getServerName(htmlURL);
+            trace("WebcamViewSA::determineHTMLURL HTML URL [" + htmlURL + "]");
+          } catch(s:Error) {
+            trace("WebcamViewSA::determineHTMLURL Cannot determine HTML URL");
+          }
+        }
+        
+        return serverName;
+      }
+      
+      private function initExternalInterface():void {
+        trace('WebcamViewSA::initExternalInterface');
+        if (ExternalInterface.available) {
+          ExternalInterface.addCallback("startViewCameraStream", handleStartViewCameraRequest);
+          ExternalInterface.addCallback("stopViewCameraStream", handleStopViewCamera);
+        }
+      }
+      
+      private function connect(url:String):void {
+        nc = new NetConnection();
+        nc.client = this;
+        nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
+        nc.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
+        nc.addEventListener(NetStatusEvent.NET_STATUS, onNetConnectStatus);
+        nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
+        nc.connect(url);
+      }
+     
+      public function onBWCheck(... rest):Number { 
+        return 0; 
+      } 
+      
+      public function onBWDone(... rest):void { 
+        var p_bw:Number; 
+        if (rest.length > 0) p_bw = rest[0]; 
+        // your application should do something here 
+        // when the bandwidth check is complete 
+        trace("WebcamViewSA:: bandwidth = " + p_bw + " Kbps."); 
+      }
+      
+      private function getVideoResolution(stream:String):Array {
+        var pattern:RegExp = new RegExp("(\\d+x\\d+)-([A-Za-z0-9]+)-\\d+", "");
+        if (pattern.test(stream)) {
+          trace("WebcamViewSA:: The stream name is well formatted [" + stream + "]");
+          trace("WebcamViewSA:: Stream resolution is [" + pattern.exec(stream)[1] + "]");
+          trace("WebcamViewSA:: Userid [" + pattern.exec(stream)[2] + "]");
+          return pattern.exec(stream)[1].split("x");
+        } else {
+          trace("WebcamViewSA:: The stream name doesn't follow the pattern <width>x<height>-<userId>-<timestamp>. Using 320x240 resolution.");
+          return "320x240".split("x");
+        }
+      }
+      
+    
+      private function onIOError(event:NetStatusEvent):void{
+      }
+           
+      private function onNetConnectStatus(event:NetStatusEvent):void{
+        switch(event.info.code){
+          case "NetConnection.Connect.Success":
+            playWebcamStream();
+            break;
+          default:
+            trace("WebcamViewSA:: [" + event.info.code + "] for [" + _url + "]");
+            break;
+        }
+      }
+      
+      private function onSecurityError(event:NetStatusEvent):void{
+      }
+      
+      private function handleStartViewCameraRequest(url:String, stream:String):void {
+        _url = url;
+        _stream = stream;
+        connect(url);
+      }
+      
+      private function handleStopViewCamera():void {
+        stopViewing();
+      }
+      
+      private function stopViewing():void {
+        if (_video != null) {
+          trace("WebcamViewSA:: removing video from holder");
+          _videoHolder.removeChild(_video);
+          _video.clear();
+          _video = null;
+        }
+        _videoHolder.visible = false;
+        trace("WebcamViewSA:: closing stream");
+        ns.close();
+      }
+      
+      private function playWebcamStream():void {
+        ns = new NetStream(nc);
+        ns.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
+        ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
+        ns.client = this;
+        ns.bufferTime = 0;
+        ns.receiveVideo(true);
+        ns.receiveAudio(false);
+        
+        var res:Array = getVideoResolution(_stream);
+        if (res == null) // error
+          return;
+        _video = new Video(Number(res[0]), Number(res[1]));
+        _video.width = Number(res[0]);
+        _video.height = Number(res[1]);
+        trace("WebcamViewSA:: resolution [" + _video.width + "," + _video.height + "]");
+        setAspectRatio(Number(res[0]), Number(res[1])); 
+        _video.attachNetStream(ns);
+        
+        _video.smoothing = smoothVideo;
+        
+        if (applyConvolutionFilter) {
+          var filter:ConvolutionFilter = new flash.filters.ConvolutionFilter();
+          filter.matrixX = 3;
+          filter.matrixY = 3;					
+          filter.matrix = convolutionFilter;
+          filter.bias =  filterBias;
+          filter.divisor = filterDivisor;
+          _video.filters = [filter];					
+        }
+        
+        trace("WebcamViewSA:: adding video to video holder");
+        
+        _videoHolder.addChild(_video);
+        
+        _videoHolder.visible = true;
+        ns.play(_stream);       
+      }
+      
+      private function onAsyncError(e:AsyncErrorEvent):void{
+        trace("WebcamViewSA::asyncerror " + e.toString());
+      }
+      
+      public function onMetaData(info:Object):void{
+        trace("WebcamViewSA:: metadata: width=" + info.width + " height=" + info.height);
+        _video.width = info.width;
+        _video.height = info.height;
+        setAspectRatio(info.width, info.height);
+      }
+      
+      private function onNetStatus(e:NetStatusEvent):void{
+        switch(e.info.code){
+          case "NetStream.Publish.Start":
+            trace("WebcamViewSA:: NetStream.Publish.Start");
+            break;
+          case "NetStream.Play.UnpublishNotify":
+            trace("WebcamViewSA:: NetStream.Play.UnpublishNotify");
+            stopViewing();
+            break;
+          case "NetStream.Play.Start":
+            trace("WebcamViewSA:: Netstatus: " + e.info.code);					
+            break;
+          case "NetStream.Play.FileStructureInvalid":
+            trace("WebcamViewSA:: The MP4's file structure is invalid.");
+            break;
+          case "NetStream.Play.NoSupportedTrackFound":
+            trace("WebcamViewSA:: The MP4 doesn't contain any supported tracks");
+            break;
+        }
+      }
+      
+      private function setAspectRatio(width:int, height:int):void {
+        aspectRatio = (width/height);
+        this.minHeight = Math.floor((this.minWidth - PADDING_HORIZONTAL) / aspectRatio) + PADDING_VERTICAL;
+      }
+           
+    ]]>
+  </mx:Script>
+   
+</mx:Application>
diff --git a/bigbluebutton-client/src/assets/images/delete.png b/bigbluebutton-client/src/assets/images/delete.png
new file mode 100755
index 0000000000000000000000000000000000000000..0059eaa72ce11f79b11fb2fa0d5c3e225ca6c11a
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/delete.png differ
diff --git a/bigbluebutton-client/src/assets/images/elipse.png b/bigbluebutton-client/src/assets/images/elipse.png
new file mode 100755
index 0000000000000000000000000000000000000000..3252b6aa957f272a4c0ae8ea14213464681cba7d
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/elipse.png differ
diff --git a/bigbluebutton-client/src/assets/images/fit-to-screen.png b/bigbluebutton-client/src/assets/images/fit-to-screen.png
new file mode 100755
index 0000000000000000000000000000000000000000..0f83d20bedc8a35bced16f37b0e6cd2f6277d81f
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/fit-to-screen.png differ
diff --git a/bigbluebutton-client/src/assets/images/fit-to-width.png b/bigbluebutton-client/src/assets/images/fit-to-width.png
new file mode 100755
index 0000000000000000000000000000000000000000..12b052798435720aca6d0c94e43073e4eac5a1d4
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/fit-to-width.png differ
diff --git a/bigbluebutton-client/src/assets/images/hand.png b/bigbluebutton-client/src/assets/images/hand.png
new file mode 100755
index 0000000000000000000000000000000000000000..d923194e5ed2ccd5ac57a456540474727d6531b4
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/hand.png differ
diff --git a/bigbluebutton-client/src/assets/images/left_arrow.png b/bigbluebutton-client/src/assets/images/left_arrow.png
new file mode 100755
index 0000000000000000000000000000000000000000..e6abeb60d45d8a2a2b0f85b741f1af14683a4c4c
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/left_arrow.png differ
diff --git a/bigbluebutton-client/src/assets/images/line.png b/bigbluebutton-client/src/assets/images/line.png
new file mode 100755
index 0000000000000000000000000000000000000000..175174a0ea5ebb32535ad19ccd0a86a319496bb9
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/line.png differ
diff --git a/bigbluebutton-client/src/assets/images/pencil.png b/bigbluebutton-client/src/assets/images/pencil.png
new file mode 100755
index 0000000000000000000000000000000000000000..dd979748baebc063f532af178489732ab0c4548f
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/pencil.png differ
diff --git a/bigbluebutton-client/src/assets/images/right_arrow.png b/bigbluebutton-client/src/assets/images/right_arrow.png
new file mode 100755
index 0000000000000000000000000000000000000000..6eab9f047a5ecd05d65ac1dae3f226b80009347d
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/right_arrow.png differ
diff --git a/bigbluebutton-client/src/assets/images/square.png b/bigbluebutton-client/src/assets/images/square.png
new file mode 100755
index 0000000000000000000000000000000000000000..48b5280bdb794d3d5de562af781f3affeda59ffc
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/square.png differ
diff --git a/bigbluebutton-client/src/assets/images/text.png b/bigbluebutton-client/src/assets/images/text.png
new file mode 100755
index 0000000000000000000000000000000000000000..21858b8ca4c28e93acb3eddd665860cf214d3bcf
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/text.png differ
diff --git a/bigbluebutton-client/src/assets/images/triangle.png b/bigbluebutton-client/src/assets/images/triangle.png
new file mode 100755
index 0000000000000000000000000000000000000000..f629ee6aebb3c600c700ef3eb54cbf59917dd70b
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/triangle.png differ
diff --git a/bigbluebutton-client/src/assets/images/undo.png b/bigbluebutton-client/src/assets/images/undo.png
new file mode 100755
index 0000000000000000000000000000000000000000..f65e9db3edf0cd4f2ee09b2a463e8436c19894d3
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/undo.png differ
diff --git a/bigbluebutton-client/src/assets/images/upload.png b/bigbluebutton-client/src/assets/images/upload.png
new file mode 100755
index 0000000000000000000000000000000000000000..724a094ae6974c1fd6e451ed492a06955e538ed2
Binary files /dev/null and b/bigbluebutton-client/src/assets/images/upload.png differ
diff --git a/bigbluebutton-client/src/branding/css/Blue.css b/bigbluebutton-client/src/branding/css/Blue.css
deleted file mode 100755
index 86a6b807a8228e8f2608e74ca809ce21866ca8b7..0000000000000000000000000000000000000000
--- a/bigbluebutton-client/src/branding/css/Blue.css
+++ /dev/null
@@ -1,173 +0,0 @@
-Application 
-{  
-   backgroundColors: #000000,#3f3f3f;
-   backgroundImage: Embed(source="assets/img/bk3.jpg");
-   backgroundSize: "100%";
-   backgroundGradientColors: #B4BFCF, #78829C;
-   themeColor: #0094C7;
-   backgroundGradientAlphas: 0.62, 0.26;
-}
-
-
-MDICanvas 
-{
-	backgroundColor: #0094C7;
-	backgroundAlpha: 0;
-}
-
-
-Button 
-{
-   highlightAlphas: 1, 0.33;
-   fillAlphas: 1, 0.16, 0.18, 1;
-   fillColors: #5f89b9, #697182, #ffffff, #eeeeee;
-}
-
-
-.mdiWindowFocus 
-{
-	headerHeight: 26;
-	roundedBottomCorners: true;
-	backgroundAlpha: 1;
-	backgroundColor: #FFFFFF;
-	backgroundImage: Embed(source="assets/swf/Blue.swf", symbol="Window_Background");
-	backgroundSize: '100%';
-	
-	borderStyle: solid;
-	borderColor: #ffffff;
-	borderAlpha: 1;
-	borderThickness: 2;
-	borderThicknessLeft: 0;
-	borderThicknessTop: 0;
-	borderThicknessBottom: 0;
-	borderThicknessRight: 0;
-	cornerRadius: 4;
-	dropShadowEnabled: false;
-	titleStyleName: "mypanelTitle";
-	
-	cornerResizeImg: Embed(source="assets/swf/Blue.swf", symbol="Corner_Resize");
-	cornerResizeWidth: 15;
-	cornerResizeHeight: 15;
-	cornerResizePaddingRight: 2;
-	cornerResizePaddingBottom: 2;
-	
-	controlButtonWidth: 10;
-	controlButtonHeight: 10;
-	controlButtonGap: 4;
-}
-
-.mdiWindowNoFocus 
-{
-	headerHeight: 26;
-	roundedBottomCorners: true;
-	backgroundAlpha: 0.5;
-	backgroundImage: Embed(source="assets/swf/Blue.swf", symbol="Window_Background");
-	backgroundSize: '100%';
-	
-	borderStyle: solid;
-	borderColor: #ffffff;
-	borderAlpha: 1;
-	borderThickness: 2;
-	borderThicknessLeft: 0;
-	borderThicknessTop: 0;
-	borderThicknessBottom: 0;
-	borderThicknessRight: 0;
-	cornerRadius: 4;
-	dropShadowEnabled: false;
-	titleStyleName: "mypanelTitle";
-	
-	cornerResizeImg: Embed(source="assets/swf/Blue.swf", symbol="Corner_Resize");
-	cornerResizeWidth: 15;
-	cornerResizeHeight: 15;
-	cornerResizePaddingRight: 2;
-	cornerResizePaddingBottom: 2;
-	
-	controlButtonWidth: 10;
-	controlButtonHeight: 10;
-	controlButtonGap: 4;
-}
-
-.mypanelTitle 
-{
-	fontFamily: Arial;
-	fontSize: 12;
-	fontWeight: bold;
-	color: #ffffff;
-}
-
-
-.closeBtnFocus
-{
-	upSkin:        Embed('assets/img/3_closeButton.png');
-	overSkin:      Embed('assets/img/3_closeButton.png');
-	downSkin:      Embed('assets/img/3_closeButton.png');
-	disabledSkin:  Embed('assets/img/3_closeButton.png');
-}
-
-.closeBtnNoFocus
-{
-	upSkin:        Embed('assets/img/3_closeButton.png');
-	overSkin:      Embed('assets/img/3_closeButton.png');
-	downSkin:      Embed('assets/img/3_closeButton.png');
-	disabledSkin:  Embed('assets/img/3_closeButton.png');
-}
-
-
-.increaseBtnFocus
-{
-	upSkin:        Embed('assets/img/3_increaseButton.png');
-	overSkin:      Embed('assets/img/3_increaseButton.png');
-	downSkin:      Embed('assets/img/3_increaseButton.png');
-	disabledSkin:  Embed('assets/img/3_increaseButton.png');
-}
-
-.increaseBtnNoFocus
-{
-	upSkin:        Embed('assets/img/3_increaseButton.png');
-	overSkin:      Embed('assets/img/3_increaseButton.png');
-	downSkin:      Embed('assets/img/3_increaseButton.png');
-	disabledSkin:  Embed('assets/img/3_increaseButton.png');
-}
-
-
-.decreaseBtnFocus 
-{
-	upSkin:        Embed('assets/img/3_decreaseButton.png');
-	overSkin:      Embed('assets/img/3_decreaseButton.png');
-	downSkin:      Embed('assets/img/3_decreaseButton.png');
-	disabledSkin:  Embed('assets/img/3_decreaseButton.png');
-}
-
-.decreaseBtnNoFocus 
-{
-	upSkin:        Embed('assets/img/3_decreaseButton.png');
-	overSkin:      Embed('assets/img/3_decreaseButton.png');
-	downSkin:      Embed('assets/img/3_decreaseButton.png');
-	disabledSkin:  Embed('assets/img/3_decreaseButton.png');
-}
-
-
-.minimizeBtnFocus 
-{
-	upSkin:        Embed('assets/img/3_minimizeButton.png');
-	overSkin:      Embed('assets/img/3_minimizeButton.png');
-	downSkin:      Embed('assets/img/3_minimizeButton.png');
-	disabledSkin:  Embed('assets/img/3_minimizeButton.png');
-}
-
-.minimizeBtnNoFocus 
-{
-	upSkin:        Embed('assets/img/3_minimizeButton.png');
-	overSkin:      Embed('assets/img/3_minimizeButton.png');
-	downSkin:      Embed('assets/img/3_minimizeButton.png');
-	disabledSkin:  Embed('assets/img/3_minimizeButton.png');
-}
-
-
-.resizeHndlr 
-{
-	upSkin:        Embed('assets/img/resizeHandler.png');
-	overSkin:      Embed('assets/img/resizeHandler.png');
-	downSkin:      Embed('assets/img/resizeHandler.png');
-	disabledSkin:  Embed('assets/img/resizeHandler.png');
-}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/branding/css/BrushedMetal.css b/bigbluebutton-client/src/branding/css/BrushedMetal.css
deleted file mode 100755
index 4bb394c2c4183347670970143a46d57b6d8c21c1..0000000000000000000000000000000000000000
--- a/bigbluebutton-client/src/branding/css/BrushedMetal.css
+++ /dev/null
@@ -1,100 +0,0 @@
-Application
-{
-	
-	backgroundImage: Embed(source="assets/img/BrushedMetalBack.jpg"); 
-	backgroundSize: "100%";
-   themeColor: #999999;
-    fontFamily: Arial;
-    paddingLeft:10; paddingRight:10; paddingTop:10; paddingBottom:10;
-}
-
-.mdiWindowFocus 
-{
-	borderStyle: solid;
-   borderColor: #FFFFFF;
-   borderAlpha: 0;
-   borderThickness: 1;
-   borderThicknessLeft: 5;
-   borderThicknessTop: 5;
-   borderThicknessBottom: 15;
-   borderThicknessRight: 5;
-   roundedBottomCorners: true;
-   cornerRadius: 5;
-   headerHeight: 27;
-   
-   backgroundAlpha: 1; 
-   backgroundColor: #FFFFFF;
-   
-	backgroundImage: Embed(source="assets/swf/BrushedMetal.swf", symbol="Window_Background");
-	backgroundSize: "100%";
-	
-   dropShadowEnabled: true;
-	
-	
-	cornerResizeImg: Embed(source="assets/swf/BrushedMetal.swf", symbol="Corner_Resize");
-	cornerResizeWidth: 12;
-	cornerResizeHeight: 12;
-	cornerResizePaddingRight: 2;
-	cornerResizePaddingBottom: 2;
-	
-	titleStyleName: "mypanelTitle";
-	titleBackgroundSkin: Embed(source="assets/swf/BrushedMetal.swf", symbol="header");
-	
-	controlButtonWidth: 10;
-	controlButtonHeight: 10;
-	controlButtonGap: 8;
-}
-
-.mdiWindowNoFocus 
-{
-	borderStyle: solid;
-   borderColor: #FFFFFF;
-   borderAlpha: 0;
-   borderThickness: 1;
-   borderThicknessLeft: 5;
-   borderThicknessTop: 5;
-   borderThicknessBottom: 15;
-   borderThicknessRight: 5;
-   roundedBottomCorners: true;
-   cornerRadius: 5;
-   headerHeight: 27;
-   
-
-	
-   
-   backgroundAlpha: 1; 
-   backgroundColor: #FFFFFF;
-   
-	backgroundImage: Embed(source="assets/swf/BrushedMetal.swf", symbol="Window_Background");
-	backgroundSize: "100%";
-	
-   dropShadowEnabled: true;
-	
-	
-	cornerResizeImg: Embed(source="assets/swf/BrushedMetal.swf", symbol="Corner_Resize");
-	cornerResizeWidth: 12;
-	cornerResizeHeight: 12;
-	cornerResizePaddingRight: 2;
-	cornerResizePaddingBottom: 2;
-	
-	titleStyleName: "mypanelTitle";
-	titleBackgroundSkin: Embed(source="assets/swf/BrushedMetal.swf", symbol="header");
-	
-	controlButtonWidth: 10;
-	controlButtonHeight: 10;
-	controlButtonGap: 8;
-}
-
-
-
-.mypanelTitle {
-	fontSize: 12;
-	fontWeight: bold;
-	color: #000000;
-}
-
-
-Button {
-   fillColors: #ffffff, #999999, #ffffff, #eeeeee;
-   themeColor: #999999;
-}
diff --git a/bigbluebutton-client/src/branding/css/MacOS9.css b/bigbluebutton-client/src/branding/css/MacOS9.css
deleted file mode 100755
index 98a49cdf6ff985c94dab5d8906d12190932de7be..0000000000000000000000000000000000000000
--- a/bigbluebutton-client/src/branding/css/MacOS9.css
+++ /dev/null
@@ -1,83 +0,0 @@
-Application
-{
-	background-image: Embed(source="assets/img/wallpaperOS9.gif");
-}
-
-MDIWindow
-{
-	titleStyleName: "macTitle";
-}
-
-.macTitle
-{
-	fontFamily: Georgia;
-	fontSize: 12;
-	fontWeight: normal;
-	color: #000000;
-}
-
-.mdiWindowFocus
-{
-	borderColor: #CCCCCC;
-	borderAlpha: 1;
-	borderThicknessLeft: 2;
-	borderThicknessTop: 0;
-	borderThicknessBottom: 2;
-	borderThicknessRight: 2;
-	roundedBottomCorners: false;
-	cornerRadius: 5;
-	dropShadowEnabled: false;
-	headerHeight: 29;
-	backgroundAlpha: 1; 
-	backgroundColor: #FFFFFF;	
-	titleBackgroundSkin: Embed(source="assets/swf/WindowsAssets.swf", symbol="macHeaderFocus");
-}
-
-.mdiWindowNoFocus
-{
-	borderColor: #CCCCCC;
-	borderAlpha: 1;
-	borderThicknessLeft: 2;
-	borderThicknessTop: 0;
-	borderThicknessBottom: 2;
-	borderThicknessRight: 2;
-	roundedBottomCorners: false;
-	cornerRadius: 5;
-	dropShadowEnabled: false;
-	headerHeight: 29;
-	backgroundAlpha: 1; 
-	backgroundColor: #FFFFFF;
-	titleBackgroundSkin: Embed(source="assets/swf/WindowsAssets.swf", symbol="macHeaderNoFocus");
-}
-
-.mdiWindowMinimizeBtn
-{
-	upSkin:        Embed(source="assets/swf/WindowsAssets.swf", symbol="minimizeBtnOS9");
-	overSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="minimizeBtnOS9");
-	downSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="minimizeBtnOS9");
-	disabledSkin:  Embed(source="assets/swf/WindowsAssets.swf", symbol="minimizeBtnOS9");
-}
-
-.mdiWindowMaximizeBtn
-{
-	upSkin:        Embed(source="assets/swf/WindowsAssets.swf", symbol="maxRestoreBtnOS9");
-	overSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="maxRestoreBtnOS9");
-	downSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="maxRestoreBtnOS9");
-	disabledSkin:  Embed(source="assets/swf/WindowsAssets.swf", symbol="maxRestoreBtnOS9");
-}
-
-.mdiWindowRestoreBtn
-{
-	upSkin:        Embed(source="assets/swf/WindowsAssets.swf", symbol="maxRestoreBtnOS9");
-	overSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="maxRestoreBtnOS9");
-	downSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="maxRestoreBtnOS9");
-	disabledSkin:  Embed(source="assets/swf/WindowsAssets.swf", symbol="maxRestoreBtnOS9");
-}
-
-.mdiWindowCloseBtn
-{
-	upSkin:        Embed(source="assets/swf/WindowsAssets.swf", symbol="closeBtnOS9");
-	overSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="closeBtnOS9");
-	downSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="closeBtnOS9");
-	disabledSkin:  Embed(source="assets/swf/WindowsAssets.swf", symbol="closeBtnOS9");
-}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/branding/css/WindowsXP_default.css b/bigbluebutton-client/src/branding/css/WindowsXP_default.css
deleted file mode 100755
index f7f143a4d6b3d43f64f48feefa8144ac042c7cbf..0000000000000000000000000000000000000000
--- a/bigbluebutton-client/src/branding/css/WindowsXP_default.css
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
-Copyright (c) 2007 FlexLib Contributors.  See:
-    http://code.google.com/p/flexlib/wiki/ProjectContributors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-Application
-{
-	background-image: Embed(source="assets/img/wallpaperWin.jpg");
-}
-
-MDIWindow
-{
-	titleStyleName: "winXPTitleStyle";
-	
-	minimizeBtnStyleNameNoFocus: "mdiWindowMinimizeBtnNoFocus";
-	maximizeBtnStyleNameNoFocus: "mdiWindowMaximizeBtnNoFocus";
-	restoreBtnStyleNameNoFocus: "mdiWindowRestoreBtnNoFocus";
-	closeBtnStyleNameNoFocus: "mdiWindowCloseBtnNoFocus";
-}
-
-.winXPTitleStyle
-{
-	fontFamily: Verdana;
-	fontSize: 12;
-	fontWeight: normal;
-	color: #FFFFFF;
-}
-
-.mdiWindowFocus
-{
-	borderColor: #0053E1;
-	borderAlpha: 1;
-	borderThicknessLeft: 2;
-	borderThicknessTop: 0;
-	borderThicknessBottom: 2;
-	borderThicknessRight: 2;
-	roundedBottomCorners: false;
-	cornerRadius: 5;
-	dropShadowEnabled: false;
-	headerHeight: 29;
-	backgroundAlpha: 1; 
-	backgroundColor: #FFFFFF;
-	titleBackgroundSkin: Embed(source="assets/swf/WindowsAssets.swf", symbol="headerBgDefault");
-}
-
-.mdiWindowNoFocus
-{
-	borderColor: #7B97E0;
-	borderAlpha: 1;
-	borderThicknessLeft: 2;
-	borderThicknessTop: 0;
-	borderThicknessBottom: 2;
-	borderThicknessRight: 2;
-	roundedBottomCorners: false;
-	cornerRadius: 5;
-	dropShadowEnabled: false;
-	headerHeight: 29;
-	backgroundAlpha: 1; 
-	backgroundColor: #FFFFFF;
-	titleBackgroundSkin: Embed(source="assets/swf/WindowsAssets.swf", symbol="headerBgDefaultNoFocus");
-	
-}
-
-.mdiWindowMinimizeBtn
-{
-	upSkin:        Embed(source="assets/swf/WindowsAssets.swf", symbol="minimizeBtnDefault_up");
-	overSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="minimizeBtnDefault_over");
-	downSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="minimizeBtnDefault_down");
-	disabledSkin:  Embed(source="assets/swf/WindowsAssets.swf", symbol="minimizeBtnDefaultNoFocus");
-}
-
-.mdiWindowMinimizeBtnNoFocus
-{
-	upSkin:        Embed(source="assets/swf/WindowsAssets.swf", symbol="minimizeBtnDefaultNoFocus");
-	overSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="minimizeBtnDefaultNoFocus");
-	downSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="minimizeBtnDefaultNoFocus");
-	disabledSkin:  Embed(source="assets/swf/WindowsAssets.swf", symbol="minimizeBtnDefaultNoFocus");
-}
-
-.mdiWindowMaximizeBtn
-{
-	upSkin:        Embed(source="assets/swf/WindowsAssets.swf", symbol="maximizeBtnDefault_up");
-	overSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="maximizeBtnDefault_over");
-	downSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="maximizeBtnDefault_down");
-	disabledSkin:  Embed(source="assets/swf/WindowsAssets.swf", symbol="maximizeBtnDefaultNoFocus");
-}
-
-.mdiWindowMaximizeBtnNoFocus
-{
-	upSkin:        Embed(source="assets/swf/WindowsAssets.swf", symbol="maximizeBtnDefaultNoFocus");
-	overSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="maximizeBtnDefaultNoFocus");
-	downSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="maximizeBtnDefaultNoFocus");
-	disabledSkin:  Embed(source="assets/swf/WindowsAssets.swf", symbol="maximizeBtnDefaultNoFocus");
-}
-
-.mdiWindowRestoreBtn
-{
-	upSkin:        Embed(source="assets/swf/WindowsAssets.swf", symbol="restoreBtnDefault_up");
-	overSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="restoreBtnDefault_over");
-	downSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="restoreBtnDefault_down");
-	disabledSkin:  Embed(source="assets/swf/WindowsAssets.swf", symbol="restoreBtnDefaultNoFocus");
-}
-
-.mdiWindowRestoreBtnNoFocus
-{
-	upSkin:        Embed(source="assets/swf/WindowsAssets.swf", symbol="restoreBtnDefaultNoFocus");
-	overSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="restoreBtnDefaultNoFocus");
-	downSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="restoreBtnDefaultNoFocus");
-	disabledSkin:  Embed(source="assets/swf/WindowsAssets.swf", symbol="restoreBtnDefaultNoFocus");
-}
-
-.mdiWindowCloseBtn
-{
-	upSkin:        Embed(source="assets/swf/WindowsAssets.swf", symbol="closeBtnDefault_up");
-	overSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="closeBtnDefault_over");
-	downSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="closeBtnDefault_down");
-	disabledSkin:  Embed(source="assets/swf/WindowsAssets.swf", symbol="closeBtnDefaultNoFocus");
-}
-
-.mdiWindowCloseBtnNoFocus
-{
-	upSkin:        Embed(source="assets/swf/WindowsAssets.swf", symbol="closeBtnDefaultNoFocus");
-	overSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="closeBtnDefaultNoFocus");
-	downSkin:      Embed(source="assets/swf/WindowsAssets.swf", symbol="closeBtnDefaultNoFocus");
-	disabledSkin:  Embed(source="assets/swf/WindowsAssets.swf", symbol="closeBtnDefaultNoFocus");
-}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/branding/css/assets/img/BBBLogo.png b/bigbluebutton-client/src/branding/css/assets/img/BBBLogo.png
deleted file mode 100755
index 9f1fa1235f1ecd14dd0424ae1e953fe66b33e597..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/BBBLogo.png and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/BrushedMetalBack.jpg b/bigbluebutton-client/src/branding/css/assets/img/BrushedMetalBack.jpg
deleted file mode 100755
index 2db87165999edc4b00aa99f0387bb9bcf4a5e8fa..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/BrushedMetalBack.jpg and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/bk3.jpg b/bigbluebutton-client/src/branding/css/assets/img/bk3.jpg
deleted file mode 100755
index f6c8ab242bc4e5a7dc4b589718cce54381e15d3d..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/bk3.jpg and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/closeButton.png b/bigbluebutton-client/src/branding/css/assets/img/closeButton.png
deleted file mode 100755
index 82da8f0486f977671dbbcc99460018662b688dfc..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/closeButton.png and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/cornerResize3.png b/bigbluebutton-client/src/branding/css/assets/img/cornerResize3.png
deleted file mode 100755
index c0e341f43f6ccdbb3cf9b4a59c52d53c936b3a8c..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/cornerResize3.png and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/decreaseButton.png b/bigbluebutton-client/src/branding/css/assets/img/decreaseButton.png
deleted file mode 100755
index ae7f931fc0515a2886d7bf231e3901cc118b8c06..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/decreaseButton.png and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/increaseButton.png b/bigbluebutton-client/src/branding/css/assets/img/increaseButton.png
deleted file mode 100755
index 620353fbe0085eec7b49a7224f458fcbcbcdca0c..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/increaseButton.png and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/menuArrow.png b/bigbluebutton-client/src/branding/css/assets/img/menuArrow.png
deleted file mode 100755
index 38af93c846d284982cc59f1cd0388ea86cabb9ef..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/menuArrow.png and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/minimizeButton.png b/bigbluebutton-client/src/branding/css/assets/img/minimizeButton.png
deleted file mode 100755
index 0178081ebf45ef277676f155f2f1d22ffe42c4cc..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/minimizeButton.png and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/resizeCursor.png b/bigbluebutton-client/src/branding/css/assets/img/resizeCursor.png
deleted file mode 100755
index a64e80cd9d662d55b4ba969990488d2c6c6f4f35..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/resizeCursor.png and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/resizeCursorH.gif b/bigbluebutton-client/src/branding/css/assets/img/resizeCursorH.gif
deleted file mode 100755
index daa8facfa135fa1b74afd29d11cd9785fc4350cd..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/resizeCursorH.gif and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/resizeCursorTLBR.gif b/bigbluebutton-client/src/branding/css/assets/img/resizeCursorTLBR.gif
deleted file mode 100755
index d0c72562c0988afc47f96bde9cda32827d1ea8b3..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/resizeCursorTLBR.gif and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/resizeCursorTRBL.gif b/bigbluebutton-client/src/branding/css/assets/img/resizeCursorTRBL.gif
deleted file mode 100755
index 442efa5d48cc5b5cf0e0d59a6a0d5df3939c1fa6..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/resizeCursorTRBL.gif and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/resizeCursorV.gif b/bigbluebutton-client/src/branding/css/assets/img/resizeCursorV.gif
deleted file mode 100755
index 6061a32a9a85e43b6f25db8096189fb8600791ee..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/resizeCursorV.gif and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/resizeCursorVH.gif b/bigbluebutton-client/src/branding/css/assets/img/resizeCursorVH.gif
deleted file mode 100755
index 7da81d6f379062077edbb7a1b241bd479363a312..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/resizeCursorVH.gif and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/wallpaperOS9.gif b/bigbluebutton-client/src/branding/css/assets/img/wallpaperOS9.gif
deleted file mode 100755
index 23183806e7472cf62193ac2cf7b1cc4eb3bd67fa..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/wallpaperOS9.gif and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/assets/img/wallpaperWin.jpg b/bigbluebutton-client/src/branding/css/assets/img/wallpaperWin.jpg
deleted file mode 100755
index 5db85738abcbf140ef3a69e6f3e2f4d697705286..0000000000000000000000000000000000000000
Binary files a/bigbluebutton-client/src/branding/css/assets/img/wallpaperWin.jpg and /dev/null differ
diff --git a/bigbluebutton-client/src/branding/css/logo_basic.css b/bigbluebutton-client/src/branding/css/logo_basic.css
deleted file mode 100755
index 4c9dae3d7cbb07a53f08ca50e3d39a61016d5859..0000000000000000000000000000000000000000
--- a/bigbluebutton-client/src/branding/css/logo_basic.css
+++ /dev/null
@@ -1,6 +0,0 @@
-/*The image for your logo is 200x200 pixels. No other size is currently supported so resize your logo accordingly. The logo will always appear in the lower right corner. */
-BrandingLogo
-{
-	backgroundImage: Embed(source="assets/img/BBBLogo.png");
-	backgroundSize: "100%";
-}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/branding/css/theme.css b/bigbluebutton-client/src/branding/css/theme.css
deleted file mode 100755
index 143ffc19c2c78d03e9821c76b6c2098f39b86911..0000000000000000000000000000000000000000
--- a/bigbluebutton-client/src/branding/css/theme.css
+++ /dev/null
@@ -1,180 +0,0 @@
-Application 
-{  
-   backgroundColors: #000000,#3f3f3f;
-   backgroundImage: Embed(source="assets/img/bk3.jpg");
-   backgroundSize: "100%";
-   backgroundGradientColors: #B4BFCF, #78829C;
-   themeColor: #0094C7;
-   backgroundGradientAlphas: 0.62, 0.26;
-}
-
-/*The image for your logo is 200x200 pixels. No other size is currently supported so resize your logo accordingly. The logo will always appear in the lower right corner. */
-BrandingLogo
-{
-	backgroundImage: Embed(source="assets/img/BBBLogo.png");
-	backgroundSize: "100%";
-}
-
-
-MDICanvas 
-{
-	backgroundColor: #0094C7;
-	backgroundAlpha: 0;
-}
-
-
-Button 
-{
-   highlightAlphas: 1, 0.33;
-   fillAlphas: 1, 0.16, 0.18, 1;
-   fillColors: #5f89b9, #697182, #ffffff, #eeeeee;
-}
-
-
-.mdiWindowFocus 
-{
-	headerHeight: 26;
-	roundedBottomCorners: true;
-	backgroundAlpha: 1;
-	backgroundColor: #FFFFFF;
-	backgroundImage: Embed(source="assets/swf/Blue.swf", symbol="Window_Background");
-	backgroundSize: '100%';
-	
-	borderStyle: solid;
-	borderColor: #ffffff;
-	borderAlpha: 1;
-	borderThickness: 2;
-	borderThicknessLeft: 0;
-	borderThicknessTop: 0;
-	borderThicknessBottom: 0;
-	borderThicknessRight: 0;
-	cornerRadius: 4;
-	dropShadowEnabled: false;
-	titleStyleName: "mypanelTitle";
-	
-	cornerResizeImg: Embed(source="assets/swf/Blue.swf", symbol="Corner_Resize");
-	cornerResizeWidth: 15;
-	cornerResizeHeight: 15;
-	cornerResizePaddingRight: 2;
-	cornerResizePaddingBottom: 2;
-	
-	controlButtonWidth: 10;
-	controlButtonHeight: 10;
-	controlButtonGap: 4;
-}
-
-.mdiWindowNoFocus 
-{
-	headerHeight: 26;
-	roundedBottomCorners: true;
-	backgroundAlpha: 0.5;
-	backgroundImage: Embed(source="assets/swf/Blue.swf", symbol="Window_Background");
-	backgroundSize: '100%';
-	
-	borderStyle: solid;
-	borderColor: #ffffff;
-	borderAlpha: 1;
-	borderThickness: 2;
-	borderThicknessLeft: 0;
-	borderThicknessTop: 0;
-	borderThicknessBottom: 0;
-	borderThicknessRight: 0;
-	cornerRadius: 4;
-	dropShadowEnabled: false;
-	titleStyleName: "mypanelTitle";
-	
-	cornerResizeImg: Embed(source="assets/swf/Blue.swf", symbol="Corner_Resize");
-	cornerResizeWidth: 15;
-	cornerResizeHeight: 15;
-	cornerResizePaddingRight: 2;
-	cornerResizePaddingBottom: 2;
-	
-	controlButtonWidth: 10;
-	controlButtonHeight: 10;
-	controlButtonGap: 4;
-}
-
-.mypanelTitle 
-{
-	fontFamily: Arial;
-	fontSize: 12;
-	fontWeight: bold;
-	color: #ffffff;
-}
-
-
-.closeBtnFocus
-{
-	upSkin:        Embed('assets/img/3_closeButton.png');
-	overSkin:      Embed('assets/img/3_closeButton.png');
-	downSkin:      Embed('assets/img/3_closeButton.png');
-	disabledSkin:  Embed('assets/img/3_closeButton.png');
-}
-
-.closeBtnNoFocus
-{
-	upSkin:        Embed('assets/img/3_closeButton.png');
-	overSkin:      Embed('assets/img/3_closeButton.png');
-	downSkin:      Embed('assets/img/3_closeButton.png');
-	disabledSkin:  Embed('assets/img/3_closeButton.png');
-}
-
-
-.increaseBtnFocus
-{
-	upSkin:        Embed('assets/img/3_increaseButton.png');
-	overSkin:      Embed('assets/img/3_increaseButton.png');
-	downSkin:      Embed('assets/img/3_increaseButton.png');
-	disabledSkin:  Embed('assets/img/3_increaseButton.png');
-}
-
-.increaseBtnNoFocus
-{
-	upSkin:        Embed('assets/img/3_increaseButton.png');
-	overSkin:      Embed('assets/img/3_increaseButton.png');
-	downSkin:      Embed('assets/img/3_increaseButton.png');
-	disabledSkin:  Embed('assets/img/3_increaseButton.png');
-}
-
-
-.decreaseBtnFocus 
-{
-	upSkin:        Embed('assets/img/3_decreaseButton.png');
-	overSkin:      Embed('assets/img/3_decreaseButton.png');
-	downSkin:      Embed('assets/img/3_decreaseButton.png');
-	disabledSkin:  Embed('assets/img/3_decreaseButton.png');
-}
-
-.decreaseBtnNoFocus 
-{
-	upSkin:        Embed('assets/img/3_decreaseButton.png');
-	overSkin:      Embed('assets/img/3_decreaseButton.png');
-	downSkin:      Embed('assets/img/3_decreaseButton.png');
-	disabledSkin:  Embed('assets/img/3_decreaseButton.png');
-}
-
-
-.minimizeBtnFocus 
-{
-	upSkin:        Embed('assets/img/3_minimizeButton.png');
-	overSkin:      Embed('assets/img/3_minimizeButton.png');
-	downSkin:      Embed('assets/img/3_minimizeButton.png');
-	disabledSkin:  Embed('assets/img/3_minimizeButton.png');
-}
-
-.minimizeBtnNoFocus 
-{
-	upSkin:        Embed('assets/img/3_minimizeButton.png');
-	overSkin:      Embed('assets/img/3_minimizeButton.png');
-	downSkin:      Embed('assets/img/3_minimizeButton.png');
-	disabledSkin:  Embed('assets/img/3_minimizeButton.png');
-}
-
-
-.resizeHndlr 
-{
-	upSkin:        Embed('assets/img/resizeHandler.png');
-	overSkin:      Embed('assets/img/resizeHandler.png');
-	downSkin:      Embed('assets/img/resizeHandler.png');
-	disabledSkin:  Embed('assets/img/resizeHandler.png');
-}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/Images.as b/bigbluebutton-client/src/org/bigbluebutton/common/Images.as
index 03dcd2c573e7c1347b84e94d8ed18e1f434047ac..01e67207782bfa2c90f92285283c5eec459a8339 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/common/Images.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/common/Images.as
@@ -21,6 +21,33 @@ package org.bigbluebutton.common
 	[Bindable]
 	public class Images
 	{
+    [Embed(source="assets/images/webcam_kickuser.png")]
+    public var webcam_kickuser:Class;
+    
+    [Embed(source="assets/images/webcam_make_presenter.png")]
+    public var webcam_make_presenter:Class;
+    
+    [Embed(source="assets/images/webcam_mute.png")]
+    public var webcam_mute:Class;
+    
+    [Embed(source="assets/images/webcam_private_chat.png")]
+    public var webcam_private_chat:Class;
+    
+    [Embed(source="assets/images/webcam_unmute.png")]
+    public var webcam_unmute:Class;
+    
+    [Embed(source="assets/images/vdoc_bg.jpg")]
+    public var video_dock_bg:Class;
+        
+    [Embed(source="assets/images/bandwidth.png")]
+    public var bandwidth:Class;
+    
+    [Embed(source="assets/images/statistics.png")]
+    public var stats:Class;
+    
+    [Embed(source="assets/images/avatar.png")]
+    public var avatar:Class;
+    
     [Embed(source="assets/images/sign-out.png")]
     public var signOutIcon:Class;
     
@@ -91,7 +118,7 @@ package org.bigbluebutton.common
         public var sound:Class;                
 
         [Embed(source="assets/images/cancel.png")]
-        public var cancel_user:Class;    
+        public var cancel:Class;    
 
         [Embed(source="assets/images/user_go.png")]
         public var eject_user:Class;  
@@ -108,19 +135,19 @@ package org.bigbluebutton.common
         [Embed(source="assets/images/shape_square.png")]
         public var square_icon:Class;  
         
-        [Embed(source="assets/images/arrow_undo.png")] 
+        [Embed(source="assets/images/undo.png")] 
         public var undo_icon:Class;  
         
-        [Embed(source="assets/images/hand_icon.png")]
+        [Embed(source="assets/images/hand.png")]
         public var hand_icon:Class; 
         
-        [Embed(source="assets/images/scribble_icon.png")]
+        [Embed(source="assets/images/marker.png")]
         public var scribble_icon:Class; 
 
-        [Embed(source="assets/images/text_icon.png")]
+        [Embed(source="assets/images/text.png")]
         public var text_icon:Class; 
         
-        [Embed(source="assets/images/circle.png")]
+        [Embed(source="assets/images/ellipse.png")]
         public var circle_icon:Class; 
         
         [Embed(source="assets/images/arrow_out.png")]
@@ -144,7 +171,7 @@ package org.bigbluebutton.common
 		[Embed(source="assets/images/table.png")]
 		public var table:Class; 
 		
-		[Embed(source="assets/images/cancel.png")]
+		[Embed(source="assets/images/trash.png")]
 		public var delete_icon:Class; 
 
         [Embed(source="assets/images/arrow_right.png")]
@@ -223,7 +250,7 @@ package org.bigbluebutton.common
 		[Embed(source="assets/images/pointer_icon_small.png")]
 		public var select_icon:Class;	
 		
-		[Embed(source="assets/images/triangle_icon.png")]
+		[Embed(source="assets/images/triangle.png")]
 		public var triangle_icon:Class;	
 		
 		[Embed(source="assets/images/text_background_icon.png")]
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/avatar.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/avatar.png
new file mode 100644
index 0000000000000000000000000000000000000000..2e9f8151f4083aece663009ae40d9271104dbb41
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/avatar.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/bandwidth.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/bandwidth.png
new file mode 100755
index 0000000000000000000000000000000000000000..adb979ce5aa24832549312d1291605e4dfcc4cae
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/bandwidth.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/ellipse.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/ellipse.png
new file mode 100755
index 0000000000000000000000000000000000000000..ce5466bfe0cdf9a697052b5ecf4939b3c59b95fe
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/ellipse.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/fit-to-screen.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/fit-to-screen.png
new file mode 100755
index 0000000000000000000000000000000000000000..fe28c01d240b2ba38bc005ec4fc8af97f3248d62
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/fit-to-screen.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/fit-to-width.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/fit-to-width.png
index 39d6e1dd445af304d4e922288fe22a3f0d7946d9..f991166ed66ce39733208574c3a1bc7931d812be 100755
Binary files a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/fit-to-width.png and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/fit-to-width.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/hand.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/hand.png
new file mode 100755
index 0000000000000000000000000000000000000000..c6bcefaea0a1b7ef4950cfefcd58d7a588b58d57
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/hand.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/left_arrow.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/left_arrow.png
new file mode 100755
index 0000000000000000000000000000000000000000..3117136c1fda27fb27a057d835deb05a0a888e23
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/left_arrow.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/line.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/line.png
old mode 100644
new mode 100755
index f5413cb7bf9600800f1c5232fc52c21a17b57daf..e0abedeaaea9868fceee6038e75524d663cf883e
Binary files a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/line.png and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/line.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/marker.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/marker.png
new file mode 100755
index 0000000000000000000000000000000000000000..7a026099e3685ceb87505f5b1292f48b714da566
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/marker.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/righ-arrow.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/righ-arrow.png
new file mode 100755
index 0000000000000000000000000000000000000000..f00775a7eab38053a23d662ed228e66cb25f4b56
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/righ-arrow.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/square.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/square.png
new file mode 100755
index 0000000000000000000000000000000000000000..bdceb2e4744dabf7b1352e115e41e58ca92c1946
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/square.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/statistics.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/statistics.png
new file mode 100755
index 0000000000000000000000000000000000000000..d4779d9d69e71375594045eeb070e9793fb897a6
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/statistics.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/text.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/text.png
new file mode 100755
index 0000000000000000000000000000000000000000..819b5803925d8254c7ced6199719aeac3ac1735d
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/text.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/trash.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/trash.png
new file mode 100755
index 0000000000000000000000000000000000000000..2b95a3faa6ff838bff79a0c8e53a8a0c83bdb9e5
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/trash.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/triangle.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/triangle.png
new file mode 100755
index 0000000000000000000000000000000000000000..0530c3deb689c473880dc3fc22ddb692d766256f
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/triangle.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/undo.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/undo.png
new file mode 100755
index 0000000000000000000000000000000000000000..43a7e19fc6cdedaec8349b4fabf34a0bf47e208d
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/undo.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/upload.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/upload.png
index 36086b05258973bb5b2fdebf826fd32629858bae..030cc3e82aab53ff29cbc0dc4fbe30ee067177be 100755
Binary files a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/upload.png and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/upload.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/vdoc_bg.jpg b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/vdoc_bg.jpg
new file mode 100755
index 0000000000000000000000000000000000000000..0dfda438df84be7d57567944ff3a89f1f540900a
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/vdoc_bg.jpg differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_kickuser.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_kickuser.png
new file mode 100755
index 0000000000000000000000000000000000000000..561edc8d9b00d9c97c9acd82b4bf121bc3a77426
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_kickuser.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_make_presenter.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_make_presenter.png
new file mode 100755
index 0000000000000000000000000000000000000000..e7cfff5e97381b5a88d0b96b35508e52e850960e
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_make_presenter.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_mute.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_mute.png
new file mode 100755
index 0000000000000000000000000000000000000000..3be5bd19cf8cf09beb6c7c7758b21b5deabab69b
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_mute.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_private_chat.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_private_chat.png
new file mode 100755
index 0000000000000000000000000000000000000000..9fdff988a3cfa2f6ef81f0a2d0de135dd199371e
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_private_chat.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_unmute.png b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_unmute.png
new file mode 100755
index 0000000000000000000000000000000000000000..32a685732f0073772bb782662fe37e30a83d5220
Binary files /dev/null and b/bigbluebutton-client/src/org/bigbluebutton/common/assets/images/webcam_unmute.png differ
diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/BBB.as b/bigbluebutton-client/src/org/bigbluebutton/core/BBB.as
index f2adcc2809a3dadea1bee3a54c6ddb9e6f4c3fbe..f1c4a9bbff96fc04db5261e9ac592f77c387d4fe 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/core/BBB.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/core/BBB.as
@@ -2,7 +2,6 @@ package org.bigbluebutton.core
 {
 	import org.bigbluebutton.core.managers.ConfigManager2;
 	import org.bigbluebutton.core.managers.ConnectionManager;
-	import org.bigbluebutton.core.managers.StreamManager;
 	import org.bigbluebutton.core.managers.UserConfigManager;
 	import org.bigbluebutton.core.managers.UserManager;
 	import org.bigbluebutton.core.model.Session;
@@ -10,7 +9,6 @@ package org.bigbluebutton.core
 	
 	public class BBB {
 		private static var configManager:ConfigManager2 = null;
-		private static var streamManager:StreamManager = null;
 		private static var connectionManager:ConnectionManager = null;
 		private static var session:Session = null;
 		private static var userConfigManager:UserConfigManager = null;
@@ -34,13 +32,6 @@ package org.bigbluebutton.core
 			return initConfigManager().config.getConfigFor(module);
 		}
 		
-		public static function initStreamManager():StreamManager {
-			if (streamManager == null) {
-				streamManager = new StreamManager();
-			}
-			return streamManager;
-		}
-		
 		public static function initConnectionManager():ConnectionManager {
 			if (connectionManager == null) {
 				connectionManager = new ConnectionManager();
diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/EventConstants.as b/bigbluebutton-client/src/org/bigbluebutton/core/EventConstants.as
index 583d9e72eab4e766b6427f06aeae373df2b75cbf..0b377d81c48c09eb0b2bb91a3ef1e8d1b67b24db 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/core/EventConstants.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/core/EventConstants.as
@@ -19,10 +19,15 @@ package org.bigbluebutton.core
     
     /** Events to External JS **/
     public static const GET_MY_ROLE_RESP:String           = 'GetMyRoleResponse';
- 
+    public static const AM_I_PRESENTER_RESP:String        = 'AmIPresenterQueryResponse';
+    public static const AM_I_SHARING_CAM_RESP:String      = 'AmISharingCamQueryResponse';
+    public static const BROADCASTING_CAM_STARTED:String   = 'BroadcastingCameraStartedEvent';
+    public static const BROADCASTING_CAM_STOPPED:String   = 'BroadcastingCameraStoppedEvent';
+    public static const I_AM_SHARING_CAM:String           = 'IAmSharingCamEvent';
+    public static const CAM_STREAM_SHARED:String          = 'CamStreamSharedEvent';
     public static const USER_JOINED:String                = 'UserJoinedEvent';
     public static const USER_LEFT:String                  = 'UserLeftEvent';
-    public static const NEW_ROLE:String                   = 'NewRoleEvent';
+    public static const SWITCHED_PRESENTER:String         = 'SwitchedPresenterEvent';
     public static const NEW_PRIVATE_CHAT:String           = 'NewPrivateChatEvent';
     public static const NEW_PUBLIC_CHAT:String            = 'NewPublicChatEvent';
     public static const SWITCHED_LAYOUT:String            = 'SwitchedLayoutEvent';
@@ -30,7 +35,9 @@ package org.bigbluebutton.core
     public static const REMOTE_UNLOCKED_LAYOUT:String     = 'RemoteUnlockedLayoutEvent';
     public static const USER_JOINED_VOICE:String          = 'UserJoinedVoiceEvent';
     public static const USER_LEFT_VOICE:String            = 'UserLeftVoiceEvent';
+    public static const USER_MUTED_VOICE:String           = 'UserVoiceMutedEvent';
     public static const USER_TALKING:String               = 'UserTalkingEvent';
+    public static const USER_LOCKED_VOICE:String          = 'UserLockedVoiceEvent';
     public static const START_PRIVATE_CHAT:String         = "StartPrivateChatEvent";
   }
 }
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/UsersUtil.as b/bigbluebutton-client/src/org/bigbluebutton/core/UsersUtil.as
index e113ead8a341b1f57b3357dc77955332ab5caa16..21f2d71c8a096f1fc8233786eb0db320b72a9257 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/core/UsersUtil.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/core/UsersUtil.as
@@ -1,11 +1,61 @@
 package org.bigbluebutton.core
 {
+  import mx.collections.ArrayCollection;
+  
   import org.bigbluebutton.common.LogUtil;
   import org.bigbluebutton.core.managers.UserManager;
+  import org.bigbluebutton.core.vo.CameraSettingsVO;
   import org.bigbluebutton.main.model.users.BBBUser;
 
   public class UsersUtil
   {
+    
+    public static function amIPublishing():CameraSettingsVO {
+     return UserManager.getInstance().getConference().amIPublishing();
+    }
+    
+    public static function setIAmPublishing(publishing:Boolean):void {
+      UserManager.getInstance().getConference().setCamPublishing(publishing);
+    }
+    
+    public static function setCameraSettings(camSettings:CameraSettingsVO):void {
+      UserManager.getInstance().getConference().setCameraSettings(camSettings);
+    }
+    
+    public static function hasWebcamStream(userID:String):Boolean {
+      var u:BBBUser = getUser(userID);
+      if (u != null) {
+        return u.hasStream;
+      }
+      
+      return false;
+    }
+    
+    public static function getWebcamStream(userID:String):String {
+      var u:BBBUser = getUser(userID);
+      if (u != null) {
+        return u.streamName;
+      }
+      
+      return null;
+    }
+    
+    public static function getUserIDs():ArrayCollection {
+      return UserManager.getInstance().getConference().getUserIDs();
+    }
+    
+    public static function getInternalMeetingID():String {
+      return UserManager.getInstance().getConference().internalMeetingID;
+    }
+    
+    public static function getAvatarURL():String {
+      return UserManager.getInstance().getConference().avatarURL;
+    }
+    
+    public static function getExternalMeetingID():String {
+      return UserManager.getInstance().getConference().externalMeetingID;
+    }
+    
     public static function amIModerator():Boolean {
       return UserManager.getInstance().getConference().amIModerator();
     }
diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/events/AmIPresenterQueryEvent.as b/bigbluebutton-client/src/org/bigbluebutton/core/events/AmIPresenterQueryEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..d65ff7b132ba197dedba21aa55a9cae572b4b117
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/core/events/AmIPresenterQueryEvent.as
@@ -0,0 +1,13 @@
+package org.bigbluebutton.core.events
+{
+  import flash.events.Event;
+  
+  public class AmIPresenterQueryEvent extends Event
+  {
+    public static const AM_I_PRESENTER_QUERY:String = "am I presenter query request";
+    
+    public function AmIPresenterQueryEvent(bubbles:Boolean=true, cancelable:Boolean=false) {
+      super(AM_I_PRESENTER_QUERY, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/events/AmISharingWebcamQueryEvent.as b/bigbluebutton-client/src/org/bigbluebutton/core/events/AmISharingWebcamQueryEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..f4a11378a2671f29954841cef98938de4e9d0334
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/core/events/AmISharingWebcamQueryEvent.as
@@ -0,0 +1,14 @@
+package org.bigbluebutton.core.events
+{
+  import flash.events.Event;
+  
+  public class AmISharingWebcamQueryEvent extends Event
+  {
+    public static const AM_I_SHARING_CAM_QUERY:String = "am I sharing cam query event";
+    
+    public function AmISharingWebcamQueryEvent(bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(AM_I_SHARING_CAM_QUERY, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/events/ConnectAppEvent.as b/bigbluebutton-client/src/org/bigbluebutton/core/events/ConnectAppEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..b2fe39f1c987e5a68b64294867808cbce8f7d62d
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/core/events/ConnectAppEvent.as
@@ -0,0 +1,14 @@
+package org.bigbluebutton.core.events
+{
+  import flash.events.Event;
+  
+  public class ConnectAppEvent extends Event
+  {
+    public static const CONNECT_VIDEO_APP:String = "connect to video app event";
+    
+    public function ConnectAppEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(type, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/events/SwitchedLayoutEvent.as b/bigbluebutton-client/src/org/bigbluebutton/core/events/SwitchedLayoutEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..6fb7915f0f16fdd4d4d9a6519a20d77ca2ab9127
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/core/events/SwitchedLayoutEvent.as
@@ -0,0 +1,16 @@
+package org.bigbluebutton.core.events
+{
+  import flash.events.Event;
+  
+  public class SwitchedLayoutEvent extends Event
+  {
+    public static const SWITCHED_LAYOUT_EVENT:String = "switched layout event";
+    
+    public var layoutID:String;
+    
+    public function SwitchedLayoutEvent(bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(SWITCHED_LAYOUT_EVENT, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/managers/StreamManager.as b/bigbluebutton-client/src/org/bigbluebutton/core/managers/StreamManager.as
deleted file mode 100755
index e262210f356fd9138c0bbc73c516f9013ecd4408..0000000000000000000000000000000000000000
--- a/bigbluebutton-client/src/org/bigbluebutton/core/managers/StreamManager.as
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bigbluebutton.core.managers
-{
-	public class StreamManager
-	{
-		public function StreamManager()
-		{
-		}
-
-	}
-}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/services/BandwidthMonitor.as b/bigbluebutton-client/src/org/bigbluebutton/core/services/BandwidthMonitor.as
new file mode 100755
index 0000000000000000000000000000000000000000..c8aef8314d56b9765e63d182c9ee65fe3fe70dba
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/core/services/BandwidthMonitor.as
@@ -0,0 +1,145 @@
+package org.bigbluebutton.core.services
+{
+  import flash.events.AsyncErrorEvent;
+  import flash.events.NetStatusEvent;
+  import flash.events.TimerEvent;
+  import flash.net.NetConnection;
+  import flash.utils.Timer;
+  
+  import mx.utils.ObjectUtil;
+
+  import org.bigbluebutton.common.LogUtil;
+  import org.bigbluebutton.main.model.NetworkStatsData;
+
+  import org.red5.flash.bwcheck.ClientServerBandwidth;
+  import org.red5.flash.bwcheck.ServerClientBandwidth;
+  import org.red5.flash.bwcheck.events.BandwidthDetectEvent;
+
+  public class BandwidthMonitor {
+    private var _serverURL:String = "localhost";
+    private var _serverApplication:String = "video";
+    private var _clientServerService:String = "checkBandwidthUp";
+    private var _serverClientService:String = "checkBandwidth";
+    private var nc:NetConnection;
+    
+    private var bwTestTimer:Timer;
+    
+    public function BandwidthMonitor() {
+      
+    }
+    
+    public function set serverURL(url:String):void {
+      _serverURL = url;
+    }
+    
+    public function set serverApplication(app:String):void {
+      _serverApplication = app;
+    }
+
+    public function start():void {
+      connect();
+    }
+       
+    private function connect():void {
+      nc = new NetConnection();
+      nc.objectEncoding = flash.net.ObjectEncoding.AMF0;
+      nc.client = this;
+      nc.addEventListener(NetStatusEvent.NET_STATUS, onStatus);	
+      nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);	
+      nc.connect("rtmp://" + _serverURL + "/" + _serverApplication);
+    }
+    
+    private function onAsyncError(event:AsyncErrorEvent):void
+    {
+      LogUtil.debug(event.error.toString());
+    }
+    
+    private function onStatus(event:NetStatusEvent):void
+    {
+      switch (event.info.code)
+      {
+        case "NetConnection.Connect.Success":
+          LogUtil.debug("Starting to monitor bandwidth between client and server");
+          monitor();
+          break;
+        default:
+          LogUtil.debug("Cannot establish the connection to measure bandwidth");
+          break;
+      }      
+    }
+    
+    private function monitor():void {
+      LogUtil.debug("Starting to monitor bandwidth");
+      bwTestTimer =  new Timer(30000);
+      bwTestTimer.addEventListener(TimerEvent.TIMER, rtmptRetryTimerHandler);
+      bwTestTimer.start();
+    }
+    
+    private function rtmptRetryTimerHandler(event:TimerEvent):void {
+      LogUtil.debug("Starting to detect bandwidth from server to client");
+      ServerClient();
+    }
+    
+    public function ClientServer():void
+    {
+      var clientServer:ClientServerBandwidth  = new ClientServerBandwidth();
+      //connect();
+      clientServer.connection = nc;
+      clientServer.service = _clientServerService;
+      clientServer.addEventListener(BandwidthDetectEvent.DETECT_COMPLETE,onClientServerComplete);
+      clientServer.addEventListener(BandwidthDetectEvent.DETECT_STATUS,onClientServerStatus);
+      clientServer.addEventListener(BandwidthDetectEvent.DETECT_FAILED,onDetectFailed);
+      clientServer.start();
+    }
+    
+    public function ServerClient():void
+    {
+      var serverClient:ServerClientBandwidth = new ServerClientBandwidth();
+      //connect();
+      serverClient.connection = nc;
+      serverClient.service = _serverClientService;
+      serverClient.addEventListener(BandwidthDetectEvent.DETECT_COMPLETE,onServerClientComplete);
+      serverClient.addEventListener(BandwidthDetectEvent.DETECT_STATUS,onServerClientStatus);
+      serverClient.addEventListener(BandwidthDetectEvent.DETECT_FAILED,onDetectFailed);
+      serverClient.start();
+    }
+    
+    public function onDetectFailed(event:BandwidthDetectEvent):void
+    {
+      LogUtil.debug("Detection failed with error: " + event.info.application + " " + event.info.description);
+    }
+    
+    public function onClientServerComplete(event:BandwidthDetectEvent):void
+    {
+//      LogUtil.debug("Client-slient bandwidth detect complete");
+      
+//      LogUtil.debug(ObjectUtil.toString(event.info));
+      NetworkStatsData.getInstance().setUploadMeasuredBW(event.info);
+    }
+    
+    public function onClientServerStatus(event:BandwidthDetectEvent):void
+    {
+      if (event.info) {
+//        LogUtil.debug("\n count: "+event.info.count+ " sent: "+event.info.sent+" timePassed: "+event.info.timePassed+" latency: "+event.info.latency+" overhead:  "+event.info.overhead+" packet interval: " + event.info.pakInterval + " cumLatency: " + event.info.cumLatency);
+      }
+    }
+    
+    public function onServerClientComplete(event:BandwidthDetectEvent):void
+    {
+//      LogUtil.debug("Server-client bandwidth detect complete");
+      
+//      LogUtil.debug(ObjectUtil.toString(event.info));
+      NetworkStatsData.getInstance().setDownloadMeasuredBW(event.info);
+
+//      LogUtil.debug("Detecting Client Server Bandwidth");
+      ClientServer();
+    }
+    
+    public function onServerClientStatus(event:BandwidthDetectEvent):void
+    {	
+      if (event.info) {
+//        LogUtil.debug("\n count: "+event.info.count+ " sent: "+event.info.sent+" timePassed: "+event.info.timePassed+" latency: "+event.info.latency+" cumLatency: " + event.info.cumLatency);
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/services/StreamMonitor.as b/bigbluebutton-client/src/org/bigbluebutton/core/services/StreamMonitor.as
new file mode 100755
index 0000000000000000000000000000000000000000..b9d198643874a68de4105c73dc39ab05072918f7
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/core/services/StreamMonitor.as
@@ -0,0 +1,212 @@
+package org.bigbluebutton.core.services
+{
+	import com.asfusion.mate.events.Dispatcher;
+	
+	import flash.events.NetDataEvent; 
+	import flash.events.NetMonitorEvent; 
+	import flash.events.NetStatusEvent; 
+	import flash.events.StatusEvent;
+	import flash.events.TimerEvent;
+	import flash.net.NetMonitor; 
+	import flash.net.NetStream; 
+	import flash.utils.Dictionary;	 
+	import flash.utils.Timer;
+	import flash.utils.getDefinitionByName;
+	import flash.utils.getQualifiedClassName;
+	 
+	import org.bigbluebutton.common.LogUtil;
+	import org.bigbluebutton.main.events.NetworkStatsEvent;
+	import org.bigbluebutton.main.model.NetworkStatsData;
+	
+	public class StreamMonitor
+	{
+		/**
+		 * https://github.com/ritzalam/red5-bw-check
+		 * http://help.adobe.com/en_US/as3/dev/WS901d38e593cd1bac-1201e73713000d1f624-8000.html
+		 * http://www.adobe.com/devnet/video/articles/media-measurement-flash.html
+		 * http://help.adobe.com/en_US/air/reference/html/flash/net/NetMonitor.html
+		 * http://help.adobe.com/en_US/flashmediaserver/devguide/WSae44d1d92c7021ff-1f5381712889cd7b56-8000.html#WSae44d1d92c7021ff-1f5381712889cd7b56-7ff7
+		 * http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStreamInfo.html
+		 * http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html
+		 * http://help.adobe.com/en_US/FlashMediaServer/3.5_Deving/WS5b3ccc516d4fbf351e63e3d11a0773d56e-7ffa.html
+		 * https://groups.google.com/d/topic/red5interest/PiUDeH6jZBQ/discussion
+		 * http://flowplayer.electroteque.org/bwcheck
+		 * http://code.google.com/p/flowplayer-plugins/
+		 * http://osflash.org/pipermail/red5_osflash.org/2009-January/028906.html
+		 */
+		
+		private var _netmon:NetMonitor;
+		private var _heartbeat:Timer = new Timer( 2000 );
+		private var _globalDispatcher:Dispatcher = new Dispatcher();
+		private var _totalBytesCounter:Dictionary = new Dictionary();
+		
+		public function StreamMonitor():void {
+			//Create NetMonitor object 
+			_netmon = new NetMonitor(); 
+			_netmon.addEventListener( NetMonitorEvent.NET_STREAM_CREATE, newNetStream );
+			
+			//Start the heartbeat timer 
+			_heartbeat.addEventListener( TimerEvent.TIMER, onHeartbeat ); 
+			_heartbeat.start(); 
+		}
+		
+		//On new NetStream 
+		private function newNetStream(event:NetMonitorEvent):void  
+		{ 
+			log("New Netstream object: " + event); 
+			var stream:NetStream = event.netStream; 
+			log("Stream info: " + stream.info);
+			stream.addEventListener(NetDataEvent.MEDIA_TYPE_DATA, onStreamData); 
+			stream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
+			stream.addEventListener(StatusEvent.STATUS, onStatus);			 
+		} 
+		 
+		//On data events from a NetStream object 
+		private function onStreamData(event:NetDataEvent):void { 
+			var netStream:NetStream = event.target as NetStream; 
+//			log("Data event from " + netStream.info.uri + " at " + event.timestamp); 
+			log("Data event: " + event);
+			switch(event.info.handler) { 
+				case "onMetaData": 
+					//handle metadata; 
+					break; 
+				case "onXMPData": 
+					//handle XMP; 
+					break; 
+				case "onPlayStatus": 
+					//handle NetStream.Play.Complete
+					break;
+				case "onImageData": 
+					//handle image 
+					break; 
+				case "onTextData": 
+					//handle text 
+					break; 
+				default: 
+					//handle other events 
+					break;
+			} 
+		} 
+		 
+		//On status events from a NetStream object 
+		private function onNetStatus(event:NetStatusEvent):void { 
+//			log("Status event from " + event.target.info.uri + " at " + event.target.time); 
+			log("NetStatus event code: " + event.info.code);
+			log("NetStatus event details: " + event.info.details);
+			log("Stream info: " + event.target.info);
+		}
+		
+		private function onStatus(event:StatusEvent):void {
+			log("Status event code: " + event.code);
+			log("Status event: " + event.target);
+			log("Stream info: " + event.currentTarget);
+		}
+		
+		private function isRemoteStream(stream:NetStream):Boolean {
+			return (stream != null && stream.info != null && stream.info.resourceName != null);
+		}
+		
+		//On heartbeat timer 
+		private function onHeartbeat(event:TimerEvent):void { 
+			var streams:Vector.<NetStream> = _netmon.listStreams();
+
+			var download:Dictionary = new Dictionary();
+			var upload:Dictionary = new Dictionary();
+			 
+			for (var i:int = 0; i < streams.length; i++) {
+				if (streams[i] == null || streams[i].info == null) {
+					// stream info is null, returning
+					continue;
+				}
+				
+//				log("Heartbeat on " + streams[i].info);
+
+				var remote:Boolean = isRemoteStream(streams[i]);
+				var ref:Dictionary = (remote? download: upload);
+
+				if (streams[i].info.uri == null) {
+					log("Stream URI is null, returning");
+					continue;
+				}
+				var uri:String = streams[i].info.uri.toLowerCase();
+				var pattern1:RegExp = /(?P<protocol>.+):\/\/(?P<server>.+)\/(?P<app>.+)\/(?P<meeting>.+)/;
+				var pattern2:RegExp = /(?P<protocol>.+):\/\/(?P<server>.+)\/(?P<app>.+)/;
+				var result:Array;
+				var protocol:String = "", server:String = "", app:String = "", meeting:String = ""; 
+				if (uri.match(pattern1)) {
+					result = pattern1.exec(uri);
+					protocol = result.protocol;
+					server = result.server;
+					app = result.app;
+					meeting = result.meeting;
+				} else if (uri.match(pattern2)) {
+					result = pattern2.exec(uri);
+					protocol = result.protocol;
+					server = result.server;
+					app = result.app;
+				} else {
+					log("***** NO MATCH *****");
+				}
+
+				var props:XMLList = flash.utils.describeType(streams[i].info)..accessor;
+				
+				for each (var s:XML in props) {
+					//log(s + ": " + streams[i].info[s]);
+					if (s.@type == "Number") {
+						var property:String = s.@name;
+						var num:Number = 0;
+						if (ref.hasOwnProperty(property))
+							num = ref[property] as Number;
+						num += (streams[i].info[property] as Number);
+						ref[property] = num;
+					}
+				}
+				var streamName:String = app + "/" + (remote? streams[i].info.resourceName: "local");
+				var streamsName:String = (ref.hasOwnProperty("streams")? ref["streams"] + ";":"") + streamName;
+				ref["streams"] = streamsName;
+				
+				var totalReg:Object = new Object;
+				totalReg.streamName = streamName;
+				totalReg.remote = remote;
+				totalReg.byteCount = streams[i].info["byteCount"];
+				if (_totalBytesCounter.hasOwnProperty(streamName) && _totalBytesCounter[streamName].byteCount > totalReg.byteCount) {
+					var curTime:Number = new Date().getTime();
+					var newStreamName:String = streamName + "_" + curTime;
+					_totalBytesCounter[streamName].streamName = newStreamName;
+					_totalBytesCounter[newStreamName] = _totalBytesCounter[streamName];
+					delete _totalBytesCounter[streamName];
+				}
+				_totalBytesCounter[streamName] = totalReg;
+			}
+
+			download["byteCount"] = upload["byteCount"] = 0;
+			for each (var value:Object in _totalBytesCounter) {
+				if (value.remote)
+					download["byteCount"] += value.byteCount;
+				else
+					upload["byteCount"] += value.byteCount;
+				//log(value.streamName + ": " + value.byteCount);
+			}
+
+//			var netstatsEvent:NetworkStatsEvent = new NetworkStatsEvent();
+//			netstatsEvent.downloadStats = download;
+//			netstatsEvent.uploadStats = upload;
+//			_globalDispatcher.dispatchEvent(netstatsEvent);
+
+			NetworkStatsData.getInstance().updateConsumedBW(download["currentBytesPerSecond"],
+					upload["currentBytesPerSecond"],
+					download["byteCount"],
+					upload["byteCount"]);
+		}
+		
+		static public function printDictionary(dict:Dictionary):void {
+			for (var key:Object in dict) {
+				LogUtil.debug(key + ": " + dict[key]);
+			}
+		}
+		
+		private function log(s:String):void {
+			LogUtil.debug("[StreamMonitor] " + s);
+		}
+	}
+}
diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/vo/CameraSettingsVO.as b/bigbluebutton-client/src/org/bigbluebutton/core/vo/CameraSettingsVO.as
new file mode 100755
index 0000000000000000000000000000000000000000..0afa3d1a73a038b1fe10161850c873736f6ab4fc
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/core/vo/CameraSettingsVO.as
@@ -0,0 +1,11 @@
+package org.bigbluebutton.core.vo
+{
+  public class CameraSettingsVO
+  {
+    public var camIndex:int;
+    public var camWidth:int;
+    public var camHeight:int;
+    public var isPublishing:Boolean = false;
+    
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/api/ExternalApiCallbacks.as b/bigbluebutton-client/src/org/bigbluebutton/main/api/ExternalApiCallbacks.as
index 5437bb449fc7e5bcaa4bcba033f1e9d3518b5e17..3c48c2662fbd56239615e3ad91810a362e1a4050 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/api/ExternalApiCallbacks.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/api/ExternalApiCallbacks.as
@@ -9,18 +9,22 @@ package org.bigbluebutton.main.api
   import org.bigbluebutton.common.LogUtil;
   import org.bigbluebutton.core.EventConstants;
   import org.bigbluebutton.core.UsersUtil;
+  import org.bigbluebutton.core.events.AmIPresenterQueryEvent;
+  import org.bigbluebutton.core.events.AmISharingWebcamQueryEvent;
   import org.bigbluebutton.core.events.CoreEvent;
   import org.bigbluebutton.core.managers.UserManager;
+  import org.bigbluebutton.core.vo.CameraSettingsVO;
   import org.bigbluebutton.main.events.BBBEvent;
+  import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
   import org.bigbluebutton.modules.listeners.events.ListenersCommand;
+  import org.bigbluebutton.modules.videoconf.events.ClosePublishWindowEvent;
   import org.bigbluebutton.modules.videoconf.events.ShareCameraRequestEvent;
 
   public class ExternalApiCallbacks
   {
     private var _dispatcher:Dispatcher;
     
-    public function ExternalApiCallbacks()
-    {
+    public function ExternalApiCallbacks() {
       _dispatcher = new Dispatcher();
       
       init();
@@ -28,21 +32,77 @@ package org.bigbluebutton.main.api
     
     private function init():void {
       if (ExternalInterface.available) {
+        ExternalInterface.addCallback("switchPresenterRequest", handleSwitchPresenterRequest);
+        ExternalInterface.addCallback("getMyUserID", handleGetMyUserID);
+        ExternalInterface.addCallback("getExternalMeetingID", handleGetExternalMeetingID);
         ExternalInterface.addCallback("joinVoiceRequest", handleJoinVoiceRequest);
+        ExternalInterface.addCallback("leaveVoiceRequest", handleLeaveVoiceRequest);        
         ExternalInterface.addCallback("getMyRoleRequestSync", handleGetMyRoleRequestSync);
         ExternalInterface.addCallback("getMyRoleRequestAsync", handleGetMyRoleRequestAsynch);
+        ExternalInterface.addCallback("amIPresenterRequestSync", handleAmIPresenterRequestSync);
+        ExternalInterface.addCallback("amIPresenterRequestAsync", handleAmIPresenterRequestAsync);
+        ExternalInterface.addCallback("amISharingCameraRequestSync", handleAmISharingCameraRequestSync);
+        ExternalInterface.addCallback("amISharingCameraRequestAsync", handleAmISharingCameraRequestAsync);
         ExternalInterface.addCallback("muteMeRequest", handleMuteMeRequest);
         ExternalInterface.addCallback("unmuteMeRequest", handleUnmuteMeRequest);
         ExternalInterface.addCallback("muteAllUsersRequest", handleMuteAllUsersRequest);
         ExternalInterface.addCallback("unmuteAllUsersRequest", handleUnmuteAllUsersRequest);
         ExternalInterface.addCallback("shareVideoCamera", onShareVideoCamera);
+        ExternalInterface.addCallback("stopShareCameraRequest", handleStopShareCameraRequest);
         ExternalInterface.addCallback("switchLayout", handleSwitchLayoutRequest);
         ExternalInterface.addCallback("sendPublicChatRequest", handleSendPublicChatRequest);  
         ExternalInterface.addCallback("sendPrivateChatRequest", handleSendPrivateChatRequest); 
         ExternalInterface.addCallback("lockLayout", handleSendLockLayoutRequest);
       }
     }
-
+
+
+    private function handleAmISharingCameraRequestSync():Object {
+      var obj:Object = new Object();
+      var camSettings:CameraSettingsVO = UsersUtil.amIPublishing();
+      obj.isPublishing = camSettings.isPublishing;
+      obj.camIndex = camSettings.camIndex;
+      obj.camWidth = camSettings.camWidth;
+      obj.camHeight = camSettings.camHeight;
+      
+      return obj;
+    }
+    
+    private function handleAmISharingCameraRequestAsync():void {
+      _dispatcher.dispatchEvent(new AmISharingWebcamQueryEvent());
+    }
+    
+
+    private function handleAmIPresenterRequestSync():Boolean {
+      return UsersUtil.amIPresenter();
+    }
+    
+    private function handleAmIPresenterRequestAsync():void {
+      _dispatcher.dispatchEvent(new AmIPresenterQueryEvent());
+    }
+
+    private function handleStopShareCameraRequest():void {
+      _dispatcher.dispatchEvent(new ClosePublishWindowEvent());	
+    }
+    
+    private function handleSwitchPresenterRequest(userID:String):void {
+      var intUserID:String = UsersUtil.externalUserIDToInternalUserID(userID);
+      trace("Switching presenter to [" + intUserID + "] [" + UsersUtil.getUserName(intUserID) + "]"); 
+      
+      var e:RoleChangeEvent = new RoleChangeEvent(RoleChangeEvent.ASSIGN_PRESENTER);
+      e.userid = intUserID;
+      e.username = UsersUtil.getUserName(intUserID);
+      _dispatcher.dispatchEvent(e);
+    }
+    
+    private function handleGetMyUserID():String {
+      return UsersUtil.internalUserIDToExternalUserID(UsersUtil.getMyUserID());
+    }
+    
+    private function handleGetExternalMeetingID():String {
+      return UserManager.getInstance().getConference().externalMeetingID;
+    }
+    
     private function handleSendLockLayoutRequest(lock:Boolean):void {
       if (lock) {
         var lockEvent:CoreEvent = new CoreEvent(EventConstants.LOCK_LAYOUT_REQ);
@@ -65,7 +125,7 @@ package org.bigbluebutton.main.api
     * 
     */
     private function handleSendPublicChatRequest(fontColor:String, localeLang:String, message:String):void {
-      LogUtil.debug("handleSendPublicChatRequest");
+      trace("handleSendPublicChatRequest");
       var chatEvent:CoreEvent = new CoreEvent(EventConstants.SEND_PUBLIC_CHAT_REQ);      
       var payload:Object = new Object();      
       payload.fromColor = fontColor;
@@ -157,18 +217,29 @@ package org.bigbluebutton.main.api
     }
     
     private function handleGetMyRoleRequestAsynch():void {
-      LogUtil.debug("handleGetMyRoleRequestAsynch");
+      trace("handleGetMyRoleRequestAsynch");
       _dispatcher.dispatchEvent(new CoreEvent(EventConstants.GET_MY_ROLE_REQ));
     }
     
     private function handleJoinVoiceRequest():void {
-      LogUtil.debug("handleJoinVoiceRequest");
-      _dispatcher.dispatchEvent(new BBBEvent(BBBEvent.JOIN_VOICE_CONFERENCE));
+      trace("handleJoinVoiceRequest");
+      var joinEvent:BBBEvent = new BBBEvent("JOIN_VOICE_CONFERENCE_EVENT");
+      joinEvent.payload['useMicrophone'] = true;
+      _dispatcher.dispatchEvent(joinEvent);
     }
     
-    private function onShareVideoCamera():void {
-      LogUtil.debug("Sharing webcam");
-      _dispatcher.dispatchEvent(new ShareCameraRequestEvent());
+    private function handleLeaveVoiceRequest():void {
+      var leaveEvent:BBBEvent = new BBBEvent("LEAVE_VOICE_CONFERENCE_EVENT");
+      leaveEvent.payload["userRequested"] = true;
+      _dispatcher.dispatchEvent(leaveEvent);
+    }
+    
+    private function onShareVideoCamera(publishInClient:Boolean=true):void {
+      trace("Sharing webcam: publishInClient = [" + publishInClient + "]");
+      var event:ShareCameraRequestEvent = new ShareCameraRequestEvent();
+      event.publishInClient = publishInClient;
+      
+      _dispatcher.dispatchEvent(event);
     }
     
   }
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/api/ExternalApiCalls.as b/bigbluebutton-client/src/org/bigbluebutton/main/api/ExternalApiCalls.as
index c7f4b2c02ab59a29612bf41910b2651bce38c98a..b65229f8ae00245e7e187becc984e68bdff8b083 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/api/ExternalApiCalls.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/api/ExternalApiCalls.as
@@ -5,16 +5,94 @@ package org.bigbluebutton.main.api
   import org.bigbluebutton.common.LogUtil;
   import org.bigbluebutton.core.EventConstants;
   import org.bigbluebutton.core.UsersUtil;
+  import org.bigbluebutton.core.events.AmIPresenterQueryEvent;
+  import org.bigbluebutton.core.events.AmISharingWebcamQueryEvent;
   import org.bigbluebutton.core.events.CoreEvent;
+  import org.bigbluebutton.core.events.SwitchedLayoutEvent;
   import org.bigbluebutton.core.managers.UserManager;
-  import org.bigbluebutton.main.events.ParticipantJoinEvent;
+  import org.bigbluebutton.core.vo.CameraSettingsVO;
+  import org.bigbluebutton.main.events.BBBEvent;
+  import org.bigbluebutton.main.events.UserJoinedEvent;
+  import org.bigbluebutton.main.events.UserLeftEvent;
   import org.bigbluebutton.main.model.users.BBBUser;
+  import org.bigbluebutton.main.model.users.events.BroadcastStartedEvent;
+  import org.bigbluebutton.main.model.users.events.BroadcastStoppedEvent;
+  import org.bigbluebutton.main.model.users.events.StreamStartedEvent;
+  import org.bigbluebutton.modules.videoconf.model.VideoConfOptions;
 
-  public class ExternalApiCalls
-  {   
+
+  public class ExternalApiCalls { 
+        
+    public function handleSwitchedLayoutEvent(event:SwitchedLayoutEvent):void {
+      var payload:Object = new Object();
+      payload.eventName = EventConstants.SWITCHED_LAYOUT;
+      payload.layoutID = event.layoutID;
+      
+      broadcastEvent(payload);
+    }    
+    
+    public function handleStreamStartedEvent(event:StreamStartedEvent):void {
+      var vidConf:VideoConfOptions = new VideoConfOptions();
+      
+      var payload:Object = new Object();
+      payload.eventName = EventConstants.CAM_STREAM_SHARED;
+      payload.userID = UsersUtil.internalUserIDToExternalUserID(event.userID);
+      payload.uri = vidConf.uri + "/" + UsersUtil.getInternalMeetingID();
+      payload.streamName = event.stream;
+      
+      broadcastEvent(payload);
+    }
+    
+    public function handleBroadcastStoppedEvent(event:BroadcastStoppedEvent):void {
+      var payload:Object = new Object();
+      payload.eventName = EventConstants.BROADCASTING_CAM_STOPPED;
+      broadcastEvent(payload);  
+    }
+    
+    public function handleBroadcastStartedEvent(event:BroadcastStartedEvent):void {
+      var vidConf:VideoConfOptions = new VideoConfOptions();
+      
+      var payload:Object = new Object();
+      payload.eventName = EventConstants.BROADCASTING_CAM_STARTED;
+      payload.isPresenter = UsersUtil.amIPresenter();
+      payload.streamName = event.stream;
+      payload.isPublishing = event.camSettings.isPublishing;
+      payload.camIndex = event.camSettings.camIndex;
+      payload.camWidth = event.camSettings.camWidth;
+      payload.camHeight = event.camSettings.camHeight;
+      payload.camKeyFrameInterval = vidConf.camKeyFrameInterval;
+      payload.camModeFps = vidConf.camModeFps;
+      payload.camQualityBandwidth = vidConf.camQualityBandwidth;
+      payload.camQualityPicture = vidConf.camQualityPicture;
+      
+      broadcastEvent(payload);         
+    }
+    
+    public function handleAmISharingCamQueryEvent(event:AmISharingWebcamQueryEvent):void {
+      var camSettings:CameraSettingsVO = UsersUtil.amIPublishing();
+      
+      var payload:Object = new Object();
+      payload.eventName = EventConstants.AM_I_SHARING_CAM_RESP;
+      payload.isPublishing = camSettings.isPublishing;
+      payload.camIndex = camSettings.camIndex;
+      payload.camWidth = camSettings.camWidth;
+      payload.camHeight = camSettings.camHeight;
+      
+      broadcastEvent(payload);        
+    }
+    
+
+    public function handleAmIPresenterQueryEvent(event:AmIPresenterQueryEvent):void {
+      var payload:Object = new Object();
+      payload.eventName = EventConstants.AM_I_PRESENTER_RESP;
+      payload.amIPresenter = UsersUtil.amIPresenter();
+      broadcastEvent(payload);        
+    }
+    
     public function handleSwitchToNewRoleEvent(event:CoreEvent):void {
+      trace("Got NEW ROLE EVENT role = [" + event.message.role + "]");
       var payload:Object = new Object();
-      payload.eventName = EventConstants.NEW_ROLE;
+      payload.eventName = EventConstants.SWITCHED_PRESENTER;
       payload.role = event.message.role;
       broadcastEvent(payload);        
     }
@@ -32,20 +110,47 @@ package org.bigbluebutton.main.api
       payload.myRole = event.message.myRole;
       broadcastEvent(payload);        
     }
-    
-    public function handleUserJoinedVoiceEvent():void {
+
+    public function handleUserJoinedVoiceEvent(event:BBBEvent):void {
       var payload:Object = new Object();
       payload.eventName = EventConstants.USER_JOINED_VOICE;
+      payload.userID = UsersUtil.internalUserIDToExternalUserID(event.payload.userID);
+      
+      trace("Notifying external API that [" + UsersUtil.getUserName(event.payload.userID) + "] has joined the voice conference.");
+      
       broadcastEvent(payload);
     }
     
-    public function handleSwitchedLayoutEvent(layoutID:String):void {
+    public function handleUserVoiceMutedEvent(event:BBBEvent):void {
       var payload:Object = new Object();
-      payload.eventName = EventConstants.SWITCHED_LAYOUT;
-      payload.layoutID = layoutID;
+      payload.eventName = EventConstants.USER_MUTED_VOICE;
+      payload.userID = UsersUtil.internalUserIDToExternalUserID(event.payload.userID);
+      payload.muted = event.payload.muted;
+      
+      trace("Notifying external API that [" + UsersUtil.getUserName(event.payload.userID) + "] is now muted=[" + payload.muted + "]");
       broadcastEvent(payload);
     }
-        
+    
+    public function handleUserVoiceLockedEvent(event:BBBEvent):void {
+      var payload:Object = new Object();
+      payload.eventName = EventConstants.USER_LOCKED_VOICE;
+      payload.userID = UsersUtil.internalUserIDToExternalUserID(event.payload.userID);
+      payload.locked = event.payload.locked;
+      
+      trace("Notifying external API that [" + UsersUtil.getUserName(event.payload.userID) + "] is now locked=[" + payload.locked + "]");
+      broadcastEvent(payload);
+    }
+    
+    public function handleUserVoiceLeftEvent(event:BBBEvent):void {
+      var payload:Object = new Object();
+      payload.eventName = EventConstants.USER_LEFT_VOICE;
+      payload.userID = UsersUtil.internalUserIDToExternalUserID(event.payload.userID);
+      
+      trace("Notifying external API that [" + UsersUtil.getUserName(event.payload.userID) + "] has left the voice conference.");
+      
+      broadcastEvent(payload);
+    }
+            
     public function handleNewPublicChatEvent(event:CoreEvent):void {
       var payload:Object = new Object();
       payload.eventName = EventConstants.NEW_PUBLIC_CHAT;
@@ -84,7 +189,7 @@ package org.bigbluebutton.main.api
       broadcastEvent(payload);
     }
         
-    public function handleParticipantJoinEvent(event:ParticipantJoinEvent):void {
+    public function handleUserJoinedEvent(event:UserJoinedEvent):void {
       var payload:Object = new Object();
       var user:BBBUser = UserManager.getInstance().getConference().getUser(event.userID);
       
@@ -93,17 +198,27 @@ package org.bigbluebutton.main.api
         return;
       }
       
-      if (event.join) {
-        payload.eventName = EventConstants.USER_JOINED;
-        payload.userID = user.userID;
-        payload.userName = user.name;        
-      } else {
-        payload.eventName = EventConstants.USER_LEFT;
-        payload.userID = user.userID;
-      }
+      payload.eventName = EventConstants.USER_JOINED;
+      payload.userID = user.userID;
+      payload.userName = user.name;        
       
       broadcastEvent(payload);        
     }    
+
+    public function handleUserLeftEvent(event:UserLeftEvent):void {
+      var payload:Object = new Object();
+      var user:BBBUser = UserManager.getInstance().getConference().getUser(event.userID);
+      
+      if (user == null) {
+        LogUtil.warn("[ExternalApiCall:handleParticipantJoinEvent] Cannot find user with ID [" + event.userID + "]");
+        return;
+      }
+      
+      payload.eventName = EventConstants.USER_LEFT;
+      payload.userID = user.userID;
+      
+      broadcastEvent(payload);        
+    }  
     
     private function broadcastEvent(message:Object):void {
       if (ExternalInterface.available) {
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/api/maps/ExternalApiEventMap.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/api/maps/ExternalApiEventMap.mxml
index a9fd45fafdc4bdf7fcac9a8260995a688f405c2c..e97632ccdb199de9f2dee3724e9f9e44dece839d 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/api/maps/ExternalApiEventMap.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/api/maps/ExternalApiEventMap.mxml
@@ -23,29 +23,82 @@
 <EventMap xmlns="http://mate.asfusion.com/" xmlns:mx="http://www.adobe.com/2006/mxml">
   <mx:Script>
     <![CDATA[
-    import org.bigbluebutton.core.EventConstants;
-    import org.bigbluebutton.main.api.ExternalApiCalls;
-    import org.bigbluebutton.main.events.BBBEvent;
-    import org.bigbluebutton.main.events.ParticipantJoinEvent;
-    import org.bigbluebutton.main.events.MadePresenterEvent;
+      import org.bigbluebutton.core.EventConstants;
+      import org.bigbluebutton.core.events.AmIPresenterQueryEvent;
+      import org.bigbluebutton.core.events.AmISharingWebcamQueryEvent;
+      import org.bigbluebutton.core.events.SwitchedLayoutEvent;
+      import org.bigbluebutton.main.api.ExternalApiCalls;
+      import org.bigbluebutton.main.events.BBBEvent;
+      import org.bigbluebutton.main.events.MadePresenterEvent;
+      import org.bigbluebutton.main.events.UserJoinedEvent;
+      import org.bigbluebutton.main.events.UserLeftEvent;
+      import org.bigbluebutton.main.model.users.events.BroadcastStartedEvent;
+      import org.bigbluebutton.main.model.users.events.BroadcastStoppedEvent;
+      import org.bigbluebutton.main.model.users.events.StreamStartedEvent;
     ]]>
   </mx:Script>
   <!--
     Listen for events we are interested to forward to the external container..
   -->
-  <EventHandlers type="{BBBEvent.ADDED_LISTENER}" >
-    <MethodInvoker generator="{ExternalApiCalls}" method="handleUserJoinedVoiceEvent"/>
+  
+
+  <EventHandlers type="{StreamStartedEvent.STREAM_STARTED}" >
+    <MethodInvoker generator="{ExternalApiCalls}" method="handleStreamStartedEvent" arguments="{event}"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{BroadcastStartedEvent.BROADCAST_STARTED_EVENT}" >
+    <MethodInvoker generator="{ExternalApiCalls}" method="handleBroadcastStartedEvent" arguments="{event}"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{BroadcastStoppedEvent.BROADCAST_STOPPED}" >
+    <MethodInvoker generator="{ExternalApiCalls}" method="handleBroadcastStoppedEvent" arguments="{event}"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{AmIPresenterQueryEvent.AM_I_PRESENTER_QUERY}" >
+    <MethodInvoker generator="{ExternalApiCalls}" method="handleAmIPresenterQueryEvent" arguments="{event}"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{AmISharingWebcamQueryEvent.AM_I_SHARING_CAM_QUERY}" >
+    <MethodInvoker generator="{ExternalApiCalls}" method="handleAmISharingCamQueryEvent" arguments="{event}"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{BBBEvent.USER_VOICE_MUTED}" >
+    <MethodInvoker generator="{ExternalApiCalls}" method="handleUserVoiceMutedEvent" arguments="{event}"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{BBBEvent.USER_VOICE_LOCKED}" >
+    <MethodInvoker generator="{ExternalApiCalls}" method="handleUserVoiceLockedEvent" arguments="{event}"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{BBBEvent.USER_VOICE_LEFT}" >
+    <MethodInvoker generator="{ExternalApiCalls}" method="handleUserVoiceLeftEvent" arguments="{event}"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{BBBEvent.USER_VOICE_JOINED}" >
+    <MethodInvoker generator="{ExternalApiCalls}" method="handleUserJoinedVoiceEvent" arguments="{event}"/>
   </EventHandlers>
   
   <EventHandlers type="{EventConstants.GET_MY_ROLE_RESP}" >
     <MethodInvoker generator="{ExternalApiCalls}" method="handleGetMyRoleResponse" arguments="{event}"/>
   </EventHandlers>
+
+  <EventHandlers type="{SwitchedLayoutEvent.SWITCHED_LAYOUT_EVENT}" >
+    <MethodInvoker generator="{ExternalApiCalls}" method="handleSwitchedLayoutEvent" arguments="{event}"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{AmIPresenterQueryEvent.AM_I_PRESENTER_QUERY}" >
+    <MethodInvoker generator="{ExternalApiCalls}" method="handleAmIPresenterQueryEvent" arguments="{event}"/>
+  </EventHandlers>
   
-  <EventHandlers type="{ParticipantJoinEvent.PARTICIPANT_JOINED_EVENT}" >
-    <MethodInvoker generator="{ExternalApiCalls}" method="handleParticipantJoinEvent" arguments="{event}"/>
+  <EventHandlers type="{UserJoinedEvent.JOINED}" >
+    <MethodInvoker generator="{ExternalApiCalls}" method="handleUserJoinedEvent" arguments="{event}"/>
   </EventHandlers>
 
-  <EventHandlers type="{EventConstants.NEW_ROLE}" >
+  <EventHandlers type="{UserLeftEvent.LEFT}" >
+    <MethodInvoker generator="{ExternalApiCalls}" method="handleUserLeftEvent" arguments="{event}"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{EventConstants.SWITCHED_PRESENTER}" >
     <MethodInvoker generator="{ExternalApiCalls}" method="handleSwitchToNewRoleEvent" arguments="{event}"/>
   </EventHandlers>
 
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/events/BBBEvent.as b/bigbluebutton-client/src/org/bigbluebutton/main/events/BBBEvent.as
index 1f172fee1237e62a304e108796707e47c4d98ae7..a2ed7c0f6114ea389de68d7c36a50b9734e2f2d6 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/events/BBBEvent.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/events/BBBEvent.as
@@ -27,14 +27,20 @@ package org.bigbluebutton.main.events {
 		public static const RECEIVED_PUBLIC_CHAT_MESSAGE_EVENT:String = 'RECEIVED_PUBLIC_CHAT_MESSAGE_EVENT';
 		public static const SEND_PUBLIC_CHAT_MESSAGE_EVENT:String = 'SEND_PUBLIC_CHAT_MESSAGE_EVENT';
 		public static const JOIN_VOICE_CONFERENCE:String = 'BBB_JOIN_VOICE_CONFERENCE';
-		public static const ADDED_LISTENER:String = 'BBB_ADDED_LISTENER';
 		public static const PRESENTATION_CONVERTED:String = 'BBB_PRESENTATION_CONVERTED';
 		public static const START_VIDEO_CONNECTION:String = 'BBB_START_VIDEO_CONNECTION';
 		public static const START_VIDEO_STREAM:String = 'BBB_START_VIDEO_STREAM';
 		public static const VIDEO_STARTED:String = 'BBB_VIDEO_STARTED';
 		public static const START_DESKSHARE:String = 'BBB_START_DESKSHARE';
 		public static const DESKSHARE_STARTED:String = 'BBB_DESKSHARE_STARTED';
-		
+    public static const USER_VOICE_JOINED:String = 'user voice joined event';
+		public static const USER_VOICE_MUTED:String = "user voice muted event";
+    public static const USER_VOICE_LOCKED:String = "user voice locked event";
+    public static const USER_VOICE_LEFT:String = "user voice left event";
+    public static const USER_VOICE_TALKING:String = "user voice talking event";
+    public static const CAMERA_SETTING:String = "camera settings event";
+    public static const OPEN_WEBCAM_PREVIEW:String = "open webcam preview event";
+   
 		public var message:String;
 		public var payload:Object = new Object();
 		
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/events/NetworkStatsEvent.as b/bigbluebutton-client/src/org/bigbluebutton/main/events/NetworkStatsEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..8250908dc643f3f7f4e8e17355ca44a02204ade8
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/events/NetworkStatsEvent.as
@@ -0,0 +1,19 @@
+package org.bigbluebutton.main.events
+{
+	import flash.events.Event;
+	import flash.utils.Dictionary;	 
+
+	public class NetworkStatsEvent extends Event
+	{
+		public static const NETWORK_STATS_EVENTS:String = "NETWORK_STATS_EVENTS";
+		
+		public var downloadStats:Dictionary;
+		public var uploadStats:Dictionary;
+		
+		public function NetworkStatsEvent(bubbles:Boolean=true, cancelable:Boolean=false)
+		{
+			super(NETWORK_STATS_EVENTS, bubbles, cancelable);
+		}
+		
+	}
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/events/StoppedViewingWebcamEvent.as b/bigbluebutton-client/src/org/bigbluebutton/main/events/StoppedViewingWebcamEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..966140a2558e3cacea52df8b2ffc41b59a477ac2
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/events/StoppedViewingWebcamEvent.as
@@ -0,0 +1,17 @@
+package org.bigbluebutton.main.events
+{
+  import flash.events.Event;
+  
+  public class StoppedViewingWebcamEvent extends Event
+  {
+    public static const STOPPED_VIEWING_WEBCAM:String = "stopped viewing webcam event";
+    
+    // The userID of the webcam being viewed.
+    public var webcamUserID:String;
+    
+    public function StoppedViewingWebcamEvent(bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(STOPPED_VIEWING_WEBCAM, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/events/ParticipantJoinEvent.as b/bigbluebutton-client/src/org/bigbluebutton/main/events/UserJoinedEvent.as
similarity index 77%
rename from bigbluebutton-client/src/org/bigbluebutton/main/events/ParticipantJoinEvent.as
rename to bigbluebutton-client/src/org/bigbluebutton/main/events/UserJoinedEvent.as
index b8c56448f8ea86b341013fbf3a23184ad852864b..bc32fcf55fdf3b28f13598a4f1eb4e1d00f2ad8d 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/events/ParticipantJoinEvent.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/events/UserJoinedEvent.as
@@ -22,14 +22,13 @@ package org.bigbluebutton.main.events
 	
 	import org.bigbluebutton.main.model.User;
 
-	public class ParticipantJoinEvent extends Event
+	public class UserJoinedEvent extends Event
 	{
-		public static const PARTICIPANT_JOINED_EVENT:String = 'PARTICIPANT_JOINED_EVENT';
+		public static const JOINED:String = 'user has joined event';
 		
 		public var userID:String;
-		public var join:Boolean = false;
     
-		public function ParticipantJoinEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
+		public function UserJoinedEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
 		{
 			super(type, bubbles, cancelable);
 		}
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/events/UserLeftEvent.as b/bigbluebutton-client/src/org/bigbluebutton/main/events/UserLeftEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..f924233dae4cf5f2dae5548fe71b5036c25ec1d3
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/events/UserLeftEvent.as
@@ -0,0 +1,37 @@
+/**
+* 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.main.events
+{
+	import flash.events.Event;
+	
+	import org.bigbluebutton.main.model.User;
+
+	public class UserLeftEvent extends Event
+	{
+		public static const LEFT:String = 'user has left event';
+		
+		public var userID:String;
+    
+		public function UserLeftEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
+		{
+			super(type, bubbles, cancelable);
+		}
+		
+	}
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/maps/ApplicationEventMap.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/maps/ApplicationEventMap.mxml
index 803f8080c88d938cc17e22a7ffdef3249ab33b29..8bbf1005df798692d6d811c20a3d2a4e53b0be6f 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/maps/ApplicationEventMap.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/maps/ApplicationEventMap.mxml
@@ -31,6 +31,7 @@
 		<ObjectBuilder generator="{ModulesProxy}" cache="global" />
 		<ObjectBuilder generator="{UserService}" cache="global" />
 		<ObjectBuilder generator="{ConfigManager}" cache="global" />
+		<ObjectBuilder generator="{StreamMonitor}" cache="global" />
 	</EventHandlers>
 	
 	<EventHandlers type="{PortTestEvent.TEST_RTMP}" >
@@ -104,17 +105,17 @@
   <EventHandlers type="{ModuleLoadEvent.LAYOUT_MODULE_STARTED}">
     <MethodInvoker generator="{ModulesProxy}" method="startAllModules" />
   </EventHandlers>
-  
+
 	<mx:Script>
 	<![CDATA[
 		import mx.events.FlexEvent;
 		
 		import org.bigbluebutton.core.managers.ConfigManager;
 		import org.bigbluebutton.core.services.SkinningService;
+		import org.bigbluebutton.core.services.StreamMonitor;
 		import org.bigbluebutton.main.events.ConfigEvent;
 		import org.bigbluebutton.main.events.LogoutEvent;
 		import org.bigbluebutton.main.events.ModuleLoadEvent;
-		import org.bigbluebutton.main.events.ParticipantJoinEvent;
 		import org.bigbluebutton.main.events.PortTestEvent;
 		import org.bigbluebutton.main.events.SuccessfulLoginEvent;
 		import org.bigbluebutton.main.events.UserServicesEvent;
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/ConferenceParameters.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/ConferenceParameters.as
index be412ebde72874f4681940253bf123fa33ecb32d..505ebedc3e7673716ce813444bec411a30536114 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/model/ConferenceParameters.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/ConferenceParameters.as
@@ -27,6 +27,10 @@ package org.bigbluebutton.main.model
 	 */	
 	public class ConferenceParameters
 	{
+    public var meetingName:String;
+    
+    public var externMeetingID:String;
+    
 		/**
 		 * The name of the conference
 		 */		
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/NetworkStatsData.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/NetworkStatsData.as
new file mode 100644
index 0000000000000000000000000000000000000000..be046d2e07a8c55bdd5edd827ff68668f75f0c3e
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/NetworkStatsData.as
@@ -0,0 +1,113 @@
+package org.bigbluebutton.main.model
+{
+	
+	import com.asfusion.mate.events.Dispatcher;
+	
+	import org.bigbluebutton.common.LogUtil;
+	import org.bigbluebutton.main.events.NetworkStatsEvent;
+	
+	import flash.events.EventDispatcher;
+	
+	public class NetworkStatsData extends EventDispatcher
+	{
+		private static var _instance:NetworkStatsData = null;
+		private var _currentConsumedDownBW:Number = 0; // Kb
+		private var _currentConsumedUpBW:Number = 0; // Kb
+		private var _totalConsumedDownBW:Number = 0; // MB
+		private var _totalConsumedUpBW:Number = 0; // MB
+		private var _measuredDownBW:int = 0; // Mb
+		private var _measuredDownLatency:int = 0; // ms
+		private var _measuredUpBW:int = 0; // Mb
+		private var _measuredUpLatency:int = 0; // ms
+		
+		/**
+		 * This class is a singleton. Please initialize it using the getInstance() method.
+		 */		
+		public function NetworkStatsData(enforcer:SingletonEnforcer) {
+			if (enforcer == null) {
+				throw new Error("There can only be one instance of this class");
+			}
+			initialize();
+		}
+		
+		private function initialize():void {
+		}
+		
+		/**
+		 * Return the single instance of this class
+		 */
+		public static function getInstance():NetworkStatsData {
+			if (_instance == null){
+				_instance = new NetworkStatsData(new SingletonEnforcer());
+			}
+			return _instance;
+		}
+		
+		// all the numbers are in bytes
+		public function updateConsumedBW(down:Number, up:Number, downTotal:Number, upTotal:Number):void {
+			_currentConsumedDownBW = (down * 8)/1024;
+			_currentConsumedUpBW = (up * 8)/1024;
+			_totalConsumedDownBW = downTotal / 1048576;
+			_totalConsumedUpBW = upTotal / 1048576;
+		}
+		
+		/*
+			12/8/2012 17:24:38.293 [DEBUG] (Array)#0
+			  [deltaDown] 2455.704
+			  [deltaTime] 170
+			  [kbitDown] 14445
+			  [latency] 10
+		*/
+		public function setDownloadMeasuredBW(info:Object):void {
+			_measuredDownBW = info["kbitDown"] / 1000;
+			_measuredDownLatency = info["latency"];
+  		}
+		
+		/*
+			12/8/2012 17:24:39.556 [DEBUG] (Object)#0
+			  deltaTime = 1
+			  deltaUp = 10516
+			  kbitUp = 10516
+			  KBytes = 1283
+			  latency = 11
+		*/
+		public function setUploadMeasuredBW(info:Object):void {
+			_measuredUpBW = info.kbitUp / 1000;
+			_measuredUpLatency = info.latency;
+		}
+		
+		public function get currentConsumedDownBW():Number {
+			return _currentConsumedDownBW;
+		}
+
+		public function get currentConsumedUpBW():Number {
+			return _currentConsumedUpBW;
+		}
+
+		public function get totalConsumedDownBW():Number {
+			return _totalConsumedDownBW;
+		}
+
+		public function get totalConsumedUpBW():Number {
+			return _totalConsumedUpBW;
+		}
+
+		public function get measuredDownBW():int {
+			return _measuredDownBW;
+		}
+
+		public function get measuredDownLatency():int {
+			return _measuredDownLatency;
+		}
+
+		public function get measuredUpBW():int {
+			return _measuredUpBW;
+		}
+
+		public function get measuredUpLatency():int {
+			return _measuredUpLatency;
+		}
+	}
+}
+
+class SingletonEnforcer{}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/Conference.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/Conference.as
index bf46784346a9e73fa92d8d74b728d4e9e7bb178b..b96d515b102e5102b32a4c295eb3a1842ba5fd98 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/Conference.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/Conference.as
@@ -22,21 +22,30 @@ package org.bigbluebutton.main.model.users {
 	import org.bigbluebutton.common.LogUtil;
 	import org.bigbluebutton.common.Role;
 	import org.bigbluebutton.core.BBB;
+	import org.bigbluebutton.core.vo.CameraSettingsVO;
 
 	public class Conference {		
-//		private var _myUserid:Number;		
+    public var meetingName:String;
+    public var externalMeetingID:String;
+    public var internalMeetingID:String;
+    public var avatarURL:String;
+    
+    private var _myCamSettings:CameraSettingsVO;
+    
 		[Bindable] private var me:BBBUser = null;		
 		[Bindable] public var users:ArrayCollection = null;			
-				
+	
+    private var defaultLayout:String;
+    
 		public function Conference():void {
 			me = new BBBUser();
 			users = new ArrayCollection();
 		}
 
 		public function addUser(newuser:BBBUser):void {
-      LogUtil.debug("Adding new user [" + newuser.userID + "]");
+      trace("Adding new user [" + newuser.userID + "]");
 			if (! hasUser(newuser.userID)) {
-        LogUtil.debug("Am I this new user [" + newuser.userID + ", " + me.userID + "]");
+        trace("Am I this new user [" + newuser.userID + ", " + me.userID + "]");
 				if (newuser.userID == me.userID) {
 					newuser.me = true;
 				}						
@@ -46,6 +55,26 @@ package org.bigbluebutton.main.model.users {
 			}					
 		}
 
+    public function setCamPublishing(publishing:Boolean):void {
+      _myCamSettings.isPublishing = publishing;
+    }
+    
+    public function setCameraSettings(camSettings:CameraSettingsVO):void {
+      _myCamSettings = camSettings;
+    }
+    
+    public function amIPublishing():CameraSettingsVO {
+      return _myCamSettings;
+    }
+    
+    public function setDefaultLayout(defaultLayout:String):void {
+      this.defaultLayout = defaultLayout;  
+    }
+    
+    public function getDefaultLayout():String {
+      return defaultLayout;
+    }
+    
 		public function hasUser(userID:String):Boolean {
 			var p:Object = getUserIndex(userID);
 			if (p != null) {
@@ -128,7 +157,7 @@ package org.bigbluebutton.main.model.users {
 		public function removeUser(userID:String):void {
 			var p:Object = getUserIndex(userID);
 			if (p != null) {
-				LogUtil.debug("removing user[" + p.participant.name + "," + p.participant.userID + "]");				
+				trace("removing user[" + p.participant.name + "," + p.participant.userID + "]");				
 				users.removeItemAt(p.index);
 				sort();
 			}							
@@ -281,6 +310,15 @@ package org.bigbluebutton.main.model.users {
 			
 			sort();		
 		}
+    
+    public function getUserIDs():ArrayCollection {
+      var uids:ArrayCollection = new ArrayCollection();
+      for (var i:int = 0; i < users.length; i++) {
+        var u:BBBUser = users.getItemAt(i) as BBBUser;
+        uids.addItem(u.userID);
+      }
+      return uids;
+    }
 		
 		/**
 		 * Sorts the users by name 
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/JoinService.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/JoinService.as
index 25c582b2e974a00c99598e92c861e4c23d34a7c0..f28b97621858ad25c95ede0f21fb1aa89c9038bd 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/JoinService.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/JoinService.as
@@ -67,11 +67,12 @@ package org.bigbluebutton.main.model.users
 				
 			} else if (returncode == 'SUCCESS') {
 				LogUtil.debug("Join SUCESS = " + xml);
-				var user:Object = {username:xml.fullname, conference:xml.conference, conferenceName:xml.confname,
+				var user:Object = {username:xml.fullname, conference:xml.conference, conferenceName:xml.confname, externMeetingID:xml.externMeetingID,
 										meetingID:xml.meetingID, externUserID:xml.externUserID, internalUserId:xml.internalUserID,
 										role:xml.role, room:xml.room, authToken:xml.room, record:xml.record, 
 										webvoiceconf:xml.webvoiceconf,
-										voicebridge:xml.voicebridge, mode:xml.mode, welcome:xml.welcome, logoutUrl:xml.logoutUrl};
+										voicebridge:xml.voicebridge, mode:xml.mode, welcome:xml.welcome, logoutUrl:xml.logoutUrl, 
+                    defaultLayout:xml.defaultLayout, avatarURL:xml.avatarURL};
 				
 				if (_resultListener != null) _resultListener(true, user);
 			}
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/NetConnectionDelegate.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/NetConnectionDelegate.as
index deebb5977ab035a5a995aed223a6b9122659e91c..f234754490fb4c34313b6f891623b6cd54aad5e6 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/NetConnectionDelegate.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/NetConnectionDelegate.as
@@ -18,16 +18,13 @@
 */
 package org.bigbluebutton.main.model.users
 {
-	import com.asfusion.mate.events.Dispatcher;
-	
+	import com.asfusion.mate.events.Dispatcher;	
 	import flash.events.*;
 	import flash.net.NetConnection;
 	import flash.net.Responder;
 	import flash.utils.Timer;
-	
-	import mx.controls.Alert;
-	
 	import org.bigbluebutton.common.LogUtil;
+	import org.bigbluebutton.core.services.BandwidthMonitor;
 	import org.bigbluebutton.main.model.ConferenceParameters;
 	import org.bigbluebutton.main.model.users.events.ConnectionFailedEvent;
 	import org.bigbluebutton.main.model.users.events.UsersConnectionEvent;
@@ -68,51 +65,45 @@ package org.bigbluebutton.main.model.users
 			_netConnection.addEventListener( IOErrorEvent.IO_ERROR, netIOError );
 		}
 		
-        public function setUri(uri:String):void {
-            _applicationURI = uri;
-        }
+    public function setUri(uri:String):void {
+      _applicationURI = uri;
+    }
        
         
 		public function get connection():NetConnection {
 			return _netConnection;
 		}
         
-        public function addMessageListener(listener:IMessageListener):void
-        {
-            _messageListeners.push(listener);
-        }
+    public function addMessageListener(listener:IMessageListener):void {
+      _messageListeners.push(listener);
+    }
         
-        public function removeMessageListener(listener:IMessageListener):void
-        {
-            for (var ob:int=0; ob<_messageListeners.length; ob++)
-            {
-                if (_messageListeners[ob]==listener)                    
-                {
-                    _messageListeners.splice (ob,1);
-                    break;
-                }
-            }
+    public function removeMessageListener(listener:IMessageListener):void {
+      for (var ob:int=0; ob<_messageListeners.length; ob++) {
+        if (_messageListeners[ob] == listener) {
+          _messageListeners.splice (ob,1);
+          break;
         }
+      }
+    }
         
-        private function notifyListeners(messageName:String, message:Object):void
-        {
-            if (messageName != null && messageName != "") {
-                for (var notify:String in _messageListeners)
-                {
-                    _messageListeners[notify].onMessage(messageName, message);
-                }                
-            } else {
-                LogUtil.debug("Message name is undefined");
-            }
-        }   
+    private function notifyListeners(messageName:String, message:Object):void {
+      if (messageName != null && messageName != "") {
+        for (var notify:String in _messageListeners) {
+          _messageListeners[notify].onMessage(messageName, message);
+        }                
+      } else {
+        LogUtil.debug("Message name is undefined");
+      }
+    }   
         
-        public function onMessageFromServer(messageName:String, result:Object):void {
-//            LogUtil.debug("Got message from server [" + messageName + "]");    
-            notifyListeners(messageName, result);
-        }
+    public function onMessageFromServer(messageName:String, result:Object):void {
+      trace("Got message from server [" + messageName + "]");    
+      notifyListeners(messageName, result);
+    }
 		
 		public function sendMessage(service:String, onSuccess:Function, onFailure:Function, message:Object=null):void {
-//			LogUtil.debug("SENDING [" + service + "]");
+      trace("SENDING [" + service + "]");
 			var responder:Responder =	new Responder(                    
 					function(result:Object):void { // On successful result
 						onSuccess("Successfully sent [" + service + "]."); 
@@ -130,7 +121,6 @@ package org.bigbluebutton.main.model.users
 			} else {
 				_netConnection.call(service, responder, message);
 			}
-
 		}
 		
 		/**
@@ -142,8 +132,7 @@ package org.bigbluebutton.main.model.users
 		 * mode: LIVE/PLAYBACK - Live:when used to collaborate, Playback:when being used to playback a recorded conference.
 		 * room: Need the room number when playing back a recorded conference. When LIVE, the room is taken from the URI.
 		 */
-		public function connect(params:ConferenceParameters, tunnel:Boolean = false):void
-		{	
+		public function connect(params:ConferenceParameters, tunnel:Boolean = false):void {	
 			_conferenceParameters = params;
 			
 			tried_tunneling = tunnel;	
@@ -157,10 +146,9 @@ package org.bigbluebutton.main.model.users
 											_conferenceParameters.room, _conferenceParameters.voicebridge, 
 											_conferenceParameters.record, _conferenceParameters.externUserID,
 											_conferenceParameters.internalUserID);			
-			} catch( e : ArgumentError ) {
+			} catch(e:ArgumentError) {
 				// Invalid parameters.
-				switch ( e.errorID ) 
-				{
+				switch (e.errorID) {
 					case 2004 :						
 						LogUtil.debug("Error! Invalid server location: " + uri);											   
 						break;						
@@ -171,8 +159,7 @@ package org.bigbluebutton.main.model.users
 			}	
 		}
 			
-		public function disconnect(logoutOnUserCommand:Boolean) : void
-		{
+		public function disconnect(logoutOnUserCommand:Boolean):void {
 			this.logoutOnUserCommand = logoutOnUserCommand;
 			_netConnection.close();
 		}
@@ -182,22 +169,33 @@ package org.bigbluebutton.main.model.users
       _netConnection.close();
     }
     
-		protected function netStatus( event : NetStatusEvent ) : void 
-		{
+		protected function netStatus(event:NetStatusEvent):void {
 			handleResult( event );
 		}
 		
+    private var _bwMon:BandwidthMonitor = new BandwidthMonitor();
+    
+    private function startMonitoringBandwidth():void {
+      trace("Start monitoring bandwidth.");
+      var pattern:RegExp = /(?P<protocol>.+):\/\/(?P<server>.+)\/(?P<app>.+)/;
+      var result:Array = pattern.exec(_applicationURI);
+      _bwMon.serverURL = result.server;
+      _bwMon.serverApplication = "video";
+      _bwMon.start();
+    }
+        
     private var autoReconnectTimer:Timer = new Timer(1000, 1);
     
-		public function handleResult(  event : Object  ) : void {
+		public function handleResult(event:Object):void {
 			var info : Object = event.info;
 			var statusCode : String = info.code;
 
-			switch ( statusCode ) 
-			{
+			switch (statusCode) {
 				case "NetConnection.Connect.Success":
 					LogUtil.debug(NAME + ":Connection to viewers application succeeded.");
-
+          
+					startMonitoringBandwidth();
+          
 					_netConnection.call(
 							"getMyUserId",// Remote function name
 							new Responder(
@@ -270,7 +268,6 @@ package org.bigbluebutton.main.model.users
 		
     private function autoReconnectTimerHandler(event:TimerEvent):void {
       LogUtil.debug(NAME + "autoReconnectTimerHandler: " + event);
-      Alert.show("Attempting to reconnect");
       connect(_conferenceParameters, tried_tunneling);
     }
         
@@ -351,6 +348,7 @@ package org.bigbluebutton.main.model.users
 		public function onBWCheck(... rest):Number { 
 			return 0; 
 		} 
+    
 		public function onBWDone(... rest):void { 
 			var p_bw:Number; 
 			if (rest.length > 0) p_bw = rest[0]; 
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as
index 3aae5123d50f8792fa5f28e27033b81ba9934c2c..e19fd8598e9c6fe68f9f3269e8327065eac56731 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as
@@ -66,8 +66,16 @@ package org.bigbluebutton.main.model.users
 				UserManager.getInstance().getConference().setMyRole(result.role);
 				UserManager.getInstance().getConference().setMyRoom(result.room);
 				UserManager.getInstance().getConference().setMyAuthToken(result.authToken);
-				
+        UserManager.getInstance().getConference().setDefaultLayout(result.defaultLayout);
+        
+        UserManager.getInstance().getConference().externalMeetingID = result.externMeetingID;
+        UserManager.getInstance().getConference().meetingName = result.confereceName;
+        UserManager.getInstance().getConference().internalMeetingID = result.room;
+        UserManager.getInstance().getConference().avatarURL = result.avatarURL;
+        
 				_conferenceParameters = new ConferenceParameters();
+        _conferenceParameters.meetingName = result.confereceName;
+        _conferenceParameters.externMeetingID = result.externMeetingID;
 				_conferenceParameters.conference = result.conference;
 				_conferenceParameters.username = result.username;
 				_conferenceParameters.role = result.role;
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UsersSOService.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UsersSOService.as
index 8cd249b5541cc6c02360c7d9ae313bc89598ad4b..fc2c3edbd0f6c51d23b81876503ecf18abc6765c 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UsersSOService.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UsersSOService.as
@@ -35,8 +35,9 @@ package org.bigbluebutton.main.model.users {
 	import org.bigbluebutton.main.events.BBBEvent;
 	import org.bigbluebutton.main.events.LogoutEvent;
 	import org.bigbluebutton.main.events.MadePresenterEvent;
-	import org.bigbluebutton.main.events.ParticipantJoinEvent;
 	import org.bigbluebutton.main.events.PresenterStatusEvent;
+	import org.bigbluebutton.main.events.UserJoinedEvent;
+	import org.bigbluebutton.main.events.UserLeftEvent;
 	import org.bigbluebutton.main.model.ConferenceParameters;
 	import org.bigbluebutton.main.model.users.events.ConnectionFailedEvent;
 	import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
@@ -164,7 +165,7 @@ package org.bigbluebutton.main.model.users {
 		 * Called by the server to assign a presenter
 		 */
 		public function assignPresenterCallback(userid:String, name:String, assignedBy:String):void {
-			LogUtil.debug("assignPresenterCallback " + userid + "," + name + "," + assignedBy);
+			trace("assignPresenterCallback " + userid + "," + name + "," + assignedBy);
 			var dispatcher:Dispatcher = new Dispatcher();
 			var meeting:Conference = UserManager.getInstance().getConference();
 			if (meeting.amIThisUser(userid)) {
@@ -175,8 +176,8 @@ package org.bigbluebutton.main.model.users {
 				e.assignerBy = assignedBy;
 				
 				dispatcher.dispatchEvent(e);		
-        
-        var roleEvent:CoreEvent = new CoreEvent(EventConstants.NEW_ROLE);
+        trace("Switching to [" + e.presenterName + "] to presenter");
+        var roleEvent:CoreEvent = new CoreEvent(EventConstants.SWITCHED_PRESENTER);
         roleEvent.message.role = Role.PRESENTER;
         dispatcher.dispatchEvent(roleEvent);
         
@@ -189,7 +190,8 @@ package org.bigbluebutton.main.model.users {
 
 				dispatcher.dispatchEvent(viewerEvent);
         
-        var newRoleEvent:CoreEvent = new CoreEvent(EventConstants.NEW_ROLE);
+        trace("Switching to [" + e.presenterName + "] to presenter. I am viewer.");
+        var newRoleEvent:CoreEvent = new CoreEvent(EventConstants.SWITCHED_PRESENTER);
         newRoleEvent.message.role = Role.VIEWER;
         dispatcher.dispatchEvent(newRoleEvent);
 			}
@@ -211,9 +213,8 @@ package org.bigbluebutton.main.model.users {
 			UserManager.getInstance().getConference().removeUser(userID);	
 			
 			var dispatcher:Dispatcher = new Dispatcher();
-			var joinEvent:ParticipantJoinEvent = new ParticipantJoinEvent(ParticipantJoinEvent.PARTICIPANT_JOINED_EVENT);
+			var joinEvent:UserLeftEvent = new UserLeftEvent(UserLeftEvent.LEFT);
 			joinEvent.userID = user.userID;
-			joinEvent.join = false;
 			dispatcher.dispatchEvent(joinEvent);	
 		}
 		
@@ -233,9 +234,8 @@ package org.bigbluebutton.main.model.users {
 			participantStatusChange(user.userID, "raiseHand", joinedUser.status.raiseHand);
 			
 			var dispatcher:Dispatcher = new Dispatcher();
-			var joinEvent:ParticipantJoinEvent = new ParticipantJoinEvent(ParticipantJoinEvent.PARTICIPANT_JOINED_EVENT);
+			var joinEvent:UserJoinedEvent = new UserJoinedEvent(UserJoinedEvent.JOINED);
 			joinEvent.userID = user.userID;
-			joinEvent.join = true;
 			dispatcher.dispatchEvent(joinEvent);	
 			
 		}
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/events/BroadcastStartedEvent.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/events/BroadcastStartedEvent.as
index 9f615094d0b8d368f748f39d0f26d87889cdb9a6..96852e7db36fc4c37cfd2232975ba29f76ce98a9 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/events/BroadcastStartedEvent.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/events/BroadcastStartedEvent.as
@@ -20,15 +20,18 @@
 {
 	import flash.events.Event;
 	
+	import org.bigbluebutton.core.vo.CameraSettingsVO;
+	
 	public class BroadcastStartedEvent extends Event
 	{
 		public static const BROADCAST_STARTED_EVENT:String = "BROADCAST_STARTED_EVENT";
 		
 		public var stream:String;
 		public var userid:String;
-		
-		public function BroadcastStartedEvent(type:String = BROADCAST_STARTED_EVENT)
-		{
+		public var isPresenter:Boolean;
+    public var camSettings:CameraSettingsVO;
+    
+		public function BroadcastStartedEvent(type:String = BROADCAST_STARTED_EVENT) {
 			super(type, true, false);
 		}
 
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/CameraDisplaySettings.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/CameraDisplaySettings.mxml
new file mode 100755
index 0000000000000000000000000000000000000000..18b5fce6c538d711c21d70dffc17add3a6b7fd4a
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/CameraDisplaySettings.mxml
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="utf-8"?>
+<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" 
+                xmlns:view="org.bigbluebutton.main.views.*"
+                layout="absolute" 
+                width="600" height="400" creationComplete="onCreationComplete()" 
+                showCloseButton="true" close="onCancelClicked()" keyDown="handleKeyDown(event)">
+  <mx:Script>
+    <![CDATA[
+      import com.asfusion.mate.events.Dispatcher;
+      
+      import flash.ui.Keyboard;
+      
+      import mx.events.CloseEvent;
+      import mx.events.ItemClickEvent;
+      import mx.managers.PopUpManager;
+      
+      import org.bigbluebutton.common.Images;
+      import org.bigbluebutton.common.LogUtil;
+      import org.bigbluebutton.core.UsersUtil;
+      import org.bigbluebutton.main.events.BBBEvent;
+      import org.bigbluebutton.modules.videoconf.model.VideoConfOptions;
+      import org.bigbluebutton.util.i18n.ResourceUtil;
+      
+      static public var PADDING_HORIZONTAL:Number = 6;
+      static public var PADDING_VERTICAL:Number = 29;
+      
+      private var images:Images = new Images();
+      
+      [Bindable] 
+      private var cancelIcon:Class = images.control_play;
+      
+      [Bindable]
+      public var resolutions:Array;
+      public var publishInClient:Boolean;
+      
+      public var camWidth:Number = 320;
+      public var camHeight:Number = 240;
+      private var _camera:Camera = null;
+      
+      // Timer used to enable the start publishing button, only after get any activity on the camera. 
+      // It avoids the problem of publishing a blank video
+      private var _activationTimer:Timer = null;
+      private var _waitingForActivation:Boolean = false;
+      
+      static private var _cameraAccessDenied:Boolean = false;
+      
+      [Bindable]
+      private var camIcon:Class = images.webcam;
+      
+      private var _video:Video;
+      private var aspectRatio:Number = 1;
+      
+      private function onCreationComplete():void {          
+        changeDefaultCamForMac();
+        
+        if (UsersUtil.amIPresenter()) {
+          showResControls(true);
+        }
+        
+        if (Camera.names.length > 1) {
+          showVideoControls(true);
+        }
+        
+        updateCamera();
+      }
+      
+      private function changeDefaultCamForMac():void {
+        for (var i:int = 0; i < Camera.names.length; i++){
+          if (Camera.names[i] == "USB Video Class Video") {
+            /** Set as default for Macs */
+            cmbCameraSelector.selectedIndex = i;
+          }
+        }
+      }
+      
+      private function showVideoControls(show:Boolean):void {
+        if (show) {
+          this.visible = true;
+          btnStartPublish.visible = true;
+          cmbCameraSelector.visible = true;
+        } else{					
+          this.width = 0;
+          this.height = 0;
+          btnStartPublish.visible = false;
+          cmbCameraSelector.visible = false;
+          this.visible = false;
+        }
+      }
+      
+      private function updateCamera():void {
+        _camera = null;
+        
+        _camera = Camera.getCamera(); 
+        
+        if (_camera == null) {
+          _videoHolder.showWarning('bbb.video.publish.hint.cantOpenCamera');
+          return;
+        }
+        
+        _camera.addEventListener(ActivityEvent.ACTIVITY, onActivityEvent);
+        _camera.addEventListener(StatusEvent.STATUS, onStatusEvent);
+        
+        if (_camera.muted) {
+          if (_cameraAccessDenied) {
+            onCameraAccessDisallowed();
+            return;
+          } else {
+            _videoHolder.showWarning('bbb.video.publish.hint.waitingApproval');
+          }
+        } else {
+          // if the camera isn't muted, that is because the user has
+          // previously allowed the camera capture on the flash privacy box
+          onCameraAccessAllowed();
+        }
+        
+        displayVideoPreview();
+      }
+      
+      private function displayVideoPreview():void {       
+        var videoOptions:VideoConfOptions = new VideoConfOptions();
+        _camera.setMotionLevel(5, 1000);
+        _camera.setKeyFrameInterval(videoOptions.camKeyFrameInterval);
+        _camera.setMode(camWidth, camHeight, videoOptions.camModeFps);
+        _camera.setQuality(videoOptions.camQualityBandwidth, videoOptions.camQualityPicture);
+        
+        if (_camera.width != camWidth || _camera.height != camHeight) {
+          LogUtil.debug("Resolution " + camWidth + "x" + camHeight + " is not supported, using " + _camera.width + "x" + _camera.height + " instead");
+          setResolution(_camera.width, _camera.height);
+        }
+        
+        setComboResolution();
+        
+        if (_video != null) {
+          _videoHolder.remove(_video);
+        }
+        
+        _video = new Video();       
+        _video.attachCamera(_camera);
+        
+        aspectRatio = (_video.width / _video.height);
+        
+        if (aspectRatio > _videoHolder.width / _videoHolder.height) {
+          _video.width = _videoHolder.width;
+          _video.height = _videoHolder.width / aspectRatio;
+          _video.x = 0;
+          _video.y = (_videoHolder.height - _video.height) / 2;
+        } else {
+          _video.width = _videoHolder.height * aspectRatio;
+          _video.height = _videoHolder.height;
+          _video.x = (_videoHolder.width - _video.width) / 2;
+          _video.y = 0;
+        }				
+        
+        _videoHolder.add(_video);
+      }
+      
+      private function showResControls(show:Boolean):void {
+        if (show) cmbResolution.visible = true;
+        else cmbResolution.visible = false;
+      }
+      
+      private function setComboResolution():void {
+        var res:Array = cmbResolution.selectedLabel.split( "x" );
+        setResolution(Number(res[0]), Number(res[1]));
+      }
+      
+      private function setAspectRatio(width:int, height:int):void {
+        aspectRatio = (width/height);
+        this.minHeight = Math.floor((this.minWidth - PADDING_HORIZONTAL) / aspectRatio) + PADDING_VERTICAL;
+      }
+      
+      private function setResolution(width:int, height:int):void {
+        camWidth = width;
+        camHeight = height;
+        setAspectRatio(camWidth, camHeight);
+      }
+      
+      private function startPublishing():void {
+        // Save the index of the camera. Need it to send the message.
+        var camIndex:int = _camera.index;
+        
+        disableCamera();
+        
+        var globalDispatcher:Dispatcher = new Dispatcher();
+        var camEvent:BBBEvent = new BBBEvent(BBBEvent.CAMERA_SETTING);
+        camEvent.payload.cameraIndex = camIndex;
+        camEvent.payload.cameraWidth = camWidth;
+        camEvent.payload.cameraHeight = camHeight;
+        camEvent.payload.publishInClient = publishInClient;
+        
+        globalDispatcher.dispatchEvent(camEvent);
+        
+        PopUpManager.removePopUp(this);
+      }
+      
+      private function disableCamera():void {
+        _camera = null;
+        _video.attachCamera(null);
+        _video.clear();
+        _videoHolder.remove(_video);
+        _video = null;        
+      }
+      
+      private function handleKeyDown(event:KeyboardEvent):void {
+        if (event.charCode == Keyboard.ESCAPE) {
+          disableCamera();
+          this.dispatchEvent(new CloseEvent(CloseEvent.CLOSE));
+        }
+      }
+      
+      private function onCancelClicked():void {
+        disableCamera();
+        PopUpManager.removePopUp(this);
+      }
+      
+      private function onActivityEvent(e:ActivityEvent):void {
+        if (_waitingForActivation && e.activating) {
+          _activationTimer.stop();
+          _videoHolder.showWarning('bbb.video.publish.hint.videoPreview', false, "0xFFFF00");
+          //        controls.btnStartPublish.enabled = true;
+          _waitingForActivation = false;
+        }
+      }
+      
+      private function onStatusEvent(e:StatusEvent):void {
+        if (e.code == "Camera.Unmuted") {
+          onCameraAccessAllowed();
+          // this is just to overwrite the message of waiting for approval
+          _videoHolder.showWarning('bbb.video.publish.hint.openingCamera');
+        } else if (e.code == "Camera.Muted") {
+          onCameraAccessDisallowed();
+        }
+      }
+      
+      private function onCameraAccessAllowed():void {
+        // set timer to ensure that the camera activates.  If not, it might be in use by another application
+        _waitingForActivation = true;
+        if (_activationTimer != null) {
+          _activationTimer.stop();
+        }
+        
+        _activationTimer = new Timer(10000, 1);
+        _activationTimer.addEventListener(TimerEvent.TIMER, activationTimeout);
+        _activationTimer.start();
+      }
+      
+      private function onCameraAccessDisallowed():void {
+        _videoHolder.showWarning('bbb.video.publish.hint.cameraDenied');
+        _cameraAccessDenied = true;
+      }
+      
+      private function activationTimeout(e:TimerEvent):void {
+        _videoHolder.showWarning('bbb.video.publish.hint.cameraIsBeingUsed');
+      } 
+      
+      private function showCameraSettings():void {
+        Security.showSettings(SecurityPanel.CAMERA);
+      }
+      
+    ]]>
+  </mx:Script>
+  
+  <mx:VBox id="webcamDisplay" width="100%" height="100%" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5">
+    <view:VideoHolder id="_videoHolder" width="100%" height="90%"/>
+    <mx:HBox width="100%"> 
+      <mx:Button id="btnStartPublish" toolTip="{ResourceUtil.getInstance().getString('bbb.publishVideo.startPublishBtn.toolTip')}" icon="{camIcon}" click="startPublishing()" enabled="true"/>
+      <mx:ComboBox id="cmbCameraSelector" dataProvider="{Camera.names}" width="150" visible="false" change="updateCamera()"/>
+      <mx:Button id="changeCamera" label="Change Camera" toolTip="{ResourceUtil.getInstance().getString('bbb.publishVideo.startPublishBtn.toolTip')}" click="showCameraSettings()"/>
+      <mx:ComboBox id="cmbResolution" dataProvider="{resolutions}" width="20%" visible="false" change="updateCamera()"/>
+    </mx:HBox>
+    
+  </mx:VBox>		
+</mx:TitleWindow>
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml
index 69510d23fed3c9cd2132abd06d7260bc1c3439e3..2653e61f056c60dee0ba65a923d5680e3a4cbbfe 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml
@@ -44,7 +44,8 @@
 	<mate:Listener type="{ToolbarButtonEvent.ADD}" method="handleAddToolbarComponent" />	
 	<mate:Listener type="{ToolbarButtonEvent.REMOVE}" method="handleRemoveToolbarComponent"/>
 	<mate:Listener type="{ShortcutEvent.OPEN_SHORTCUT_WIN}" method="openShortcutHelpWindow" />
-	
+  <mate:Listener type="{BBBEvent.OPEN_WEBCAM_PREVIEW}" method="openVideoPreviewWindow" />
+  
 	<mx:Script>
 		<![CDATA[
 			import com.asfusion.mate.events.Dispatcher;
@@ -61,7 +62,7 @@
 			import mx.core.UIComponent;
 			import mx.events.CloseEvent;
 			import mx.managers.PopUpManager;
-			
+			import flash.geom.Point;
 			import org.bigbluebutton.common.IBbbModuleWindow;
 			import org.bigbluebutton.common.Images;
 			import org.bigbluebutton.common.LogUtil;
@@ -102,7 +103,8 @@
 			[Bindable] private var fullscreen_icon:Class = images.full_screen;
 			[Bindable] private var logs_icon:Class = images.table;
 			[Bindable] private var reset_layout_icon:Class = images.layout;
-
+      [Bindable] private var statsIcon:Class = images.bandwidth;
+      
 			private var receivedConfigLocaleVer:Boolean = false;
 			private var receivedResourceLocaleVer:Boolean = false;
 			
@@ -240,7 +242,7 @@
 	   		
 	   		private function handleCloseWindowEvent(event:CloseWindowEvent):void {
 	   			var window:IBbbModuleWindow = event.window;
-				mdiCanvas.removeWindow(window);
+				  mdiCanvas.removeWindow(window);
 	   		}
 	   		
 	   		private function resetLayout():void{
@@ -273,8 +275,21 @@
 				micSettings.x = point1.x - (micSettings.width/2);
 				micSettings.y = point1.y - (micSettings.height/2);	
 			}
-			
-	   		private function wrongLocaleVersion():void {
+			
+      private function openVideoPreviewWindow(event:BBBEvent):void {
+        var camSettings:CameraDisplaySettings = CameraDisplaySettings(PopUpManager.createPopUp(mdiCanvas, CameraDisplaySettings, true));		
+        camSettings.resolutions = (event.payload.resolutions as String).split(",");
+        camSettings.publishInClient = event.payload.publishInClient;
+        
+        var point1:Point = new Point();
+        // Calculate position of TitleWindow in Application's coordinates. 
+        point1.x = width/2;
+        point1.y = height/2;                
+        camSettings.x = point1.x - (camSettings.width/2);
+        camSettings.y = point1.y - (camSettings.height/2);	
+      }
+      
+	   	private function wrongLocaleVersion():void {
 				var localeWindow:OldLocaleWarnWindow = OldLocaleWarnWindow(PopUpManager.createPopUp(mdiCanvas, OldLocaleWarnWindow, false));
 
 				var point1:Point = new Point();
@@ -283,7 +298,7 @@
 				point1.y = height/2;              
 				localeWindow.x = point1.x - (localeWindow.width/2);
 				localeWindow.y = point1.y - (localeWindow.height/2);	
-            }
+      }
 			
 			private function handleLogout(e:ConnectionFailedEvent):void {
 				if (layoutOptions.showLogoutWindow) {
@@ -343,7 +358,27 @@
 				if (addedBtns.contains(event.button as UIComponent))
 					addedBtns.removeChild(event.button as UIComponent);
 			}
+
+			private var networkStatsWindow:NetworkStatsWindow = new NetworkStatsWindow();
+
+			private function openNetworkStatsWindow(e:Event = null):void {
+				/*var btnPosition:Point = new Point(btnNetwork.x, btnNetwork.y);
+				var btnPositionOnGlobal:Point = btnNetwork.localToGlobal(btnPosition);
+				var windowPosition:Point = networkStatsWindow.globalToLocal(btnPositionOnGlobal);
+				
+				windowPosition.x += btnNetwork.width + 10;
+				windowPosition.y -= networkStatsWindow.height - 10;
+
+				networkStatsWindow.x = windowPosition.x;
+				networkStatsWindow.y = windowPosition.y;*/
+
+				networkStatsWindow.appear();
+			}
 			
+			private function closeNetworkStatsWindow(e:Event = null):void {
+				networkStatsWindow.disappear();
+			}
+
 		]]>
 	</mx:Script>
 			
@@ -360,6 +395,7 @@
     <mx:Label text="{isTunneling ? '[Tunnelling]' : ''}" id="isTunnellingLbl"/>
 		<mx:Button width="20" height="20" visible="{layoutOptions.showLogButton}" toolTip="{ResourceUtil.getInstance().getString('bbb.mainshell.logBtn.toolTip')}" id="logBtn" icon="{logs_icon}" click="openLogWindow()" />
 		<!-- mx:Button width="20" height="20" visible="{layoutOptions.showResetLayout}" toolTip="{ResourceUtil.getInstance().getString('bbb.mainshell.resetLayoutBtn.toolTip')}" id="btnResetLayout" icon="{reset_layout_icon}" click="resetLayout()" /-->
+		<mx:Button id="btnNetwork" icon="{statsIcon}" width="20" height="20" mouseOver="openNetworkStatsWindow()" mouseOut="closeNetworkStatsWindow()" />		
 		<mx:HBox id="addedBtns" />
 	</mx:ControlBar>
 </mx:VBox>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/MainToolbar.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/MainToolbar.mxml
index a8ea450bd833c91c2113b6c3734c1769c7bfbd0f..5cc376264472fbc2dadc1f876bf4e2ab52e2eb0d 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/views/MainToolbar.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/MainToolbar.mxml
@@ -33,24 +33,25 @@
 	
 	<mx:Script>
 		<![CDATA[
-      import com.asfusion.mate.events.Dispatcher;
-      
-      import mx.core.UIComponent;
-      
-      import org.bigbluebutton.common.IBbbToolbarComponent;
-      import org.bigbluebutton.common.LogUtil;
-      import org.bigbluebutton.common.events.CloseWindowEvent;
-      import org.bigbluebutton.common.events.ToolbarButtonEvent;
-      import org.bigbluebutton.core.BBB;
-      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.ShortcutEvent;
-      import org.bigbluebutton.main.events.SuccessfulLoginEvent;
-      import org.bigbluebutton.main.model.LayoutOptions;
-      import org.bigbluebutton.main.model.users.events.ConnectionFailedEvent;
-      import org.bigbluebutton.util.i18n.ResourceUtil;
+			import com.asfusion.mate.events.Dispatcher;		
+			import mx.core.UIComponent;
+			import org.bigbluebutton.common.IBbbToolbarComponent;
+			import org.bigbluebutton.common.LogUtil;
+			import org.bigbluebutton.common.events.CloseWindowEvent;
+			import org.bigbluebutton.common.events.OpenWindowEvent;
+			import org.bigbluebutton.common.events.ToolbarButtonEvent;
+			import org.bigbluebutton.core.BBB;
+			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.ShortcutEvent;
+			import org.bigbluebutton.main.events.SuccessfulLoginEvent;
+			import org.bigbluebutton.main.model.LayoutOptions;
+			import org.bigbluebutton.main.model.users.events.ConnectionFailedEvent;
+			import org.bigbluebutton.util.i18n.ResourceUtil;
+			import org.bigbluebutton.core.services.BandwidthMonitor;
+
 
 			private var DEFAULT_HELP_URL:String = "http://www.bigbluebutton.org/content/videos";
 			
@@ -160,7 +161,7 @@
 				var d:Dispatcher = new Dispatcher();
 				d.dispatchEvent(new ShortcutEvent(ShortcutEvent.OPEN_SHORTCUT_WIN));
 			}
-			
+
 		]]>
 	</mx:Script>	
 	<mx:HBox id="addedBtns"/>
@@ -169,8 +170,11 @@
 <!--
   <mx:Button label="DISCONNECT!" click="BBB.initConnectionManager().forceClose()" height="22" toolTip="Click to simulate disconnection" />
 -->
-	<mx:Button label="{ResourceUtil.getInstance().getString('bbb.mainToolbar.shortcutBtn')}" click="onShortcutButtonClick()" height="22" toolTip="{ResourceUtil.getInstance().getString('bbb.mainToolbar.shortcutBtn.toolTip')}" />
-	<mx:LinkButton id="helpBtn" label="{ResourceUtil.getInstance().getString('bbb.mainToolbar.helpBtn')}" visible="{showHelpBtn}" click="onHelpButtonClicked()" height="22"/>
-	<mx:Button label="{ResourceUtil.getInstance().getString('bbb.mainToolbar.logoutBtn')}" id="btnLogout" 
+	<mx:Button label="{ResourceUtil.getInstance().getString('bbb.mainToolbar.shortcutBtn')}" styleName="shortcutButtonStyle"
+             click="onShortcutButtonClick()" height="22" 
+             toolTip="{ResourceUtil.getInstance().getString('bbb.mainToolbar.shortcutBtn.toolTip')}" />
+	<mx:LinkButton id="helpBtn" label="{ResourceUtil.getInstance().getString('bbb.mainToolbar.helpBtn')}" 
+                 visible="{showHelpBtn}" click="onHelpButtonClicked()" height="22" styleName="helpLinkButtonStyle"/>
+	<mx:Button label="{ResourceUtil.getInstance().getString('bbb.mainToolbar.logoutBtn')}" id="btnLogout" styleName="logoutButtonStyle"
 			   toolTip="{ResourceUtil.getInstance().getString('bbb.mainToolbar.logoutBtn.toolTip')}" right="10" click="doLogout()" height="22"/>
 </mx:ApplicationControlBar>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/MicSettings.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/MicSettings.mxml
index f8931c8fbd682c36b94acec51569c73365f80911..fdc02cea62602590693544e34a7dcc90658f69dc 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/views/MicSettings.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/MicSettings.mxml
@@ -3,6 +3,7 @@
 		width="600" height="300" creationComplete="initDefaultMic()" showCloseButton="true" close="onCancelClicked()" keyDown="handleKeyDown(event)">
 	<mx:Script>
 		<![CDATA[
+			import flash.system.Security;
 			import flash.ui.Keyboard;
 		
 			import mx.events.CloseEvent;
@@ -23,13 +24,20 @@
 			private var mic:Microphone;
 			private var playingAudio:Boolean = false;
 			private var images:Images = new Images();
-			[Bindable] private var cancelIcon:Class = images.delete_icon;
+			[Bindable] private var cancelIcon:Class = images.cancel;
 			
 			private function initDefaultMic():void {
-				mic = Microphone.getMicrophone(-1);
-				mic.setLoopBack(true);
+				mic = Microphone.getMicrophone();
+				
 				if (mic != null) {
-					mic.addEventListener(StatusEvent.STATUS, micStatusEventHandler);				
+					if (mic.muted) {
+						// user has disallowed access to the mic
+						mic.addEventListener(StatusEvent.STATUS, micStatusEventHandler);
+						Security.showSettings();
+					} else {
+						// user has allowed access to the mic
+						mic.setLoopBack(true);
+					}
 				} else {
 					LogUtil.warn("Microphone is used by another application.");
 				}
@@ -51,6 +59,7 @@
 						LogUtil.warn("Access to microphone has been denied.");
 						break;
 					case "Microphone.Unmuted":
+						mic.setLoopBack(true);
 						LogUtil.debug("Access to the microphone has been allowed.");
 						break;
 					default:
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/NetworkStatsWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/NetworkStatsWindow.mxml
new file mode 100644
index 0000000000000000000000000000000000000000..0524067aee8c69d783a158300decdd748a158867
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/NetworkStatsWindow.mxml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  BigBlueButton open source conferencing system - http://www.bigbluebutton.org
+  
+  Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+  
+  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 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/>.
+
+  Author: Felipe Cecagno <felipe@mconf.org>
+ 
+  $Id: $
+-->
+
+<MDIWindow xmlns="flexlib.mdi.containers.*" 
+		xmlns:mx="http://www.adobe.com/2006/mxml" 
+		xmlns:mate="http://mate.asfusion.com/"
+		title="Network monitor" 
+		creationComplete="onCreationComplete()"
+		resizable="false"
+		showCloseButton="false"
+		implements="org.bigbluebutton.common.IBbbModuleWindow"
+		width="210" height="261" minHeight="0" minWidth="0"
+		resize="onResize()">
+
+	<mx:Script>
+		<![CDATA[
+
+			import com.asfusion.mate.events.Dispatcher;
+			
+			import flash.utils.Timer;
+
+			import org.bigbluebutton.common.events.CloseWindowEvent;
+			import org.bigbluebutton.common.events.OpenWindowEvent;
+			import org.bigbluebutton.common.LogUtil;
+			import org.bigbluebutton.main.model.NetworkStatsData;
+		
+			import mx.effects.Fade;
+			import mx.events.EffectEvent;
+			import mx.formatters.NumberFormatter;
+
+			private var _globalDispatcher:Dispatcher = new Dispatcher();
+			private var _updateTimer:Timer = new Timer(1000);
+			private var _numberFormatter:NumberFormatter = new NumberFormatter();
+		
+			private function onCreationComplete():void {
+				this.windowControls.maximizeRestoreBtn.visible = false;
+				this.windowControls.minimizeBtn.visible = false;
+				
+				this.x = parent.width - this.width;
+				this.y = parent.height - this.height;
+				
+				_numberFormatter.precision = 2;
+				_numberFormatter.useThousandsSeparator = true;
+
+				_updateTimer.addEventListener(TimerEvent.TIMER, timerHandler);
+				_updateTimer.start();
+			}
+			
+	        private function timerHandler(e:TimerEvent):void {
+				labelCurrentDownload.text = _numberFormatter.format(NetworkStatsData.getInstance().currentConsumedDownBW);
+			 	labelTotalDownload.text   = _numberFormatter.format(NetworkStatsData.getInstance().totalConsumedDownBW);
+			 	labelAvailableDownload.text   = _numberFormatter.format(NetworkStatsData.getInstance().measuredDownBW);
+			 	labelDownloadLatency.text   = String(NetworkStatsData.getInstance().measuredDownLatency);
+
+			 	labelCurrentUpload.text   = _numberFormatter.format(NetworkStatsData.getInstance().currentConsumedUpBW);
+			 	labelTotalUpload.text     = _numberFormatter.format(NetworkStatsData.getInstance().totalConsumedUpBW);
+			 	labelAvailableUpload.text   = _numberFormatter.format(NetworkStatsData.getInstance().measuredUpBW);
+			 	labelUploadLatency.text   = String(NetworkStatsData.getInstance().measuredUpLatency);
+	        }
+        			
+			public function getPrefferedPosition():String {
+				return MainCanvas.ABSOLUTE;
+			}
+			
+			private function onResize():void {
+				LogUtil.debug("width=" + width + " height=" + height);
+			}
+			
+			public function appear():void {
+				var fader:Fade = new Fade();
+				fader.alphaFrom = 0;
+				fader.alphaTo = 1;
+				fader.duration = 500;
+				fader.target = this;
+//				fader.addEventListener(EffectEvent.EFFECT_START, function(e:EffectEvent):void {
+//					var windowEvent:OpenWindowEvent = new OpenWindowEvent(OpenWindowEvent.OPEN_WINDOW_EVENT);
+//					windowEvent.window = e.currentTarget as IBbbModuleWindow;
+//					_globalDispatcher.dispatchEvent(windowEvent);
+//				});
+				fader.play();
+				var windowEvent:OpenWindowEvent = new OpenWindowEvent(OpenWindowEvent.OPEN_WINDOW_EVENT);
+				windowEvent.window = this;
+				_globalDispatcher.dispatchEvent(windowEvent);
+				this.windowManager.bringToFront(this);
+			}
+			
+			public function disappear():void {
+				var fader:Fade = new Fade();
+				fader.alphaFrom = 1;
+				fader.alphaTo = 0;
+				fader.duration = 500;
+				fader.target = this;
+				fader.addEventListener(EffectEvent.EFFECT_END, function(e:EffectEvent):void {
+					var windowEvent:CloseWindowEvent = new CloseWindowEvent(CloseWindowEvent.CLOSE_WINDOW_EVENT);
+					windowEvent.window = e.target as IBbbModuleWindow;
+					_globalDispatcher.dispatchEvent(windowEvent);
+				});
+				fader.play();
+			}
+		]]>
+	</mx:Script>
+	
+	
+	<mx:Panel width="100%" height="100%"
+	 paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10" headerHeight="10">
+		<mx:VBox verticalGap="0" width="100%" height="100%">
+			<mx:HBox backgroundColor="haloOrange" width="100%" horizontalAlign="center"><mx:Label fontWeight="bold" text="Upload"/></mx:HBox>
+			<mx:HBox horizontalGap="0"><mx:Label text="Total: "/><mx:Label id="labelTotalUpload" fontWeight="bold" text="-"/><mx:Label text="MB"/></mx:HBox>
+			<mx:HBox horizontalGap="0"><mx:Label text="Current: "/><mx:Label id="labelCurrentUpload" fontWeight="bold" text="-"/><mx:Label text="Kb/s"/></mx:HBox>
+			<mx:HBox horizontalGap="0"><mx:Label text="Available: "/><mx:Label id="labelAvailableUpload" fontWeight="bold" text="-"/><mx:Label text="Mb/s"/></mx:HBox>
+			<mx:HBox horizontalGap="0"><mx:Label text="Latency: "/><mx:Label id="labelUploadLatency" fontWeight="bold" text="-"/><mx:Label text="ms"/></mx:HBox>
+			<mx:HBox backgroundColor="haloOrange" width="100%" horizontalAlign="center"><mx:Label fontWeight="bold" text="Download"/></mx:HBox>
+			<mx:HBox horizontalGap="0"><mx:Label text="Total: "/><mx:Label id="labelTotalDownload" fontWeight="bold" text="-"/><mx:Label text="MB"/></mx:HBox>
+			<mx:HBox horizontalGap="0"><mx:Label text="Current: "/><mx:Label id="labelCurrentDownload" fontWeight="bold" text="-"/><mx:Label text="Kb/s"/></mx:HBox>
+			<mx:HBox horizontalGap="0"><mx:Label text="Available: "/><mx:Label id="labelAvailableDownload" fontWeight="bold" text="-"/><mx:Label text="Mb/s"/></mx:HBox>
+			<mx:HBox horizontalGap="0"><mx:Label text="Latency: "/><mx:Label id="labelDownloadLatency" fontWeight="bold" text="-"/><mx:Label text="ms"/></mx:HBox>
+		</mx:VBox>
+	</mx:Panel>
+
+</MDIWindow>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/views/VideoHolder.mxml b/bigbluebutton-client/src/org/bigbluebutton/main/views/VideoHolder.mxml
new file mode 100755
index 0000000000000000000000000000000000000000..23791e20676ce321ed65a4e90c9aa37be9007231
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/views/VideoHolder.mxml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">
+  <mx:Script>
+    <![CDATA[
+      import mx.core.UIComponent;
+      
+      import org.bigbluebutton.common.LogUtil;
+      import org.bigbluebutton.util.i18n.ResourceUtil;
+      private var hideWarningTimer:Timer = null;
+      
+      private function onCreationComplete():void {
+        this.addChild(_videoHolder);
+      }
+      
+      public function remove(video:Video):void {
+        _videoHolder.removeChild(video);
+      }
+      
+      public function add(video:Video):void {
+        _videoHolder.addChild(video);
+      }
+      
+      public function showWarning(resourceName:String, autoHide:Boolean=false, color:String="0xFF0000"):void {
+        const text:String = ResourceUtil.getInstance().getString(resourceName);
+        
+        if (hideWarningTimer != null) {
+          hideWarningTimer.stop();
+        }
+        
+        if (autoHide) {
+          hideWarningTimer = new Timer(3000, 1);
+          hideWarningTimer.addEventListener(TimerEvent.TIMER, hideWarning);
+          hideWarningTimer.start();
+        }
+        
+        // bring the label to front
+        setChildIndex(lblWarning, getChildren().length - 1);
+        lblWarning.text = text;
+        lblWarning.setStyle("color", color);
+        lblWarning.visible = true;
+        LogUtil.debug("Showing warning: " + text);
+      }
+      
+      private function hideWarning(e:TimerEvent):void {
+        lblWarning.visible = false;
+      }
+      
+    ]]>
+  </mx:Script>
+  
+  <mx:Fade id="dissolveOut" duration="1000" alphaFrom="1.0" alphaTo="0.0"/>
+  <mx:Fade id="dissolveIn" duration="1000" alphaFrom="0.0" alphaTo="1.0"/>
+  
+  <mx:UIComponent id="_videoHolder"/>
+  
+  <mx:Text id="lblWarning" width="100%" textAlign="center" fontSize="14" fontWeight="bold" 
+           y="{this.height - lblWarning.height - 30}" 
+           visible="true" selectable="false" hideEffect="{dissolveOut}" showEffect="{dissolveIn}"/>
+</mx:Canvas>
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/events/PlayStreamEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/events/PlayStreamEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..7efb875d86448ffa050a7e91d6bc51d169629def
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/events/PlayStreamEvent.as
@@ -0,0 +1,12 @@
+package org.bigbluebutton.modules.broadcast.events
+{
+  import flash.events.Event;
+  
+  public class PlayStreamEvent extends Event
+  {
+    public function PlayStreamEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
+    {
+      super(type, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/events/StreamsListLoadedEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/events/StreamsListLoadedEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..663f208fe5bb9ad7e039375142aa36a4968d9024
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/events/StreamsListLoadedEvent.as
@@ -0,0 +1,14 @@
+package org.bigbluebutton.modules.broadcast.events
+{
+  import flash.events.Event;
+  
+  public class StreamsListLoadedEvent extends Event
+  {
+    public static const STREAMS_LIST_LOADED:String = "broadcast streams list loaded event";
+    
+    public function StreamsListLoadedEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(type, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/managers/BroadcastManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/managers/BroadcastManager.as
new file mode 100755
index 0000000000000000000000000000000000000000..0e5e9739749f5632c59777fecf6ba5e526325563
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/managers/BroadcastManager.as
@@ -0,0 +1,149 @@
+package org.bigbluebutton.modules.broadcast.managers
+{
+	import com.asfusion.mate.events.Dispatcher;
+	
+	import flash.events.AsyncErrorEvent;
+	import flash.events.Event;
+	import flash.events.NetStatusEvent;
+	import flash.events.SecurityErrorEvent;
+	import flash.media.Video;
+	import flash.net.NetConnection;
+	import flash.net.NetStream;
+	
+	import mx.core.UIComponent;
+	
+	import org.bigbluebutton.common.LogUtil;
+	import org.bigbluebutton.common.events.OpenWindowEvent;
+	import org.bigbluebutton.core.BBB;
+	import org.bigbluebutton.core.managers.UserManager;
+	import org.bigbluebutton.main.events.BBBEvent;
+	import org.bigbluebutton.modules.broadcast.models.BroadcastOptions;
+	import org.bigbluebutton.modules.broadcast.models.Stream;
+	import org.bigbluebutton.modules.broadcast.models.Streams;
+	import org.bigbluebutton.modules.broadcast.services.BroadcastService;
+	import org.bigbluebutton.modules.broadcast.services.StreamsService;
+	import org.bigbluebutton.modules.broadcast.views.BroadcastWindow;
+	
+	public class BroadcastManager {	
+		private var broadcastWindow:BroadcastWindow;
+		private var dispatcher:Dispatcher;
+		private var broadcastService:BroadcastService = new BroadcastService();
+		private var streamService:StreamsService;
+		private var opt:BroadcastOptions;
+    
+		[Bindable]
+		public var streams:Streams = new Streams();	
+		private var curStream:Stream;
+		
+		public function BroadcastManager() {
+			streamService = new StreamsService(this);
+			LogUtil.debug("BroadcastManager Created");
+		}
+		
+		public function start():void {
+			LogUtil.debug("BroadcastManager Start");
+      opt = new BroadcastOptions();
+			dispatcher = new Dispatcher();
+      streamService.queryAvailableStreams(opt.streamsUri);
+		}
+		
+    public function handleStreamsListLoadedEvent():void {
+      if (broadcastWindow == null){
+        trace("*** BroadcastManager Opening BroadcastModule Window");
+
+        broadcastWindow = new BroadcastWindow();
+        broadcastWindow.options = opt;
+        broadcastWindow.streams = streams;
+        
+        broadcastWindow.broadcastManager = this;
+        
+        var e:OpenWindowEvent = new OpenWindowEvent(OpenWindowEvent.OPEN_WINDOW_EVENT);
+        e.window = broadcastWindow;
+        dispatcher.dispatchEvent(e);
+        
+      } else {
+        trace("***BroadcastManager Not Opening BroadcastModule Window");
+      }
+      
+ //     sendWhatIsTheCurrentStreamRequest();
+      
+      if (UserManager.getInstance().getConference().amIPresenter()) {
+        handleSwitchToPresenterMode();
+      } else {
+        handleSwitchToViewerMode();
+      }
+    }
+    
+		public function handleSwitchToPresenterMode():void {
+      if (broadcastWindow != null) {
+        broadcastWindow.becomePresenter();        
+      }
+		}
+		
+		public function handleSwitchToViewerMode():void {
+      if (broadcastWindow != null) {
+        broadcastWindow.becomeViewer();
+      }
+			
+		}
+		
+		public function playVideo(index:int):void {
+      trace("BroadcastManager::playVideo [" + streams.streamUrls[index] + "],[" + streams.streamIds[index] + "],[" + streams.streamNames[index] + "]"); 
+			broadcastService.playStream(streams.streamUrls[index], streams.streamIds[index], streams.streamNames[index]);
+		}
+				
+		public function stopVideo():void {
+      trace("BroadcastManager::stopVideo"); 
+			broadcastService.stopStream();
+		}
+		
+		public function sendWhatIsTheCurrentStreamRequest():void {
+			broadcastService.sendWhatIsTheCurrentStreamRequest();
+		}
+		
+		public function handleWhatIsTheCurrentStreamRequest(event:BBBEvent):void {
+			trace("BroadcastManager:: Received " + event.payload["messageID"] );
+			var isPresenter:Boolean = UserManager.getInstance().getConference().amIPresenter();
+			if (isPresenter && curStream != null) {
+				broadcastService.sendWhatIsTheCurrentStreamReply(event.payload["requestedBy"], curStream.getStreamId());
+			}
+		}
+		
+		public function handleWhatIsTheCurrentStreamReply(event:BBBEvent):void {
+			trace("BroadcastManager:: Received " + event.payload["messageID"] );
+			var amIRequester:Boolean = UserManager.getInstance().getConference().amIThisUser(event.payload["requestedBy"]);
+			if (amIRequester) {
+				var streamId:String = event.payload["streamID"];
+				var info:Object = streams.getStreamNameAndUrl(streamId);
+				if (info != null) {
+					playStream(info["url"], streamId, info["name"]);
+				}
+			}
+		}		
+		
+		private function playStream(url:String, streamId:String, streamName:String):void {
+      trace("BroadcastManager::playStream [" + url + "], [" + streamId + "], [" + streamName + "]");
+			curStream = new Stream(url, streamId, streamName);
+			broadcastWindow.curStream = curStream;
+			curStream.play(broadcastWindow);			
+		}
+		
+		public function handlePlayStreamRequest(event:BBBEvent):void {
+			trace("BroadcastManager Received " + event.payload["messageID"]);
+			playStream(event.payload["uri"], event.payload["streamID"], event.payload["streamName"]);
+		}
+		
+		public function handleStopStreamRequest(event:BBBEvent):void {
+			trace("BroadcastManager Received " + event.payload["messageID"]);
+			stopPlayingStream();
+		}
+		
+		public function stopPlayingStream():void {
+			if (curStream != null)	{
+				curStream.stop();
+				broadcastWindow.curStream = null;
+				curStream == null;
+			}	
+		}
+	}
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/maps/BroadcastEventMap.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/maps/BroadcastEventMap.mxml
new file mode 100755
index 0000000000000000000000000000000000000000..ac84f31993bebf7f6544eb2e2ffd22d5b45bcfe0
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/maps/BroadcastEventMap.mxml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  BigBlueButton open source conferencing system - http://www.bigbluebutton.org
+  
+  Copyright (c) 2010 BigBlueButton Inc. and by respective authors (see below).
+  
+  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 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/>.
+ 
+  $Id: $
+-->
+
+<EventMap xmlns="http://mate.asfusion.com/"
+	xmlns:mx="http://www.adobe.com/2006/mxml">
+	<mx:Script>
+		<![CDATA[
+      import com.asfusion.mate.events.Dispatcher;
+      
+      import mx.events.FlexEvent;
+      
+      import org.bigbluebutton.main.events.MadePresenterEvent;
+      import org.bigbluebutton.modules.broadcast.events.StreamsListLoadedEvent;
+      import org.bigbluebutton.modules.broadcast.managers.BroadcastManager;
+      import org.bigbluebutton.modules.broadcast.services.BroadcastService;
+      import org.bigbluebutton.modules.broadcast.services.MessageReceiver;
+      import org.bigbluebutton.modules.broadcast.services.MessageSender;
+			
+		]]>
+	</mx:Script>
+	
+	<EventHandlers type="{FlexEvent.PREINITIALIZE}">
+		<ObjectBuilder generator="{BroadcastManager}" cache="global"/>
+	</EventHandlers>
+	
+	<EventHandlers type="BroadcastModuleStartEvent">
+		<MethodInvoker generator="{BroadcastManager}" method="start" />
+	</EventHandlers>	
+
+	<EventHandlers type="{MadePresenterEvent.SWITCH_TO_PRESENTER_MODE}">
+		<MethodInvoker generator="{BroadcastManager}" method="handleSwitchToPresenterMode" />
+	</EventHandlers>
+	
+	<EventHandlers type="{MadePresenterEvent.SWITCH_TO_VIEWER_MODE}">
+		<MethodInvoker generator="{BroadcastManager}" method="handleSwitchToViewerMode" />
+	</EventHandlers>
+	
+  <EventHandlers type="{StreamsListLoadedEvent.STREAMS_LIST_LOADED}">
+    <MethodInvoker generator="{BroadcastManager}" method="handleStreamsListLoadedEvent" />
+  </EventHandlers>
+  
+	<EventHandlers type="BroadcastPlayStreamCommand">
+		<MethodInvoker generator="{BroadcastManager}" method="handlePlayStreamRequest" arguments="{event}"/>
+	</EventHandlers>
+
+	<EventHandlers type="BroadcastStopStreamCommand">
+		<MethodInvoker generator="{BroadcastManager}" method="handleStopStreamRequest" arguments="{event}"/>
+	</EventHandlers>
+	
+	<EventHandlers type="BroadcastWhatIsTheCurrentStreamRequest">
+		<MethodInvoker generator="{BroadcastManager}" method="handleWhatIsTheCurrentStreamRequest" arguments="{event}"/>
+	</EventHandlers>
+	
+	<EventHandlers type="BroadcastWhatIsTheCurrentStreamReply">
+		<MethodInvoker generator="{BroadcastManager}" method="handleWhatIsTheCurrentStreamReply" arguments="{event}"/>
+	</EventHandlers>
+
+<!--
+  <Injectors target="{BroadcastService}">
+    <ObjectBuilder generator="{MessageSender}" cache="global"/>
+    <PropertyInjector targetKey="receiver" source="{MessageReceiver}"/>
+    <PropertyInjector targetKey="sender" source="{MessageSender}"/>
+  </Injectors>
+	
+  <Injectors target="{MessageReceiver}">
+    <PropertyInjector targetKey="dispatcher" source="{scope.dispatcher}"/>
+  </Injectors>
+-->
+  
+</EventMap>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/models/BroadcastModel.as b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/models/BroadcastModel.as
new file mode 100755
index 0000000000000000000000000000000000000000..32ea3fca2ab427a0267c0c322a211dbaa3c19b62
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/models/BroadcastModel.as
@@ -0,0 +1,9 @@
+package org.bigbluebutton.modules.broadcast.models
+{
+  public class BroadcastModel
+  {
+    public function BroadcastModel()
+    {
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/models/BroadcastOptions.as b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/models/BroadcastOptions.as
new file mode 100755
index 0000000000000000000000000000000000000000..c70b10995ef588a865fc78d49c29bd9bc3e79e32
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/models/BroadcastOptions.as
@@ -0,0 +1,37 @@
+package org.bigbluebutton.modules.broadcast.models
+{
+	import org.bigbluebutton.core.BBB;
+
+	public class BroadcastOptions {
+		[Bindable]
+		public var streamsUri:String;
+				
+		[Bindable]
+		public var position:String = "absolute";
+		
+    public var showWindowControls:Boolean = false;
+    public var showStreams:Boolean = true;
+    public var autoPlay:Boolean = false;
+    	
+		public function BroadcastOptions() {
+			var cxml:XML = 	BBB.getConfigForModule("BroadcastModule");
+			if (cxml != null) {
+				if (cxml.@streamsUri != undefined) {
+					streamsUri = cxml.@streamsUri.toString();
+				}
+        if (cxml.@showWindowControls != undefined) {
+          showWindowControls = (cxml.@showWindowControls.toString().toUpperCase() == "TRUE") ? true : false;
+        }
+        if (cxml.@showStreams != undefined) {
+          showStreams = (cxml.@showStreams.toString().toUpperCase() == "TRUE") ? true : false;
+        }
+        if (cxml.@autoPlay != undefined) {
+          autoPlay = (cxml.@autoPlay.toString().toUpperCase() == "TRUE") ? true : false;
+        }
+				if (cxml.@position != undefined) {
+					position = cxml.@position.toString();
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/models/Stream.as b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/models/Stream.as
new file mode 100755
index 0000000000000000000000000000000000000000..bf82cf3e54d6bfba49ea65bc5741ea9f8aa00444
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/models/Stream.as
@@ -0,0 +1,230 @@
+package org.bigbluebutton.modules.broadcast.models
+{
+	import flash.events.AsyncErrorEvent;
+	import flash.events.NetStatusEvent;
+	import flash.events.SecurityErrorEvent;
+	import flash.media.Video;
+	import flash.net.NetConnection;
+	import flash.net.NetStream;
+	
+	import mx.core.UIComponent;
+	
+	import org.bigbluebutton.common.LogUtil;
+	import org.bigbluebutton.modules.broadcast.views.BroadcastWindow;
+
+	public class Stream {
+		private var uri:String;
+		private var streamId:String;
+		private var streamName:String;
+		private var window:BroadcastWindow;
+		private var ns:NetStream;
+		private var nc:NetConnection;
+		private var video:Video;
+		private var videoWidth:int;
+		private var videoHeight:int;
+		private var videoHolder:UIComponent;
+    
+		[Bindable]
+		public var width:int = 320;
+		[Bindable]
+		public var height:int = 240;
+		
+		public function Stream(uri:String, streamId:String, streamName:String) {
+      videoHolder = new UIComponent();
+			this.uri = uri;
+			this.streamId = streamId;
+			this.streamName = streamName;
+		}
+
+		public function play(w:BroadcastWindow):void {
+			window = w;
+			connect();
+		}
+		
+		public function getStreamId():String {
+			return streamId;
+		}
+		
+		private function displayVideo():void {
+			video = new Video();
+			ns = new NetStream(nc);
+			ns.client = this;
+			ns.bufferTime = 0;
+			ns.receiveVideo(true);
+			ns.receiveAudio(true);
+			ns.addEventListener(NetStatusEvent.NET_STATUS, netstreamStatus);
+			ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, nsAsyncErrorHandler);
+			video.attachNetStream(ns);
+      video.x = videoHolder.x;
+      video.y = videoHolder.y;
+      video.width = videoHolder.width;
+      video.height = videoHolder.height;
+
+      
+			ns.play(streamId);				
+		}		
+				
+		private function netstreamStatus(evt:NetStatusEvent):void {
+			switch(evt.info.code) {			
+				case "NetStream.Play.StreamNotFound":
+					LogUtil.debug("NetStream.Play.StreamNotFound");
+					break;			
+				case "NetStream.Play.Failed":
+					LogUtil.debug("NetStream.Play.Failed");
+					break;
+				case "NetStream.Play.Start":	
+					LogUtil.debug("NetStream.Play.Start");
+					break;
+				case "NetStream.Play.Stop":			
+					LogUtil.debug("NetStream.Play.Stop");
+					break;
+				case "NetStream.Buffer.Full":
+					LogUtil.debug("NetStream.Buffer.Full");
+					break;
+				default:
+			}			 
+		} 
+		
+		private function nsAsyncErrorHandler(event:AsyncErrorEvent):void {
+			LogUtil.debug("nsAsyncErrorHandler: " + event);
+		}
+		
+		private function connect():void {
+			LogUtil.debug("Connecting " + uri);
+			nc = new NetConnection();
+			nc.connect(uri);
+			nc.client = this;
+			nc.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
+			nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
+		}
+		
+		private function netStatus(evt:NetStatusEvent ):void {		 			
+			switch(evt.info.code) {				
+				case "NetConnection.Connect.Success":
+					LogUtil.debug("Successfully connected to broadcast application.");
+					displayVideo();
+					break;				
+				case "NetConnection.Connect.Failed":
+					LogUtil.debug("Failed to connect to broadcast application.");
+					break;				
+				case "NetConnection.Connect.Closed":
+					trace("Connection to broadcast application has closed.");
+					break;				
+				case "NetConnection.Connect.Rejected":
+					LogUtil.debug("Connection to broadcast application was rejected.");
+					break;					
+				default:	
+					LogUtil.debug("Connection to broadcast application failed. " + evt.info.code);
+			}			
+		}
+		
+		private function securityErrorHandler(event:SecurityErrorEvent):void {
+			LogUtil.debug("securityErrorHandler: " + event);
+		}
+		
+		public function onBWCheck(... rest):Number { 
+			return 0; 
+		} 
+		
+		public function onBWDone(... rest):void { 
+			var p_bw:Number; 
+			if (rest.length > 0) p_bw = rest[0]; 
+			// your application should do something here 
+			// when the bandwidth check is complete 
+			LogUtil.debug("bandwidth = " + p_bw + " Kbps."); 
+		}
+		
+		public function stop():void {
+      window.videoHolderBox.removeChild(videoHolder);
+      videoHolder.removeChild(video);
+      ns.close();
+      nc.close();      
+      video = null;
+		}
+		
+		public function onCuePoint(infoObject:Object):void {
+			LogUtil.debug("onCuePoint");
+		}
+		
+		public function onMetaData(info:Object):void {
+			LogUtil.debug("****metadata: width=" + info.width + " height=" + info.height);
+      trace("****metadata: width=" + info.width + " height=" + info.height);
+			videoWidth = info.width;
+			videoHeight = info.height;
+      
+      determineHowToDisplayVideo();
+		}
+		
+    public function onResize():void {
+      if (video != null) {
+        determineHowToDisplayVideo();        
+      }
+    }
+    
+		public function onPlayStatus(infoObject:Object):void {
+			LogUtil.debug("onPlayStatus");
+		}		
+		
+    private function centerToWindow():void{
+      videoHolder.width = video.width = videoWidth;
+      videoHolder.height = video.height = videoHeight;
+      videoHolder.x = video.x = (window.width - video.width) / 2;
+      videoHolder.y = video.y = (window.height - video.height) / 2;
+      
+      videoHolder.addChild(video);
+      window.videoHolderBox.addChild(videoHolder);
+    }
+    
+    private function fitVideoToWindow():void {
+      if (window.width < window.height) {
+        fitToWidthAndAdjustHeightToMaintainAspectRatio();				
+      } else {
+        fitToHeightAndAdjustWidthToMaintainAspectRatio();
+      }				
+    }
+       
+    private function videoIsSmallerThanWindow():Boolean {
+      return (videoHeight < window.height) && (videoWidth < window.width);
+    }
+    
+    private const VIDEO_WIDTH_PADDING:int = 7;
+    private const VIDEO_HEIGHT_PADDING:int = 65;
+    
+    private function fitToWidthAndAdjustHeightToMaintainAspectRatio():void {
+      videoHolder.width = video.width = window.width - VIDEO_WIDTH_PADDING;
+      // Maintain aspect-ratio
+      videoHolder.height = video.height = (videoHeight * video.width) / videoWidth;
+      videoHolder.x = video.x = 0;
+      videoHolder.y = video.y = 0;
+      
+      videoHolder.addChild(video);
+      window.videoHolderBox.addChild(videoHolder);
+    }
+    
+    private function fitToHeightAndAdjustWidthToMaintainAspectRatio():void {
+      videoHolder.height = video.height = window.height - VIDEO_HEIGHT_PADDING;
+      // Maintain aspect-ratio
+      videoHolder.width = video.width = (videoWidth * video.height) / videoHeight;
+      
+      if (videoHolder.width > window.width - VIDEO_WIDTH_PADDING) {
+        videoHolder.width = video.width = window.width - VIDEO_WIDTH_PADDING;
+        videoHolder.height = video.height = (videoHeight * video.width) / videoWidth;
+      }
+      
+      videoHolder.x = video.x = (window.width - VIDEO_WIDTH_PADDING - video.width) / 2;
+      videoHolder.y = video.y = (window.height - VIDEO_WIDTH_PADDING - video.height) / 2;	
+      
+      videoHolder.addChild(video);
+      window.videoHolderBox.addChild(videoHolder);
+    }
+       
+    private function determineHowToDisplayVideo():void {
+      if (videoIsSmallerThanWindow()) {
+        centerToWindow();
+      } else {
+        fitVideoToWindow();
+      }
+    }
+    
+	}
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/models/Streams.as b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/models/Streams.as
new file mode 100755
index 0000000000000000000000000000000000000000..29a72876643ecc02429307a93eb68f7c66a2c66e
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/models/Streams.as
@@ -0,0 +1,35 @@
+package org.bigbluebutton.modules.broadcast.models
+{
+	[Bindable]
+	public class Streams {		
+		public var streamNames:Array = new Array();
+		public var streamUrls:Array = new Array();
+		public var streamIds:Array = new Array();
+		
+		
+		public function getStreamNameAndUrl(streamId:String):Object {
+			var streamIndex:int = 0;
+			for (var i:int = 0; i < streamIds.length; i++) {
+				if (streamId == streamIds[i]) {
+					var info:Object = new Object();
+					info["name"] = streamNames[i];
+					info["url"] = streamUrls[i];
+					return info;
+				}
+			}
+			
+			return null;
+		} 
+		
+		public function getStreamIndex(streamId:String):Number {
+			var streamIndex:int = 0;
+			for (var i:int = 0; i < streamIds.length; i++) {
+				if (streamId == streamIds[i]) {
+					return i;
+				}
+			}
+			
+			return 0;
+		}
+	}
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/services/BroadcastService.as b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/services/BroadcastService.as
new file mode 100755
index 0000000000000000000000000000000000000000..7e4751253a715470a687e6236a2c5bc8b7f189f6
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/services/BroadcastService.as
@@ -0,0 +1,55 @@
+package org.bigbluebutton.modules.broadcast.services
+{
+	import com.asfusion.mate.events.Dispatcher;
+	
+	import org.bigbluebutton.core.BBB;
+	import org.bigbluebutton.core.managers.UserManager;
+	import org.bigbluebutton.main.events.BBBEvent;
+
+	public class BroadcastService {	
+    private var sender:MessageSender;
+    private var receiver:MessageReceiver;
+    
+    public function BroadcastService() {
+      sender = new MessageSender();
+      receiver = new MessageReceiver();
+    }
+    
+		public function playStream(uri:String, streamID:String, streamName:String):void {
+      trace("BroadcastService::playStream"); 
+      if (sender == null) {
+        trace("SENDER is NULL!!!!");
+      }
+//      sender.playStream(uri, streamID, streamName);
+      
+      var event:BBBEvent = new BBBEvent("BroadcastPlayStreamCommand");
+      event.payload["messageID"] = "BroadcastPlayStreamCommand";
+      event.payload["uri"] = uri;
+      event.payload["streamID"] = streamID;
+      event.payload["streamName"] = streamName;		
+      
+      var dispatcher:Dispatcher = new Dispatcher();
+      dispatcher.dispatchEvent(event);
+      
+		}
+		
+		public function stopStream():void {
+      trace("BroadcastService::stopStream"); 
+//			sender.stopStream();
+      
+      var event:BBBEvent = new BBBEvent("BroadcastStopStreamCommand");
+      event.payload["messageID"] = "BroadcastStopStreamCommand";    
+      
+      var dispatcher:Dispatcher = new Dispatcher();
+      dispatcher.dispatchEvent(event);     
+		}
+		
+		public function sendWhatIsTheCurrentStreamRequest():void {
+			sender.sendWhatIsTheCurrentStreamRequest();
+		}
+		
+		public function sendWhatIsTheCurrentStreamReply(requestedByUserID:Number, streamID:String):void {
+			sender.sendWhatIsTheCurrentStreamReply(requestedByUserID, streamID);
+		}
+	}
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/services/MessageReceiver.as b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/services/MessageReceiver.as
new file mode 100755
index 0000000000000000000000000000000000000000..31352ccebd696bd1db4626e5376afa6df7e0b8f0
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/services/MessageReceiver.as
@@ -0,0 +1,72 @@
+package org.bigbluebutton.modules.broadcast.services
+{
+  import com.asfusion.mate.events.Dispatcher;
+  
+  import org.bigbluebutton.core.BBB;
+  import org.bigbluebutton.main.events.BBBEvent;
+  import org.bigbluebutton.main.model.users.IMessageListener;
+
+  public class MessageReceiver implements IMessageListener
+  {
+    private var dispatcher:Dispatcher;
+    
+    public function MessageReceiver() {
+      dispatcher = new Dispatcher();
+      BBB.initConnectionManager().addMessageListener(this);
+    }
+    
+    public function onMessage(messageName:String, message:Object):void {
+      trace("Broadcast: received message " + messageName);
+      
+      switch (messageName) {
+        case "BroadcastPlayStreamCommand":
+            handleBroadcastPlayStreamCommand(message);
+          break;
+        case "BroadcastStopStreamCommand":
+            handleBroadcastStopStreamCommand(message);
+          break;
+        case "BroadcastWhatIsTheCurrentStreamRequest":
+            handleBroadcastWhatIsTheCurrentStreamRequest(message);
+          break;    
+        case "BroadcastWhatIsTheCurrentStreamReply":
+          handleBroadcastWhatIsTheCurrentStreamReply(message);
+          break;   				
+        default:
+          //          LogUtil.warn("Cannot handle message [" + messageName + "]");
+      }
+    }
+    
+    private function handleBroadcastPlayStreamCommand(message:Object):void {
+      var event:BBBEvent = new BBBEvent("BroadcastPlayStreamCommand");
+      event.payload["messageID"] = "BroadcastPlayStreamCommand";
+      event.payload["uri"] = message.uri;
+      event.payload["streamID"] = message.streamID;
+      event.payload["streamName"] = message.streamName;		
+      
+      dispatcher.dispatchEvent(event);
+    }
+    
+    private function handleBroadcastStopStreamCommand(messsage:Object):void {
+      var event:BBBEvent = new BBBEvent("BroadcastStopStreamCommand");
+      event.payload["messageID"] = "BroadcastStopStreamCommand";      
+      dispatcher.dispatchEvent(event);      
+    }
+    
+    private function handleBroadcastWhatIsTheCurrentStreamRequest(message:Object):void {
+      var event:BBBEvent = new BBBEvent("BroadcastWhatIsTheCurrentStreamRequest");
+      event.payload["messageID"] = "BroadcastWhatIsTheCurrentStreamRequest";   
+      event.payload["requestedBy"] = message.requestedByUserID;
+
+      dispatcher.dispatchEvent(event);      
+    }
+    
+    private function handleBroadcastWhatIsTheCurrentStreamReply(message:Object):void {
+      var event:BBBEvent = new BBBEvent("BroadcastWhatIsTheCurrentStreamReply");
+      event.payload["messageID"] = "BroadcastWhatIsTheCurrentStreamReply";   
+      event.payload["requestedBy"] = message.requestedByUserID;
+      event.payload["streamID"] = message.streamID;
+      
+      dispatcher.dispatchEvent(event);
+    }
+  }        
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/services/MessageSender.as b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/services/MessageSender.as
new file mode 100755
index 0000000000000000000000000000000000000000..42dca4bc04ab7e6727765c2663e4d96ec2f29d66
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/services/MessageSender.as
@@ -0,0 +1,79 @@
+package org.bigbluebutton.modules.broadcast.services
+{
+  import org.bigbluebutton.common.LogUtil;
+  import org.bigbluebutton.core.BBB;
+  import org.bigbluebutton.core.managers.ConnectionManager;
+  import org.bigbluebutton.core.managers.UserManager;
+
+  public class MessageSender {
+    public function playStream(uri:String, streamId:String, streamName:String):void {
+      var message:Object = new Object();
+      message["messageID"] = "BroadcastPlayStreamCommand";
+      message["uri"] = uri;
+      message["streamID"] = streamId;
+      message["streamName"] = streamName;				
+      
+      var _nc:ConnectionManager = BBB.initConnectionManager();
+      _nc.sendMessage("bigbluebutton.sendMessage", 
+        function(result:String):void { // On successful result
+          trace(result); 
+        },	                   
+        function(status:String):void { // status - On error occurred
+          LogUtil.error(status); 
+        },
+        message
+      );
+    }
+    
+    public function stopStream():void {
+      var message:Object = new Object();
+      message["messageID"] = "BroadcastStopStreamCommand";			
+        
+      var _nc:ConnectionManager = BBB.initConnectionManager();
+      _nc.sendMessage("bigbluebutton.sendMessage", 
+        function(result:String):void { // On successful result
+          trace(result); 
+        },	                   
+        function(status:String):void { // status - On error occurred
+          LogUtil.error(status); 
+        },
+        message
+      );
+    }
+       
+    public function sendWhatIsTheCurrentStreamRequest():void {
+      var message:Object = new Object();
+      message["messageID"] = "BroadcastWhatIsTheCurrentStreamRequest";	
+      message["requestedBy"] = UserManager.getInstance().getConference().getMyUserId();
+        
+      var _nc:ConnectionManager = BBB.initConnectionManager();
+      _nc.sendMessage("bigbluebutton.sendMessage", 
+        function(result:String):void { // On successful result
+          trace(result); 
+        },	                   
+        function(status:String):void { // status - On error occurred
+          LogUtil.error(status); 
+        },
+        message
+      );
+    }
+    
+    public function sendWhatIsTheCurrentStreamReply(requestedByUserID:Number, streamID:String):void {
+      var message:Object = new Object();
+      message["messageID"] = "BroadcastWhatIsTheCurrentStreamReply";	
+      message["requestedBy"] = requestedByUserID;
+      message["streamID"] = streamID;
+
+      var _nc:ConnectionManager = BBB.initConnectionManager();
+      _nc.sendMessage("bigbluebutton.sendMessage", 
+        function(result:String):void { // On successful result
+          trace(result); 
+        },	                   
+        function(status:String):void { // status - On error occurred
+          LogUtil.error(status); 
+        },
+        message
+      );        
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/services/StreamsService.as b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/services/StreamsService.as
new file mode 100755
index 0000000000000000000000000000000000000000..ee6eb57fb548eaf90b0d9581fb20ab251413c98e
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/services/StreamsService.as
@@ -0,0 +1,55 @@
+package org.bigbluebutton.modules.broadcast.services
+{
+	import com.asfusion.mate.events.Dispatcher;
+	
+	import flash.events.Event;
+	import flash.net.URLLoader;
+	import flash.net.URLRequest;
+	
+	import org.bigbluebutton.common.LogUtil;
+	import org.bigbluebutton.modules.broadcast.events.StreamsListLoadedEvent;
+	import org.bigbluebutton.modules.broadcast.managers.BroadcastManager;
+	import org.bigbluebutton.modules.broadcast.models.Streams;
+	
+	public class StreamsService {
+		private var streamsXml:XML;
+		
+		private var broadcastManager:BroadcastManager;
+		
+		public function StreamsService(broadcastManager:BroadcastManager) {
+			this.broadcastManager = broadcastManager;	
+		}
+		
+		public function queryAvailableStreams(uri:String):void {
+      trace("StreamsService::queryAvailableStreams");
+			var urlLoader:URLLoader = new URLLoader();
+			urlLoader.addEventListener(Event.COMPLETE, handleComplete);
+			var date:Date = new Date();
+			
+			urlLoader.load(new URLRequest(uri + "?a=" + date.time));			
+		}		
+		
+		private function handleComplete(e:Event):void {
+			streamsXml = new XML(e.target.data);
+			LogUtil.debug(streamsXml);
+      trace("StreamsService::handleComplete\n" + streamsXml.toXMLString());
+			var mn:XMLList = streamsXml.stream..@name;
+			
+			for each (var n:XML in mn) {
+				LogUtil.debug(n);
+			}
+			var item:XML;
+			var list:XMLList = streamsXml.children();
+
+			for each(item in list) {
+				LogUtil.debug(item.@url + " " + item.@name + " " + item.@id);
+				broadcastManager.streams.streamNames.push(item.@name);
+				broadcastManager.streams.streamUrls.push(item.@url);
+				broadcastManager.streams.streamIds.push(item.@id);
+			}			
+      
+      var dispatcher:Dispatcher = new Dispatcher();
+      dispatcher.dispatchEvent(new StreamsListLoadedEvent(StreamsListLoadedEvent.STREAMS_LIST_LOADED));
+		}
+	}
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/views/BroadcastWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/views/BroadcastWindow.mxml
new file mode 100755
index 0000000000000000000000000000000000000000..3a0418bd938726eb98c7514e85c3875794ed6e20
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/broadcast/views/BroadcastWindow.mxml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<bcast:MDIWindow xmlns:mx="http://www.adobe.com/2006/mxml" 
+					  xmlns:bcast="flexlib.mdi.containers.*" 
+					  implements="org.bigbluebutton.common.IBbbModuleWindow" 
+            styleNameFocus="broadcastStyleFocus"
+            styleNameNoFocus="broadcastStyleNoFocus"
+            creationComplete="onCreationComplete()"
+            visible="false"
+					  xmlns:mate="http://mate.asfusion.com/" showCloseButton="false"
+					  layout="absolute" title="Broadcast" resize="onResize()" resizeEndMDIWindow="onResize()">
+
+	<mx:Script>
+		<![CDATA[
+			import flexlib.mdi.events.MDIWindowEvent;			
+			import mx.core.UIComponent;
+			import mx.events.ResizeEvent;
+			import mx.skins.Border;			
+			import org.bigbluebutton.common.LogUtil;
+			import org.bigbluebutton.modules.broadcast.managers.BroadcastManager;
+			import org.bigbluebutton.modules.broadcast.models.BroadcastOptions;
+			import org.bigbluebutton.modules.broadcast.models.Stream;
+			import org.bigbluebutton.modules.broadcast.models.Streams;			     
+			public var broadcastManager:BroadcastManager;
+			public var curStream:Stream;
+					
+			public var options:BroadcastOptions;
+			private var createComplete:Boolean = false;
+      
+			[Bindable]
+			public var streams:Streams;
+			
+      private var autoPlayTimer:Timer
+      
+			private function onCreationComplete():void {
+        options = new BroadcastOptions();
+        streamsList.visible = options.showStreams;
+        this.showControls = options.showWindowControls;
+              
+        createComplete = true;
+        
+        autoPlayTimer = new Timer(3000,1);
+        autoPlayTimer.addEventListener(TimerEvent.TIMER, onTimerComplete);
+        autoPlayTimer.start();
+      }
+			
+      private function onTimerComplete(event:TimerEvent = null):void {
+        if (options.autoPlay && visible) {
+          // Don't start playing the video if the video is hidden.
+          broadcastManager.playVideo(0);
+        }        
+      }
+      
+			public function becomePresenter():void {
+        if (options.showStreams) {
+          videoStreamList.visible = true;
+        }
+				
+				if (curStream != null) {
+					playBtn.selected = true;
+					playBtn.label = "Stop";
+					streamsComboBox.selectedIndex = streams.getStreamIndex(curStream.getStreamId());
+				} else {
+					playBtn.selected = false;
+					playBtn.label = "Play";				
+					streamsComboBox.selectedIndex = 0;
+				}
+			}
+			
+			public function becomeViewer():void{
+        if (options.showStreams) {
+          videoStreamList.visible = false;
+        }
+				
+				if (curStream != null) {
+					playBtn.selected = true;
+					playBtn.label = "Stop";
+					streamsComboBox.selectedIndex = streams.getStreamIndex(curStream.getStreamId());
+				} else {
+					playBtn.selected = false;
+					playBtn.label = "Play";				
+					streamsComboBox.selectedIndex = 0;
+				}
+			}
+			
+			private function playStopVideo():void {
+				if (playBtn.selected) {
+					broadcastManager.playVideo(streamsComboBox.selectedIndex);	
+					playBtn.label = "Stop";
+				} else {
+					playBtn.label = "Play";
+					stopVideo();
+				}
+			}
+								
+			private function stopVideo():void {
+				broadcastManager.stopVideo();
+			}
+			
+			public function getPrefferedPosition():String {	
+				return options.position;
+			}
+            
+      private function onResize():void {
+        if (curStream != null && createComplete) {
+          curStream.onResize();         
+        }
+      }
+												
+		]]>
+	</mx:Script>
+		<mx:HBox id="videoHolderBox" width="100%" height="100%" />		
+		<mx:ControlBar id="streamsList" visible="false" width="100%" height="30" paddingTop="0" borderStyle="outset" horizontalAlign="center">
+			<mx:HBox x="1" y="1" id="videoStreamList" visible="false" width="100%" height="30" horizontalAlign="center">
+				<mx:ComboBox id="streamsComboBox" width="85%" dataProvider="{streams.streamNames}" />
+				<mx:Button id="playBtn" label="Play" width="15% " click="playStopVideo()" toggle="true"/>				
+			</mx:HBox>
+		</mx:ControlBar>
+</bcast:MDIWindow>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/AdvancedList.as b/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/AdvancedList.as
new file mode 100755
index 0000000000000000000000000000000000000000..ef19b3c416dae5c6ced9eb87edd040c95a63799b
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/AdvancedList.as
@@ -0,0 +1,19 @@
+package org.bigbluebutton.modules.chat.views
+{
+  import mx.controls.List;
+  
+  public class AdvancedList extends List
+  {
+    public function AdvancedList()
+    {
+      super();
+    }
+    
+    override protected function measure():void
+    {
+      super.measure();
+      //sovled on forum by Flex HarUI
+      measuredHeight = measureHeightOfItems() + viewMetrics.top + viewMetrics.bottom;
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatBox.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatBox.mxml
index 970872e16754f523d907cfa84463906569dff1af..dcbbf4d5130d1596938adc6d7d84b8ebf863951a 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatBox.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatBox.mxml
@@ -55,7 +55,7 @@
 	<mate:Listener type="{ShortcutEvent.GOREAD_MESSAGE}" method="goToLatestReadMessage" />
   <mate:Listener type="{PrivateChatMessageEvent.PRIVATE_CHAT_MESSAGE_EVENT}" method="handlePrivateChatMessageEvent"/>
   <mate:Listener type="{PublicChatMessageEvent.PUBLIC_CHAT_MESSAGE_EVENT}" method="handlePublicChatMessageEvent"/>
-  <mate:Listener type="{ParticipantJoinEvent.PARTICIPANT_JOINED_EVENT}" method="handleParticipantJoinEvent"/>
+  <mate:Listener type="{UserLeftEvent.LEFT}" method="handleUserLeftEvent"/>
   
 	<mx:Script>
 		<![CDATA[
@@ -69,8 +69,9 @@
       
       import org.bigbluebutton.common.LogUtil;
       import org.bigbluebutton.core.UsersUtil;
-      import org.bigbluebutton.main.events.ParticipantJoinEvent;
       import org.bigbluebutton.main.events.ShortcutEvent;
+      import org.bigbluebutton.main.events.UserJoinedEvent;
+      import org.bigbluebutton.main.events.UserLeftEvent;
       import org.bigbluebutton.modules.chat.ChatConstants;
       import org.bigbluebutton.modules.chat.ChatUtil;
       import org.bigbluebutton.modules.chat.events.ChatOptionsEvent;
@@ -158,10 +159,7 @@
 				
         // Listen for the ENTER key to send the message.
         txtMsgArea.addEventListener(KeyboardEvent.KEY_UP, handleTextAreaKeyUpEvent);
-        
-        // Put the cursor on the txt message area when this chat box is in focus
-        this.addEventListener(FocusEvent.FOCUS_IN, handleFocusInEvent);
-        
+                
 				Accessibility.updateProperties();
         focusToTextMessageArea();
         
@@ -198,9 +196,9 @@
         }
       }
       
-      private function handleParticipantJoinEvent(event:ParticipantJoinEvent):void {
+      private function handleUserLeftEvent(event:UserLeftEvent):void {
         // Handle user leaving so that the user won't be talking to someone not there.
-        if (!publicChat && !event.join && event.userID == chatWithUserID) {
+        if (!publicChat && event.userID == chatWithUserID) {
           displayUserHasLeftMessage();
           txtMsgArea.enabled = false;
           scrollToEndOfMessage();
@@ -223,11 +221,7 @@
         
         chatMessages.newChatMessage(msg);
       }
-      
-      private function handleFocusInEvent(event:FocusEvent):void {
-        focusToTextMessageArea();
-      }
-      
+          
       public function focusToTextMessageArea():void {
         txtMsgArea.setFocus();
         txtMsgArea.drawFocus(true);
@@ -267,11 +261,11 @@
 			 * doing as I don't know why it works, but it does. (ralam Nov 3, 2010)
 			 */
 			private function scrollToBottom():void {
-//				chatMessagesList.invalidateSize();
-//				chatMessagesList.invalidateDisplayList();
-				chatMessagesList.scrollToIndex(chatMessages.numMessages());
-//				chatMessagesList.validateDisplayList();
-//				chatMessagesList.validateNow();		
+				chatMessagesList.invalidateSize();
+				chatMessagesList.invalidateDisplayList();
+				chatMessagesList.validateDisplayList();
+				chatMessagesList.validateNow();		
+        chatMessagesList.scrollToIndex(chatMessages.numMessages());
 			}
 			
 			private function onScrollTimer(event:TimerEvent):void {
@@ -480,7 +474,7 @@
         cm.fromTime = now.valueOf();
         cm.fromTimezoneOffset = now.getTimezoneOffset();
         
-        cm.message = ChatUtil.cleanup(message);
+        cm.message = ChatUtil.parseURLs(ChatUtil.cleanup(message));
         
         publicEvent.chatMessage = cm;
         globalDispatcher.dispatchEvent(publicEvent);
@@ -534,17 +528,18 @@
 		
 	</mx:Script>
 
-  <mx:HBox width="100%" height="{chatListHeight}">
-    <mx:List width="100%" height="{chatListHeight}" id="chatMessagesList" selectable="false" variableRowHeight="true"
-             itemRenderer="org.bigbluebutton.modules.chat.views.ChatMessageRenderer"
+  <mx:HBox width="100%" height="{chatListHeight}" verticalScrollPolicy="off">
+    <chat:AdvancedList width="100%" height="{chatListHeight}" id="chatMessagesList" selectable="true" variableRowHeight="true" alternatingItemColors="[#EFEFEF, #FEFEFE]"
+             itemRenderer="org.bigbluebutton.modules.chat.views.ChatMessageRenderer" verticalScrollPolicy="auto" wordWrap="true"
              dataProvider="{chatMessages.messages}" />    
   </mx:HBox>
   
-  <mx:HBox id="chatCtrlBar" width="100%" height="50" styleName="chatControlBarStyle" paddingLeft="5" paddingRight="5">		
+  <mx:HBox id="chatCtrlBar" width="100%" height="50" styleName="chatControlBarStyle" verticalScrollPolicy="off"
+           paddingLeft="5" paddingRight="5">		
     <mx:TextArea id="txtMsgArea" width="100%"  color="{cmpColorPicker.selectedColor}" 
                  styleName="chatControlBarTextMsgStyle" 
                  toolTip="{ResourceUtil.getInstance().getString('bbb.accessibility.chat.chatwindow.input')}"/>
-    <mx:VBox>
+    <mx:VBox verticalScrollPolicy="off">
       <mx:Button label="{ResourceUtil.getInstance().getString('bbb.chat.sendBtn')}" id="sendBtn" 
                  styleName="chatControlBarSendButtonStyle"
                  toolTip="{ResourceUtil.getInstance().getString('bbb.chat.sendBtn.toolTip')}" 
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatControlBar.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatControlBar.mxml
index c7e0aa2ae67e8b525e6f661e5527bf20b7eab6a2..7f841ec434e9da3bb4237055c7a906c8d2d8014d 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatControlBar.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatControlBar.mxml
@@ -5,6 +5,6 @@
                styleName="chatControlBarTextMsgStyle" toolTip="{ResourceUtil.getInstance().getString('bbb.accessibility.chat.chatwindow.input')}"/>
   <mx:ColorPicker id="cmpColorPicker" showTextField="false" toolTip="{ResourceUtil.getInstance().getString('bbb.chat.cmpColorPicker.toolTip')}" 
                   selectedColor="0x000000" dataProvider="{chatView.colorPickerColours}" swatchPanelStyleName="chatColorPickerStyle"/>
-  <mx:Button label="{ResourceUtil.getInstance().getString('bbb.chat.sendBtn')}" id="sendBtn" styleName="chatControlBarSendButtonStyle"
+  <mx:Button label="{ResourceUtil.getInstance().getString('bbb.chat.sendBtn')}" id="sendBtn" styleName="chatSendButtonStyle"
              toolTip="{ResourceUtil.getInstance().getString('bbb.chat.sendBtn.toolTip')}" click="chatView.sendMessages()"/>   
 </mx:ControlBar>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatMessageRenderer.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatMessageRenderer.mxml
index 7dc0cdb22942e3b8779ade49f3ec3200d20e715b..cf6cc4b5e88fed3f4bb9b5bb515f75d15067cadf 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatMessageRenderer.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatMessageRenderer.mxml
@@ -20,7 +20,7 @@
   $Id: $
 -->
 
-<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" verticalAlign="top" height="{txtMessage.height + 3}" 
+<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" verticalAlign="top" 
 		 verticalScrollPolicy="off" xmlns:common="org.bigbluebutton.common.*" dataChange="validateNow()"
 		 creationComplete="onCreationComplete()">
 	
@@ -35,6 +35,7 @@
 			[Bindable] private var chatTime:String;
 			
 			private function onLinkClick(e:TextEvent):void{
+        trace("Clicked on link[" + e.text + "] from chat");
 				var url:URLRequest = new URLRequest(e.text);
 				navigateToURL(url, '_blank');
 			}
@@ -80,10 +81,16 @@
 		]]>
 	</mx:Script>
 	
-	<mx:Label maxWidth="50" width="50" truncateToFit="true" id="lblName" text="{chatMsg.name} " visible="{!(chatMsg.senderId == chatMsg.lastSenderId)}" color="gray" />
-	<mx:Text id="txtMessage" htmlText="{rolledOver ? chatMsg.senderText : chatMsg.translatedText}" link="onLinkClick(event)" color="{chatMsg.senderColor}"
-			 rollOver="onRollOver()" rollOut="onRollOut()" width="100%" />
-	<mx:Text id="lblTime" htmlText="{chatMsg.translateLocale} {rolledOver ? chatMsg.senderTime : chatMsg.time}" 
-				visible="{!(chatMsg.lastTime == chatMsg.time) || !(chatMsg.senderId == chatMsg.lastSenderId)}" 
-				color="gray" />
-</mx:HBox>
+  <mx:HBox width="100%">
+    <mx:Label id="lblName" text="{chatMsg.name} " visible="{!(chatMsg.senderId == chatMsg.lastSenderId)}" color="gray" width="100%" textAlign="left"/>
+    <mx:Spacer width="100%"/>
+    <mx:Text id="lblTime" htmlText="{chatMsg.translateLocale} {rolledOver ? chatMsg.senderTime : chatMsg.time}" textAlign="right"
+             visible="{!(chatMsg.lastTime == chatMsg.time) || !(chatMsg.senderId == chatMsg.lastSenderId)}" 
+             color="gray"  width="100%"/>       
+  </mx:HBox>
+  <mx:HBox width="100%">
+    <mx:Spacer width="5"/>
+    <mx:Text id="txtMessage" htmlText="{rolledOver ? chatMsg.senderText : chatMsg.translatedText}" link="onLinkClick(event)" color="{chatMsg.senderColor}"
+             rollOver="onRollOver()" rollOut="onRollOut()" width="100%" selectable="true"/>
+  </mx:HBox>  
+</mx:VBox>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatView.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatView.mxml
index f70b284bb9925f56052ff74e2a1d4d2ec158e7bc..d877f923089e3163ba42ef97de6dca7b4f3c4821 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatView.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/chat/views/ChatView.mxml
@@ -63,7 +63,6 @@
       import org.bigbluebutton.core.events.CoreEvent;
       import org.bigbluebutton.core.managers.UserManager;
       import org.bigbluebutton.main.events.BBBEvent;
-      import org.bigbluebutton.main.events.ParticipantJoinEvent;
       import org.bigbluebutton.main.events.ShortcutEvent;
       import org.bigbluebutton.main.model.users.BBBUser;
       import org.bigbluebutton.modules.chat.ChatUtil;
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/layout/managers/LayoutManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/layout/managers/LayoutManager.as
index eef563a5976b7d0f68e8f08c8bc5a8e7f6aae4b2..aad685d1acae7ef72e735bbdf5d99885d533f483 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/layout/managers/LayoutManager.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/layout/managers/LayoutManager.as
@@ -39,6 +39,7 @@ package org.bigbluebutton.modules.layout.managers
   
   import org.bigbluebutton.common.LogUtil;
   import org.bigbluebutton.core.EventBroadcaster;
+  import org.bigbluebutton.core.events.SwitchedLayoutEvent;
   import org.bigbluebutton.core.managers.UserManager;
   import org.bigbluebutton.core.model.Config;
   import org.bigbluebutton.main.events.ModuleLoadEvent;
@@ -195,23 +196,46 @@ package org.bigbluebutton.modules.layout.managers
       var newLayout:LayoutDefinition = _layouts.getLayout(name);
       if (newLayout == null) return;
 
-      LogUtil.debug("************** USING [" + newLayout.name + "] LAYOUT ***************************");
+      trace("************** USING [" + newLayout.name + "] as new LAYOUT ***************************");
       applyLayout(newLayout);
-      sendLayoutUpdate(_currentLayout);      
+      sendLayoutUpdate(_currentLayout);     
+      
+      dispatchSwitchedLayoutEvent(newLayout.name);
     }
     
-		public function applyDefaultLayout():void {      
+		public function applyDefaultLayout():void {   
+      
       var layoutOptions:LayoutOptions = new LayoutOptions();
       layoutOptions.parseOptions();
       var defaultLayout:LayoutDefinition = _layouts.getLayout(layoutOptions.defaultLayout);
+           
+      var sessionDefaulLayout:String = UserManager.getInstance().getConference().getDefaultLayout();
+      
+      
+      if (sessionDefaulLayout != "NOLAYOUT") {
+        var sesLayout:LayoutDefinition = _layouts.getLayout(sessionDefaulLayout);
+        if (sesLayout != null) {
+          defaultLayout = sesLayout;
+        }
+      }
+      
       if (defaultLayout == null) {
         defaultLayout = _layouts.getDefault();
       }
-      LogUtil.debug("************** USING [" + defaultLayout.name + "] LAYOUT ***************************");
+      
+      trace("************** USING [" + defaultLayout.name + "] as default LAYOUT ***************************");
 			applyLayout(defaultLayout);
 			sendLayoutUpdate(_currentLayout);
+      
+      dispatchSwitchedLayoutEvent(defaultLayout.name);
 		}
 		
+    private function dispatchSwitchedLayoutEvent(layoutID:String):void {
+      var layoutEvent:SwitchedLayoutEvent = new SwitchedLayoutEvent();
+      layoutEvent.layoutID = layoutID;
+      _globalDispatcher.dispatchEvent(layoutEvent);      
+    }
+    
 		public function lockLayout():void {
 			_locked = true;
 			LogUtil.debug("LayoutManager: layout locked by myself");
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/layout/model/LayoutDefinition.as b/bigbluebutton-client/src/org/bigbluebutton/modules/layout/model/LayoutDefinition.as
index 92bc29a16f718e174c5208d41c6388e06c42f909..fea809c7d9140cc4ecb0b39c1e3b58a9fdfd3f09 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/layout/model/LayoutDefinition.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/layout/model/LayoutDefinition.as
@@ -35,15 +35,11 @@ package org.bigbluebutton.modules.layout.model {
 		[Bindable] public var defaultLayout:Boolean = false;
 		private var _windows:Dictionary = new Dictionary();
 		
-		static private var _ignoredWindows:Array = new Array("PublishWindow", 
+		static private var _ignoredWindows:Array = new Array("AvatarWindow", "PublishWindow", 
 				"VideoWindow", "DesktopPublishWindow", "DesktopViewWindow",
 				"LogWindow");
 		static private var _roles:Array = new Array(Role.VIEWER, Role.MODERATOR, Role.PRESENTER);
-		
-		public function LayoutDefinition() {
-			
-		}
-		
+				
 		private function loadLayout(vxml:XML):void {
 			if (vxml.@name != undefined) {
 				name = vxml.@name.toString();
@@ -81,18 +77,19 @@ package org.bigbluebutton.modules.layout.model {
 			var hasModeratorLayout:Boolean = _windows.hasOwnProperty(Role.MODERATOR);
 			var hasPresenterLayout:Boolean = _windows.hasOwnProperty(Role.PRESENTER);
 			
-			if (UserManager.getInstance().getConference().amIPresenter() && hasPresenterLayout)
-				return _windows[Role.PRESENTER];
-			else if (UserManager.getInstance().getConference().amIModerator() && hasModeratorLayout)
-				return _windows[Role.MODERATOR];
-			else if (hasViewerLayout) 
-				return _windows[Role.VIEWER];
-			else if (hasModeratorLayout)
-				return _windows[Role.MODERATOR];
-			else if (hasPresenterLayout)
-				return _windows[Role.PRESENTER];
-			else {
+			if (UserManager.getInstance().getConference().amIPresenter() && hasPresenterLayout) {
+        return _windows[Role.PRESENTER];        
+      } else if (UserManager.getInstance().getConference().amIModerator() && hasModeratorLayout) {
+        return _windows[Role.MODERATOR];        
+      } else if (hasViewerLayout) {
+        return _windows[Role.VIEWER];        
+      } else if (hasModeratorLayout) {
+        return _windows[Role.MODERATOR];        
+      } else if (hasPresenterLayout) {
+        return _windows[Role.PRESENTER];        
+      } else {
 				LogUtil.error("There's no layout that fits the participants profile");
+        trace("LayoutDefinition::getMyLayout There's no layout that fits the participants profile");
 				return null;
 			}
 		}
@@ -189,11 +186,15 @@ package org.bigbluebutton.modules.layout.model {
 		}
 		
 		public function applyToWindow(canvas:MDICanvas, window:MDIWindow, type:String=null):void {
-			if (type == null)
-				type = WindowLayout.getType(window);
+			if (type == null) {
+        type = WindowLayout.getType(window);
+      }
+				
 
-			if (!ignoreWindowByType(type))
-				WindowLayout.setLayout(canvas, window, myLayout[type]);
+			if (!ignoreWindowByType(type)) {
+        trace("LayoutDefinition::applyToWindow [" + window.name + ", type=" + type + "]");
+        WindowLayout.setLayout(canvas, window, myLayout[type]);
+      }				
 		}
 		
 		static private function ignoreWindowByType(type:String):Boolean {
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/layout/model/WindowLayout.as b/bigbluebutton-client/src/org/bigbluebutton/modules/layout/model/WindowLayout.as
index 4610e0c45d9cf2d218a51da13e2ecdec6f1cf8c6..1c0200579610a476176e7ab53c1710e49084beee 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/layout/model/WindowLayout.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/layout/model/WindowLayout.as
@@ -23,13 +23,11 @@ package org.bigbluebutton.modules.layout.model {
 
 		import flexlib.mdi.containers.MDICanvas;
 		import flexlib.mdi.containers.MDIWindow;
-
 		import mx.effects.Fade;
 		import mx.effects.Move;
 		import mx.effects.Parallel;
 		import mx.effects.Resize;
 		import mx.events.EffectEvent;
-
 		import flash.display.DisplayObject;
 		import flash.display.DisplayObjectContainer;
 		import flash.utils.Dictionary;
@@ -47,12 +45,15 @@ package org.bigbluebutton.modules.layout.model {
 		[Bindable] public var minimized:Boolean = false;
 		[Bindable] public var maximized:Boolean = false;
 		[Bindable] public var hidden:Boolean = false;
+    [Bindable] public var resizable:Boolean = true;
+    [Bindable] public var draggable:Boolean = true;
 		[Bindable] public var order:int = -1;
 		
 
 		static private var EVENT_DURATION:int = 500;
 
 		public function load(vxml:XML):void {
+//      trace("Load layout \n" + vxml.toXMLString() + "\n");
 			if (vxml != null) {
 				if (vxml.@name != undefined) {
 					name = vxml.@name.toString();
@@ -78,10 +79,19 @@ package org.bigbluebutton.modules.layout.model {
 				if (vxml.@hidden != undefined) {
 					hidden = (vxml.@hidden.toString().toUpperCase() == "TRUE") ? true : false;
 				}
+        if (vxml.@draggable != undefined) {
+          draggable = (vxml.@draggable.toString().toUpperCase() == "TRUE") ? true : false;
+        }
+        if (vxml.@resizable != undefined) {
+          resizable = (vxml.@resizable.toString().toUpperCase() == "TRUE") ? true : false;
+        }
 				if (vxml.@order != undefined) {
 					order = int(vxml.@order);
 				}
 			}
+      
+//      trace("WindowLayout::load for " + name + " [minimized=" + minimized + ",maximized=" 
+//        + maximized + ",hidden=" + hidden + ",drag=" + draggable + ",resize=" + resizable + "]");
 		}
 		
 		static public function getLayout(canvas:MDICanvas, window:MDIWindow):WindowLayout {
@@ -93,13 +103,27 @@ package org.bigbluebutton.modules.layout.model {
 			layout.y = window.y / canvas.height;
 			layout.minimized = window.minimized;
 			layout.maximized = window.maximized;
+      layout.resizable = window.resizable;
+      layout.draggable = window.draggable;
 			layout.hidden = !window.visible;
 			layout.order = OrderManager.getInstance().getOrderByRef(window);
+      
+//      trace("WindowLayout::getLayout for " + layout.name + " [minimized=" + layout.minimized + ",maximized=" + layout.maximized + ",hidden=" + layout.hidden 
+//        + ",drag=" + layout.draggable + ",resize=" + layout.resizable + "]");
+      
 			return layout;
 		}
 		
 		static public function setLayout(canvas:MDICanvas, window:MDIWindow, layout:WindowLayout):void {
-			if (layout == null) return;
+//      trace("WindowLayout::setLayout for " + window.name + ",layout=" + layout.name + "]");
+      
+			if (layout == null) {
+        return;
+      }
+      
+//      trace("WindowLayout::setLayout [minimized=" + layout.minimized + ",maximized=" + layout.maximized + ",hidden=" + layout.hidden 
+//        + ",drag=" + layout.draggable + ",resize=" + layout.resizable + "]");
+      
 			layout.applyToWindow(canvas, window);
 		}
 		
@@ -113,11 +137,14 @@ package org.bigbluebutton.modules.layout.model {
 		}
 		
 		private function onTimerComplete(event:TimerEvent = null):void {
+//      trace("::onTimerComplete");
 			var obj:Object = _delayedEffects.pop();
 			applyToWindow(obj.canvas, obj.window);
 		}
 		
 		public function applyToWindow(canvas:MDICanvas, window:MDIWindow):void {
+//      trace("WindowLayout::applyToWindow for " + window.name + " using layout " + this.name + "]");
+      
 			var effect:Parallel = new Parallel();
 			effect.duration = EVENT_DURATION;
 			effect.target = window;
@@ -130,6 +157,9 @@ package org.bigbluebutton.modules.layout.model {
         window.visible = true;
       }
       
+      window.draggable = this.draggable;
+      window.resizable = this.resizable;
+      
 			if (this.minimized) {
 				if (!window.minimized) window.minimize();
 			} else if (this.maximized) {
@@ -165,29 +195,19 @@ package org.bigbluebutton.modules.layout.model {
 				}
 			}
       
-
-
-      /*
-			var layoutHidden:Boolean = this.hidden;
-//			var windowVisible:Boolean = (window.alpha == 1);
-			var windowVisible:Boolean = window.visible;
-			if (windowVisible == layoutHidden) {
-				var fader:Fade = new Fade();
-				fader.alphaFrom = (layoutHidden? 1: 0);
-				fader.alphaTo = (layoutHidden? 0: 1);
-				fader.addEventListener(EffectEvent.EFFECT_START, function(e:EffectEvent):void {
-					if (!windowVisible)
-						window.enabled = window.visible = true;
-				});
-				fader.addEventListener(EffectEvent.EFFECT_END, function(e:EffectEvent):void {
-					if (windowVisible)
-						window.enabled = window.visible = false;
-				});
-				effect.addChild(fader);
-			}
-*/			
-			if (effect.children.length > 0)
+      if (window.visible && this.hidden) {
+        window.visible = false;
+      }
+      
+//      trace("WindowLayout::applyToWindow Layout= [minimized=" + this.minimized + ",maximized=" + this.maximized + ",visible=" + !this.hidden 
+//        + ",drag=" + this.draggable + ",resize=" + this.resizable + "]");
+      
+//      trace("WindowLayout::applyToWindow Window = [minimized=" + window.minimized + ",maximized=" + window.maximized + ",visible=" + window.visible 
+//        + ",drag=" + window.draggable + ",resize=" + window.resizable + "]");
+		
+			if (effect.children.length > 0) {
 				effect.play();
+      }
 		}
 		
 		static public function getType(obj:Object):String {
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/listeners/business/ListenersSOService.as b/bigbluebutton-client/src/org/bigbluebutton/modules/listeners/business/ListenersSOService.as
index a144cb30a5d6d55ae0658b2e0d6b01467ff16aad..edbc3dbb6358872cc57a19e8a4f35a68f05b398e 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/listeners/business/ListenersSOService.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/listeners/business/ListenersSOService.as
@@ -18,14 +18,12 @@
 */
 package org.bigbluebutton.modules.listeners.business
 {
-	import com.asfusion.mate.events.Dispatcher;
-	
+	import com.asfusion.mate.events.Dispatcher;	
 	import flash.events.AsyncErrorEvent;
 	import flash.events.NetStatusEvent;
 	import flash.net.NetConnection;
 	import flash.net.Responder;
-	import flash.net.SharedObject;
-	
+	import flash.net.SharedObject;	
 	import org.bigbluebutton.common.LogUtil;
 	import org.bigbluebutton.core.EventConstants;
 	import org.bigbluebutton.core.UsersUtil;
@@ -141,6 +139,10 @@ package org.bigbluebutton.modules.listeners.business
             bu.voiceUserid = n.userid;
             bu.voiceMuted = n.muted;
             bu.voiceJoined = true;
+            
+            var bbbEvent:BBBEvent = new BBBEvent(BBBEvent.USER_VOICE_JOINED);
+            bbbEvent.payload.userID = bu.userID;            
+            globalDispatcher.dispatchEvent(bbbEvent);            
           }
           
 					n.callerName = result[2]; /* Store the username */
@@ -149,35 +151,49 @@ package org.bigbluebutton.modules.listeners.business
 				LogUtil.info(LOGNAME + "Adding listener [" + n.callerName + "," + userId + "]");
 				_listeners.addListener(n);
 				
-				globalDispatcher.dispatchEvent(new BBBEvent(BBBEvent.ADDED_LISTENER, n.callerName));
+//				globalDispatcher.dispatchEvent(new BBBEvent(BBBEvent.USER_VOICE_JOINED, n.callerName));
 			} else {
 				LogUtil.debug(LOGNAME + "There is a listener with userid " + userId + " " + cidName + " in the conference.");
 			}
 		}
 
-		public function userMute(userId:Number, mute:Boolean):void {
-			var l:Listener = _listeners.getListener(userId);			
+		public function userMute(userID:Number, mute:Boolean):void {
+			var l:Listener = _listeners.getListener(userID);			
 			if (l != null) {
 				l.muted = mute;
+        
+        if (l.muted) {
+          // When the user is muted, set the talking flag to false so that the UI will not display the
+          // user as talking even if muted.
+          userTalk(userID, false);
+        }
+        
 				/**
 				 * Let's store the voice userid so we can do push to talk.
 				 */
-				if (UserManager.getInstance().getConference().amIThisVoiceUser(userId)) {
+				if (UserManager.getInstance().getConference().amIThisVoiceUser(userID)) {
 					UserManager.getInstance().getConference().muteMyVoice(l.muted);
 				}				
         
-        var bu:BBBUser = UsersUtil.getVoiceUser(userId)
+        var bu:BBBUser = UsersUtil.getVoiceUser(userID)
         if (bu != null) {
           bu.voiceMuted = l.muted;
-        }        
-			}					
+          
+          LogUtil.debug("[" + bu.name + "] is now muted=[" + bu.voiceMuted + "]");
+          
+          var bbbEvent:BBBEvent = new BBBEvent(BBBEvent.USER_VOICE_MUTED);
+          bbbEvent.payload.muted = mute;
+          bbbEvent.payload.userID = bu.userID;
+          globalDispatcher.dispatchEvent(bbbEvent);
+        }     
+			}			     
 		}
 
 		public function userLockedMute(userId:Number, locked:Boolean):void {
 			var l:Listener = _listeners.getListener(userId);			
 			if (l != null) {
 				l.locked = locked;
-				LogUtil.debug(LOGNAME + 'Lock Un/Muting user ' + userId + " locked=" + locked);
+
 				/**
 				 * Let's store the voice userid so we can do push to talk.
 				 */
@@ -188,12 +204,19 @@ package org.bigbluebutton.modules.listeners.business
         var bu:BBBUser = UsersUtil.getVoiceUser(userId)
         if (bu != null) {
           bu.voiceLocked = l.locked;
+          LogUtil.debug("[" + bu.name + "] is now locked=[" + bu.voiceLocked + "] muted=[" + bu.voiceMuted + "]");
+          
+          var bbbEvent:BBBEvent = new BBBEvent(BBBEvent.USER_VOICE_LOCKED);
+          bbbEvent.payload.locked = bu.voiceLocked;
+          bbbEvent.payload.userID = bu.userID;
+          globalDispatcher.dispatchEvent(bbbEvent);
         }   
 			}					
 		}
 		
 		public function userTalk(userId:Number, talk:Boolean) : void
 		{
+      trace("User talking event");
 			var l:Listener = _listeners.getListener(userId);			
 			if (l != null) {
 				l.talking = talk;
@@ -226,6 +249,10 @@ package org.bigbluebutton.modules.listeners.business
         bu.voiceUserid = 0;
         bu.voiceMuted = false;
         bu.voiceJoined = false;
+        
+        var bbbEvent:BBBEvent = new BBBEvent(BBBEvent.USER_VOICE_LEFT);
+        bbbEvent.payload.userID = bu.userID;
+        globalDispatcher.dispatchEvent(bbbEvent);
       }
 		}
 		
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/listeners/views/ListenerItem.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/listeners/views/ListenerItem.mxml
index d6d81d4f84d4eec7ec10b0673d32895526d95e44..b9a86b82aa59fc8d33e63ce044130af8f7c7a145 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/listeners/views/ListenerItem.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/listeners/views/ListenerItem.mxml
@@ -41,7 +41,7 @@
 			[Bindable] private var muteIcon:Class = images.sound_mute;
 			[Bindable] private var unmuteIcon:Class = images.sound_none;
 			[Bindable] private var talkIcon:Object = images.sound;   		
-			[Bindable] private var ejectIcon:Class = images.delete_icon;
+			[Bindable] private var ejectIcon:Class = images.cancel;
 			[Bindable] private var statusTooltip : String = "";
 			[Bindable] private var ejectTooltip : String = ResourceUtil.getInstance().getString('bbb.listeners.ejectTooltip');
 			[Bindable] private var moderator:Boolean = false;
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/NotesModuleStartEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/NotesModuleStartEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..813f5a560112b05bb7de15040050cc1274c4ed22
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/NotesModuleStartEvent.as
@@ -0,0 +1,14 @@
+package org.bigbluebutton.modules.notes.events
+{
+  import flash.events.Event;
+  
+  public class NotesModuleStartEvent extends Event
+  {
+    public static const NOTES_MODULE_START:String = "notes module start event";
+    
+    public function NotesModuleStartEvent(bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(NOTES_MODULE_START, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/NotesModuleStopEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/NotesModuleStopEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..51c4d9bb56c863158bb803be04b2dd58e2f02486
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/NotesModuleStopEvent.as
@@ -0,0 +1,14 @@
+package org.bigbluebutton.modules.notes.events
+{
+  import flash.events.Event;
+  
+  public class NotesModuleStopEvent extends Event
+  {
+    public static const NOTES_MODULE_STOP:String = "notes module stop event";
+    
+    public function NotesModuleStopEvent(bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(NOTES_MODULE_STOP, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/RetrieveNotesErrorEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/RetrieveNotesErrorEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..aed1473faf210d5156d4c68569b97de09c0c8d91
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/RetrieveNotesErrorEvent.as
@@ -0,0 +1,14 @@
+package org.bigbluebutton.modules.notes.events
+{
+  import flash.events.Event;
+  
+  public class RetrieveNotesErrorEvent extends Event
+  {
+    public static const RETRIEVE_ERROR:String = "notes retrieve error event";
+    
+    public function RetrieveNotesErrorEvent(bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(RETRIEVE_ERROR, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/RetrieveNotesEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/RetrieveNotesEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..79af669e474955d49c511d81d9f49d911ab6c528
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/RetrieveNotesEvent.as
@@ -0,0 +1,14 @@
+package org.bigbluebutton.modules.notes.events
+{
+  import flash.events.Event;
+  
+  public class RetrieveNotesEvent extends Event
+  {
+    public static const RETRIEVE:String = "notes retrieve request event";
+    
+    public function RetrieveNotesEvent(bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(RETRIEVE, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/RetrieveNotesSuccessEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/RetrieveNotesSuccessEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..ddad695f12774a881eca83899585d5c6dc893ccc
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/RetrieveNotesSuccessEvent.as
@@ -0,0 +1,18 @@
+package org.bigbluebutton.modules.notes.events
+{
+  import flash.events.Event;
+  
+  import mx.collections.ArrayCollection;
+  
+  public class RetrieveNotesSuccessEvent extends Event
+  {
+    public static const RETRIEVE_SUCCESS:String = "notes retrieve success event";
+    
+    public var notes:ArrayCollection;
+    
+    public function RetrieveNotesSuccessEvent(bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(RETRIEVE_SUCCESS, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/SaveErrorEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/SaveErrorEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..2496154ca92555cac7c80a0b827c88958cdda027
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/SaveErrorEvent.as
@@ -0,0 +1,22 @@
+package org.bigbluebutton.modules.notes.events
+{
+  import flash.events.Event;
+  
+  public class SaveErrorEvent extends Event
+  {
+    public static const NOTE_SAVE_ERROR:String = "note save error event";
+    
+    public static const SUCCESS:String = "note save success event";
+    public static const FAILED_TO_SAVE:String = "note failed to save event";
+    public static const SECURITY_ERROR:String = "note security error event";
+    public static const IO_ERROR:String       = "note io error event";
+    
+    public var reason:String;
+    public var noteID:String;
+    
+    public function SaveErrorEvent(bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(NOTE_SAVE_ERROR, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/SaveNoteEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/SaveNoteEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..2a988822480c061d3a1a2040ebafb7a6d837e561
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/SaveNoteEvent.as
@@ -0,0 +1,16 @@
+package org.bigbluebutton.modules.notes.events
+{
+  import flash.events.Event;
+  
+  public class SaveNoteEvent extends Event
+  {
+    public static const SAVE_NOTE:String = "notes module save note event";
+    
+    public var note:String;
+    
+    public function SaveNoteEvent(bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(SAVE_NOTE, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/SaveSuccessEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/SaveSuccessEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..504cb1cd90ac7a20a8bdcf73fde79ff944575149
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/events/SaveSuccessEvent.as
@@ -0,0 +1,17 @@
+package org.bigbluebutton.modules.notes.events
+{
+  import flash.events.Event;
+  
+  public class SaveSuccessEvent extends Event
+  {
+    public static const NOTE_SAVE_SUCCESS:String = "note save success event";
+    
+    public var noteID:String;
+    public var timestamp:String;
+    
+    public function SaveSuccessEvent(bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(NOTE_SAVE_SUCCESS, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/maps/NotesEventMap.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/maps/NotesEventMap.mxml
new file mode 100755
index 0000000000000000000000000000000000000000..704e9415853621c9ae823107d7e97b914bd76525
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/maps/NotesEventMap.mxml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+
+  Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+
+  This program is free software; you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free Software
+  Foundation; either version 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/>.
+
+  Author: Felipe Cecagno <felipe@mconf.org>
+
+  $Id: $
+-->
+<EventMap xmlns:mx="http://www.adobe.com/2006/mxml" 
+          xmlns="http://mate.asfusion.com/">
+	<mx:Script>
+		<![CDATA[
+      import mx.events.FlexEvent;      
+      import org.bigbluebutton.modules.notes.events.NotesModuleStartEvent;
+      import org.bigbluebutton.modules.notes.events.RetrieveNotesEvent;
+      import org.bigbluebutton.modules.notes.events.RetrieveNotesSuccessEvent;
+      import org.bigbluebutton.modules.notes.events.SaveErrorEvent;
+      import org.bigbluebutton.modules.notes.events.SaveNoteEvent;
+      import org.bigbluebutton.modules.notes.events.SaveSuccessEvent;
+      import org.bigbluebutton.modules.notes.models.NotesModel;
+      import org.bigbluebutton.modules.notes.services.NotesMessageService;
+      import org.bigbluebutton.modules.notes.services.RetrieveNotesService;
+      
+		]]>
+	</mx:Script>
+
+  <EventHandlers type="{NotesModuleStartEvent.NOTES_MODULE_START}">    
+    <ObjectBuilder generator="{NotesModel}" cache="global"/>
+    <ObjectBuilder generator="{RetrieveNotesService}" cache="global" constructorArguments="{scope.dispatcher}"/>
+    <ObjectBuilder generator="{NotesMessageService}" cache="global" constructorArguments="{scope.dispatcher}"/>
+    <ObjectBuilder generator="{NotesEventMapDelegate}" cache="global" constructorArguments="{scope.dispatcher}"/>   
+  </EventHandlers>
+
+  <EventHandlers type="{RetrieveNotesEvent.RETRIEVE}">        
+    <MethodInvoker generator="{RetrieveNotesService}" method="retrieveNotes"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{RetrieveNotesSuccessEvent.RETRIEVE_SUCCESS}">        
+    <MethodInvoker generator="{NotesEventMapDelegate}" method="handleRetrieveNotesSuccessEvent" arguments="{event}"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{SaveNoteEvent.SAVE_NOTE}">        
+    <MethodInvoker generator="{NotesMessageService}" method="save" arguments="{event.note}" />
+  </EventHandlers>
+  
+  <EventHandlers type="{SaveSuccessEvent.NOTE_SAVE_SUCCESS}">        
+    <MethodInvoker generator="{NotesMessageService}" method="saveSuccess" arguments="{event}" />
+  </EventHandlers>	
+  
+  <EventHandlers type="{SaveErrorEvent.FAILED_TO_SAVE}">        
+    <MethodInvoker generator="{NotesMessageService}" method="saveError" arguments="{event}" />
+  </EventHandlers>	
+  
+  <Injectors target="{NotesEventMapDelegate}">
+    <PropertyInjector targetKey="notesModel" source="{NotesModel}"/>
+  </Injectors>
+  
+  <Injectors target="{NotesMessageService}">
+    <PropertyInjector targetKey="notesModel" source="{NotesModel}"/>
+  </Injectors>
+</EventMap>
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/maps/NotesEventMapDelegate.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/maps/NotesEventMapDelegate.as
new file mode 100755
index 0000000000000000000000000000000000000000..b290e41e06a0613f6fff6b6f78f13777dce4ae07
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/maps/NotesEventMapDelegate.as
@@ -0,0 +1,49 @@
+package org.bigbluebutton.modules.notes.maps
+{
+  import com.asfusion.mate.events.Dispatcher;
+  
+  import flash.events.IEventDispatcher;
+  
+  import org.bigbluebutton.common.events.OpenWindowEvent;
+  import org.bigbluebutton.modules.notes.events.RetrieveNotesEvent;
+  import org.bigbluebutton.modules.notes.events.RetrieveNotesSuccessEvent;
+  import org.bigbluebutton.modules.notes.events.SaveNoteEvent;
+  import org.bigbluebutton.modules.notes.models.NotesModel;
+  import org.bigbluebutton.modules.notes.views.NotesWindow;
+
+  public class NotesEventMapDelegate
+  {    
+    private var _notesWindow:NotesWindow;
+    private var _dispatcher:IEventDispatcher;
+    
+    public var notesModel:NotesModel;
+    
+    public function NotesEventMapDelegate(dispatcher:IEventDispatcher)
+    {
+      _dispatcher = dispatcher;
+      _dispatcher.dispatchEvent(new RetrieveNotesEvent());
+    }
+    
+    public function handleRetrieveNotesSuccessEvent(event:RetrieveNotesSuccessEvent):void {
+      notesModel.notes = event.notes;
+      
+      openNotesWindow();
+      saveALoginNote();    
+    }
+    
+    private function saveALoginNote():void {
+      var saveEvent:SaveNoteEvent = new SaveNoteEvent();
+      saveEvent.note = "** Logged in. **";
+      _dispatcher.dispatchEvent(saveEvent);
+    }
+    
+    public function openNotesWindow():void {
+      _notesWindow = new NotesWindow();
+      _notesWindow.notesModel = notesModel;
+      
+      var event:OpenWindowEvent = new OpenWindowEvent(OpenWindowEvent.OPEN_WINDOW_EVENT);
+      event.window = _notesWindow; 
+      _dispatcher.dispatchEvent(event);	
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/models/Note.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/models/Note.as
new file mode 100755
index 0000000000000000000000000000000000000000..f035b849fab17583efcbe6cf8ec8604e30b6d7f2
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/models/Note.as
@@ -0,0 +1,11 @@
+package org.bigbluebutton.modules.notes.models
+{
+  [Bindable]
+  public class Note
+  {
+    public var noteID:String;
+    public var note:String;
+    public var saved:Boolean = false;
+    public var timestamp:String = "";
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/models/NotesModel.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/models/NotesModel.as
new file mode 100755
index 0000000000000000000000000000000000000000..364b0c5545eda746858c135f90b4124a64ae01b2
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/models/NotesModel.as
@@ -0,0 +1,35 @@
+package org.bigbluebutton.modules.notes.models
+{
+  import mx.collections.ArrayCollection;
+
+  public class NotesModel
+  {
+    [Bindable]
+    public var notes:ArrayCollection = new ArrayCollection();
+        
+    public function addNote(n:Note):void {
+      notes.addItem(n);
+    }
+    
+    public function noteSaved(noteID:String, timestamp:String):void {
+      for (var i:int = 0; i < notes.length; i++){
+        var item:Note = notes.getItemAt(i) as Note;
+        if (item.noteID == noteID) {
+          item.saved = true;
+          item.timestamp = timestamp;
+        }
+      }
+    }
+    
+    public function getNote(noteID:String):Note {
+      for (var i:int = 0; i < notes.length; i++){
+        var item:Note = notes.getItemAt(i) as Note;
+        if (item.noteID == noteID) {
+          return item;
+        }
+      }  
+      
+      return null;
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/models/NotesOptions.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/models/NotesOptions.as
new file mode 100755
index 0000000000000000000000000000000000000000..e20cc269a3f79b50a991a32d344e3b2168ebded0
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/models/NotesOptions.as
@@ -0,0 +1,23 @@
+package org.bigbluebutton.modules.notes.models
+{
+  import org.bigbluebutton.core.BBB;
+
+  public class NotesOptions
+  {
+    public var saveURL:String;
+    public var position:String = "top-right";
+    
+    public function NotesOptions()
+    {
+      var cxml:XML = 	BBB.getConfigForModule("NotesModule");
+      if (cxml != null) {
+        if (cxml.@saveURL != undefined) {
+          saveURL = cxml.@saveURL.toString();
+        }
+        if (cxml.@position != undefined) {
+          position = cxml.@position.toString();
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/MessageReceiver.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/MessageReceiver.as
new file mode 100755
index 0000000000000000000000000000000000000000..f02c5bb05e6e63c5c04a7bb0df00a89f58a74d57
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/MessageReceiver.as
@@ -0,0 +1,9 @@
+package org.bigbluebutton.modules.notes.services
+{
+  public class MessageReceiver
+  {
+    public function MessageReceiver()
+    {
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/MessageSender.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/MessageSender.as
new file mode 100755
index 0000000000000000000000000000000000000000..d77e1be1b48eb09e3ba24c5cf40e3876dd5a6260
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/MessageSender.as
@@ -0,0 +1,9 @@
+package org.bigbluebutton.modules.notes.services
+{
+  public class MessageSender
+  {
+    public function MessageSender()
+    {
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/NoteSaver.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/NoteSaver.as
new file mode 100755
index 0000000000000000000000000000000000000000..ac7a1ef67be927e00351bae09842b2585e8f9c34
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/NoteSaver.as
@@ -0,0 +1,138 @@
+package org.bigbluebutton.modules.notes.services
+{
+  import flash.events.Event;
+  import flash.events.HTTPStatusEvent;
+  import flash.events.IEventDispatcher;
+  import flash.events.IOErrorEvent;
+  import flash.events.ProgressEvent;
+  import flash.events.SecurityErrorEvent;
+  import flash.net.URLLoader;
+  import flash.net.URLRequest;
+  import flash.net.URLRequestMethod;
+  import flash.net.URLVariables;
+  import flash.utils.ByteArray;
+  
+  import mx.utils.Base64Decoder;
+  import mx.utils.Base64Encoder;
+  
+  import org.bigbluebutton.core.UsersUtil;
+  import org.bigbluebutton.modules.notes.events.SaveErrorEvent;
+  import org.bigbluebutton.modules.notes.events.SaveSuccessEvent;
+  import org.bigbluebutton.modules.notes.models.Note;
+  import org.bigbluebutton.modules.notes.models.NotesOptions;
+  
+  public class NoteSaver
+  {
+    private var _serverURL:String;
+
+    private var _request:URLRequest = new URLRequest();
+    private var _vars:URLVariables;
+    private var _uri:String;
+    private var _loader:URLLoader = new URLLoader();
+    private var _note:Note;
+    private var _dispatcher:IEventDispatcher;
+    
+    public function NoteSaver(note:Note, serverURL:String, dispatcher:IEventDispatcher) {
+      _note = note;
+      _dispatcher = dispatcher;
+      _serverURL = serverURL;
+      
+      _loader.addEventListener(Event.COMPLETE, completeHandler);
+      _loader.addEventListener(Event.OPEN, openHandler);
+      _loader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
+      _loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
+      _loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
+      _loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
+    }
+    
+    public function getNoteID():String {
+      return _note.noteID;
+    }
+    
+    public function save():void {
+      //_request.url = _serverURL + "/save";
+      _request.url = _serverURL;
+      _request.method = URLRequestMethod.GET;
+      
+      _vars = new URLVariables();
+      _vars.saveNote = "";
+      _vars.noteID = _note.noteID;
+      _vars.text = base64Encode(_note.note);
+      _vars.externalMeetingID = UsersUtil.getExternalMeetingID();
+      _vars.internalMeetingID = UsersUtil.getInternalMeetingID();
+      _vars.userID = UsersUtil.internalUserIDToExternalUserID(UsersUtil.getMyUserID());
+      _vars.username = base64Encode(UsersUtil.getMyUsername());
+
+      var dec:Base64Decoder = new Base64Decoder();
+      dec.decode(_vars.text)
+      var decNote:String = dec.toByteArray().toString();
+      trace("Saving note [" + _vars.noteID + "][" + _vars.note + "] to [" + _request.url + "]");
+      
+      _request.data = _vars;
+      
+      try {
+        _loader.load(_request);
+      } catch (error:Error) {
+        trace("Unable to load requested document.");
+        var errorEvent:SaveErrorEvent = new SaveErrorEvent();
+        errorEvent.reason = SaveErrorEvent.FAILED_TO_SAVE;
+        errorEvent.noteID = _note.noteID;
+        _dispatcher.dispatchEvent(errorEvent);
+      }     
+    }
+    
+    private function base64Encode(data:String):String {
+      var encoder:Base64Encoder = new Base64Encoder();
+      encoder.encode(data);
+      return encoder.toString();
+    }
+    
+    private function completeHandler(event:Event):void {
+      var xml:XML = new XML(event.target.data);
+      
+      if (saveSuccess(xml)) {
+        trace("SAVED noteID [" + _note.noteID + "] on [" + xml.timestamp + "]");
+        var successEvent:SaveSuccessEvent = new SaveSuccessEvent();
+        successEvent.noteID = _note.noteID;
+        successEvent.timestamp = xml.timestamp;
+        _dispatcher.dispatchEvent(successEvent);        
+      } else {
+        trace("NOT SAVED");
+      } 
+    }
+    
+    private function saveSuccess(xml:XML):Boolean {
+      if (xml.success == 'T' || xml.success == 't') return true;
+      return false;
+    }
+    
+    private function openHandler(event:Event):void {
+      trace("openHandler: " + event);
+    }
+    
+    private function progressHandler(event:ProgressEvent):void {
+      trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
+    }
+    
+    private function securityErrorHandler(event:SecurityErrorEvent):void {
+      trace("securityErrorHandler: " + event);
+      var errorEvent:SaveErrorEvent = new SaveErrorEvent();
+      errorEvent.reason = SaveErrorEvent.SECURITY_ERROR;
+      errorEvent.noteID = _note.noteID;
+      _dispatcher.dispatchEvent(errorEvent);
+    }
+    
+    private function httpStatusHandler(event:HTTPStatusEvent):void {
+      trace("httpStatusHandler: " + event);
+    }
+    
+    private function ioErrorHandler(event:IOErrorEvent):void {
+      trace("ioErrorHandler: " + event);
+      var errorEvent:SaveErrorEvent = new SaveErrorEvent();
+      errorEvent.reason = SaveErrorEvent.IO_ERROR;
+      errorEvent.noteID = _note.noteID;
+      _dispatcher.dispatchEvent(errorEvent);
+    }
+
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/NotesMessageService.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/NotesMessageService.as
new file mode 100755
index 0000000000000000000000000000000000000000..84735d991dc35aadedc5910f7e90e6d010322c0e
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/NotesMessageService.as
@@ -0,0 +1,61 @@
+package org.bigbluebutton.modules.notes.services
+{
+  import flash.events.IEventDispatcher;
+  
+  import mx.collections.ArrayCollection;
+  
+  import org.bigbluebutton.modules.notes.events.SaveErrorEvent;
+  import org.bigbluebutton.modules.notes.events.SaveSuccessEvent;
+  import org.bigbluebutton.modules.notes.models.Note;
+  import org.bigbluebutton.modules.notes.models.NotesModel;
+  import org.bigbluebutton.modules.notes.models.NotesOptions;
+
+  public class NotesMessageService
+  {
+    public var notesModel:NotesModel;
+    
+    private var _noteSavers:ArrayCollection = new ArrayCollection();    
+    private var _options:NotesOptions;
+    private var _dispatcher:IEventDispatcher;
+    
+    public function NotesMessageService(dispatcher:IEventDispatcher) {
+      _options = new NotesOptions();
+      _dispatcher = dispatcher;
+    }
+    
+    public function save(note:String):void {
+      var date:Date = new Date();
+
+      var n:Note = new Note();
+      n.noteID = generateRandomString(5) + date.time;
+      n.note = note;
+      n.saved = false;
+      notesModel.addNote(n);
+      
+      var noteSaver:NoteSaver = new NoteSaver(n, _options.saveURL, _dispatcher);
+      _noteSavers.addItem(noteSaver);
+      
+      noteSaver.save();
+      
+    }
+    
+    public function saveError(event:SaveErrorEvent):void {
+      // TODO: Re-save?
+    }
+    
+    public function saveSuccess(event:SaveSuccessEvent):void {
+      notesModel.noteSaved(event.noteID, event.timestamp);
+    }
+    
+    private function generateRandomString(strlen:Number):String{
+      var chars:String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+      var num_chars:Number = chars.length - 1;
+      var randomChar:String = "";
+      
+      for (var i:Number = 0; i < strlen; i++){
+        randomChar += chars.charAt(Math.floor(Math.random() * num_chars));
+      }
+      return randomChar;
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/RetrieveNotesService.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/RetrieveNotesService.as
new file mode 100755
index 0000000000000000000000000000000000000000..f22ff5e69d9a8d4913ea24e5a18b682e6f675024
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/services/RetrieveNotesService.as
@@ -0,0 +1,134 @@
+package org.bigbluebutton.modules.notes.services
+{
+  import flash.events.Event;
+  import flash.events.HTTPStatusEvent;
+  import flash.events.IEventDispatcher;
+  import flash.events.IOErrorEvent;
+  import flash.events.ProgressEvent;
+  import flash.events.SecurityErrorEvent;
+  import flash.net.URLLoader;
+  import flash.net.URLRequest;
+  import flash.net.URLRequestMethod;
+  import flash.net.URLVariables;
+  import flash.utils.ByteArray;  
+  import mx.collections.ArrayCollection;
+  import mx.utils.Base64Decoder;
+  import mx.utils.Base64Encoder; 
+  import org.bigbluebutton.core.UsersUtil;
+  import org.bigbluebutton.modules.notes.events.RetrieveNotesErrorEvent;
+  import org.bigbluebutton.modules.notes.events.RetrieveNotesSuccessEvent;
+  import org.bigbluebutton.modules.notes.events.SaveErrorEvent;
+  import org.bigbluebutton.modules.notes.events.SaveSuccessEvent;
+  import org.bigbluebutton.modules.notes.models.Note;
+  import org.bigbluebutton.modules.notes.models.NotesOptions;
+  
+  public class RetrieveNotesService
+  {
+    private var _options:NotesOptions;
+    private var _request:URLRequest = new URLRequest();
+    private var _vars:URLVariables;
+    private var _uri:String;
+    private var _loader:URLLoader = new URLLoader();
+    private var _dispatcher:IEventDispatcher;
+    
+    public function RetrieveNotesService(dispatcher:IEventDispatcher) {
+      _dispatcher = dispatcher;
+      _options = new NotesOptions();
+      
+      _loader.addEventListener(Event.COMPLETE, completeHandler);
+      _loader.addEventListener(Event.OPEN, openHandler);
+      _loader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
+      _loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
+      _loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
+      _loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
+    }
+       
+    public function retrieveNotes():void {
+      //_request.url = _options.saveURL + "/notes";
+      _request.url = _options.saveURL;
+      _request.method = URLRequestMethod.GET;
+      
+      _vars = new URLVariables();
+      _vars.retrieveNotes = "";
+      _vars.meetingID = UsersUtil.getExternalMeetingID();
+      _vars.userID = UsersUtil.internalUserIDToExternalUserID(UsersUtil.getMyUserID());
+    
+      try {
+        _request.data = _vars;
+        _loader.load(_request);
+      } catch (error:Error) {
+        trace("Unable to load requested document.");
+        var errorEvent:RetrieveNotesErrorEvent = new RetrieveNotesErrorEvent();
+        _dispatcher.dispatchEvent(errorEvent);
+      }
+      
+    }
+    
+    private function base64Encode(data:String):String {
+      var encoder:Base64Encoder = new Base64Encoder();
+      encoder.encode(data);
+      return encoder.toString();
+    }
+    
+    private function completeHandler(event:Event):void {
+      var xml:XML = new XML(event.target.data)
+      var notes:ArrayCollection = parseNotes(xml);
+//      if (notes.length > 0) {
+        var successEvent:RetrieveNotesSuccessEvent = new RetrieveNotesSuccessEvent();
+        successEvent.notes = notes;
+        _dispatcher.dispatchEvent(successEvent);        
+//      }    
+    }
+    
+    private function parseNotes(xml:XML):ArrayCollection {
+      var notes:ArrayCollection = new ArrayCollection();
+      var list:XMLList = getNotes(xml);
+      var item:XML;
+      for each(item in list){
+        trace("Saving note [" + item.noteID + "][" + item.text + "]");
+        var note:Note = new Note();
+        var dec:Base64Decoder = new Base64Decoder();
+        dec.decode(item.text)
+        var decNote:String = dec.toByteArray().toString();
+        trace("Saving note [" + item.noteID + "][" + decNote + "]");
+        note.note = decNote;
+        note.noteID =  item.noteID;
+        note.saved = true;
+        note.timestamp = item.timestamp;
+        notes.addItem(note);
+      }
+      return notes;
+    }
+    
+    private function getNotes(xml:XML):XMLList{
+      trace("*** [" + xml.toXMLString() + "]");
+      return xml.notes.note;
+    }
+        
+    private function openHandler(event:Event):void {
+      trace("openHandler: " + event);
+    }
+    
+    private function progressHandler(event:ProgressEvent):void {
+      trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
+    }
+    
+    private function securityErrorHandler(event:SecurityErrorEvent):void {
+      trace("securityErrorHandler: " + event);
+      var errorEvent:RetrieveNotesErrorEvent = new RetrieveNotesErrorEvent();
+      _dispatcher.dispatchEvent(errorEvent);
+    }
+    
+    private function httpStatusHandler(event:HTTPStatusEvent):void {
+      trace("httpStatusHandler: " + event);
+    }
+    
+    private function ioErrorHandler(event:IOErrorEvent):void {
+      trace("ioErrorHandler: " + event);
+      var errorEvent:RetrieveNotesErrorEvent = new RetrieveNotesErrorEvent();
+      _dispatcher.dispatchEvent(errorEvent);
+    }
+    
+
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/views/AdvancedList.as b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/views/AdvancedList.as
new file mode 100755
index 0000000000000000000000000000000000000000..cbece7041c67da571a3320419199006d8101b9aa
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/views/AdvancedList.as
@@ -0,0 +1,19 @@
+package org.bigbluebutton.modules.notes.views
+{
+  import mx.controls.List;
+  
+  public class AdvancedList extends List
+  {
+    public function AdvancedList()
+    {
+      super();
+    }
+    
+    override protected function measure():void
+    {
+      super.measure();
+      //sovled on forum by Flex HarUI
+      measuredHeight = measureHeightOfItems() + viewMetrics.top + viewMetrics.bottom;
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/views/NoteRenderer.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/views/NoteRenderer.mxml
new file mode 100755
index 0000000000000000000000000000000000000000..a6e98787075ad10cbe3e7230f7d7d19c278b42d6
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/views/NoteRenderer.mxml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  BigBlueButton open source conferencing system - http://www.bigbluebutton.org
+  
+  Copyright (c) 2010 BigBlueButton Inc. and by respective authors (see below).
+  
+  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 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/>.
+ 
+  $Id: $
+-->
+
+<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" verticalAlign="top" styleName="noteRendererStyle"
+		 verticalScrollPolicy="off" xmlns:common="org.bigbluebutton.common.*" dataChange="validateNow()"
+		 creationComplete="onCreationComplete()">
+	
+	<mx:Script>
+		<![CDATA[
+      import mx.binding.utils.ChangeWatcher;
+      
+      import org.bigbluebutton.common.LogUtil;
+      import org.bigbluebutton.modules.notes.models.Note;
+
+			[Bindable] private var rolledOver:Boolean = false;					
+			[Bindable] private var note:Note;
+
+			
+			private function onCreationComplete():void{
+				/** Register a change handler as the renderer get recycled. If we don't
+				 * do this, we'll get a stale data which will display the chat 
+				 * message repeatedly. (ralam Nov 1, 2010)
+				 */
+				ChangeWatcher.watch(this, "data", dataChangeHandler);
+				if (data != null) {
+					note = data as Note;
+					data = null;	
+				}
+				
+				validateNow();
+			}
+			
+			private function dataChangeHandler(e:Event = null):void{
+				if (data == null) {
+					return;
+				}				
+				note = data as Note;
+				data = null;
+			}
+			
+
+						
+		]]>
+	</mx:Script>
+	
+  <mx:HBox width="100%" height="15" styleName="noteRendererTimestampStyle">
+    <mx:Text id="timestamp" htmlText="{note.timestamp}" textAlign="left" color="gray"  width="100%"/>      
+  </mx:HBox> 
+  <mx:HBox width="100%" styleName="noteRendererTextStyle">
+    <mx:Spacer width="5"/>
+    <mx:Text id="lblTime" htmlText="{note.note}" textAlign="left" color="gray"  width="100%"/>       
+  </mx:HBox> 
+</mx:VBox>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/views/NotesView.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/views/NotesView.mxml
new file mode 100755
index 0000000000000000000000000000000000000000..25f610482fd196868ca78fe55a24f12328c55cbc
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/views/NotesView.mxml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" 	
+         xmlns:notes="org.bigbluebutton.modules.notes.views.*"
+         width="100%" height="100%"
+         verticalScrollPolicy="off"
+         creationComplete="onCreationComplete()">
+  
+  <mx:Style>
+    .notesColorPickerStyle {
+      backgroundColor:#E5E6E7;
+      columnCount:12;
+      horizontalGap:0;
+      previewHeight:22;
+      previewWidth:45;
+      swatchGridBackgroundColor:#000000;
+      swatchGridBorderSize:0;
+      swatchHeight:60;
+      swatchHighlightColor:#FFFFFF;
+      swatchHighlightSize:1;
+      swatchWidth:12;
+      textFieldWidth:72;
+      verticalGap:0;
+    }
+    
+  </mx:Style>
+   
+  <mx:Script>
+    <![CDATA[
+      import com.adobe.utils.StringUtil;
+      
+      import org.bigbluebutton.modules.notes.events.SaveNoteEvent;
+      import org.bigbluebutton.modules.notes.models.NotesModel;
+      import org.bigbluebutton.util.i18n.ResourceUtil;
+      
+      [Bindable] public var colorPickerColours:Array = ['0x000000', '0x7A7A7A' ,'0xFF0000', '0xFF8800',
+        '0x88FF00', '0x00FF00', '0x00FF88', '0x00FFFF', '0x0088FF', '0x0000FF', '0x8800FF', '0xFF00FF'];
+      
+      [Bindable]
+      public var notesArray:NotesModel;
+      
+      private function onCreationComplete():void {    
+        // Listen for the ENTER key to send the message.
+        txtMsgArea.addEventListener(KeyboardEvent.KEY_UP, handleTextAreaKeyUpEvent);
+      }
+      
+      private function handleTextAreaKeyUpEvent(e:KeyboardEvent):void {
+        if (e.keyCode == Keyboard.ENTER) {
+          saveNote();
+        }        
+      }
+      
+      private function sendNoteToSave(note:String):void {
+        var saveEvent:SaveNoteEvent = new SaveNoteEvent();
+        saveEvent.note = note;
+        dispatchEvent(saveEvent);
+      }
+      
+      private function saveNote():void {
+        // Trim the message. This will trim the '/n' char so we don't send a message when the
+        // user just hits the enter key
+        var noteToSave:String = StringUtil.trim(txtMsgArea.text);
+        
+        if (noteToSave != ""){								
+          sendNoteToSave(noteToSave);
+        }
+        
+        txtMsgArea.text = "";        
+      }
+ 
+      //color="{cmpColorPicker.selectedColor}"
+    ]]>
+    
+  </mx:Script>
+  
+  <mx:HBox width="100%" height="100%" verticalScrollPolicy="off">
+    <notes:AdvancedList width="100%" height="100%" id="notesMessagesList" selectable="false" 
+                       variableRowHeight="true" alternatingItemColors="[#EFEFEF, #FEFEFE]"
+                       itemRenderer="org.bigbluebutton.modules.notes.views.NoteRenderer"
+                       dataProvider="{notesArray.notes}"
+                       verticalScrollPolicy="auto" wordWrap="true"/>    
+  </mx:HBox>
+  
+  <mx:HBox id="notesCtrlBar" width="100%" height="55" styleName="notesControlBarStyle" 
+           paddingLeft="5" paddingRight="5" verticalScrollPolicy="off">		
+    <mx:TextArea id="txtMsgArea" width="100%"   
+                 styleName="notesControlBarTextMsgStyle" 
+                 toolTip="{ResourceUtil.getInstance().getString('bbb.accessibility.notes.notesview.input')}"/>
+    <mx:VBox verticalScrollPolicy="off">
+      <mx:Button label="{ResourceUtil.getInstance().getString('bbb.notes.saveBtn')}" id="saveBtn" 
+                 styleName="notesControlBarSendButtonStyle"
+                 toolTip="{ResourceUtil.getInstance().getString('bbb.notes.saveBtn.toolTip')}" 
+                 click="saveNote()"/>  
+      <!--
+      <mx:ColorPicker id="cmpColorPicker" showTextField="false" 
+                      toolTip="{ResourceUtil.getInstance().getString('bbb.notes.cmpColorPicker.toolTip')}" 
+                      selectedColor="0x000000" dataProvider="{colorPickerColours}" swatchPanelStyleName="notesColorPickerStyle"/>
+      -->
+    </mx:VBox>
+  </mx:HBox>
+</mx:VBox>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/notes/views/NotesWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/views/NotesWindow.mxml
new file mode 100755
index 0000000000000000000000000000000000000000..4c592e471844b5b8936844458456e0f44ea0ca65
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/notes/views/NotesWindow.mxml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ns:MDIWindow xmlns:mx="http://www.adobe.com/2006/mxml" 
+              xmlns:ns="http://code.google.com/p/flexlib/" 
+              xmlns:views="org.bigbluebutton.modules.notes.views.*"
+              implements="org.bigbluebutton.common.IBbbModuleWindow" 
+              title="Notes"
+              creationComplete="onCreationComplete()"
+              layout="absolute">
+  <mx:Script>
+    <![CDATA[
+      import org.bigbluebutton.modules.notes.models.NotesModel;
+      import org.bigbluebutton.modules.notes.models.NotesOptions;
+      import org.bigbluebutton.util.i18n.ResourceUtil;
+      
+      [Bindable]
+      public var notesModel:NotesModel;
+      
+      public function getPrefferedPosition():String{
+        var options:NotesOptions = new NotesOptions();
+        return options.position;
+      } 
+      
+      private function onCreationComplete():void {
+        this.title = ResourceUtil.getInstance().getString("bbb.notes.title");
+      }
+    ]]>
+  </mx:Script>
+  
+  <views:NotesView id="notesView" notesArray="{notesModel}"/>
+</ns:MDIWindow>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/PhoneManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/PhoneManager.as
index 43d8760fc599d7addd3e8eb1c40168267d7c63bd..25749eff383e9695be696487cffbcf274ba159f1 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/PhoneManager.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/PhoneManager.as
@@ -20,7 +20,9 @@
 package org.bigbluebutton.modules.phone.managers {
 	import com.asfusion.mate.events.Dispatcher;
 	
+	import flash.events.StatusEvent;
 	import flash.media.Microphone;
+	import flash.system.Security;
 	
 	import org.bigbluebutton.common.LogUtil;
 	import org.bigbluebutton.core.BBB;
@@ -41,7 +43,7 @@ package org.bigbluebutton.modules.phone.managers {
 		private var rejoining:Boolean = false;
 		// User has requested to leave the voice conference.
 		private var userHangup:Boolean = false;
-		
+		private var mic:Microphone;
 		
 		public function PhoneManager() {
 			connectionManager = new ConnectionManager();
@@ -60,10 +62,15 @@ package org.bigbluebutton.modules.phone.managers {
 			
 			if (phoneOptions.autoJoin) {
 				if (phoneOptions.skipCheck || noMicrophone()) {
-					if (noMicrophone()) {
+					mic = Microphone.getMicrophone();
+					
+					if (mic == null) {
 						joinVoice(false);
+					} else if (mic.muted) {
+						Security.showSettings();
+						mic.addEventListener(StatusEvent.STATUS, micStatusEventHandler);
 					} else {
-						joinVoice(true);						
+						joinVoice(true);
 					}
 				} else {
 					var dispatcher:Dispatcher = new Dispatcher();
@@ -72,6 +79,21 @@ package org.bigbluebutton.modules.phone.managers {
 			}
 		}
 
+		private function micStatusEventHandler(event:StatusEvent):void {					
+			switch(event.code) {
+				case "Microphone.Muted":
+					LogUtil.warn("Access to microphone has been denied.");
+					joinVoice(false);
+					break;
+				case "Microphone.Unmuted":
+					LogUtil.debug("Access to the microphone has been allowed.");
+					joinVoice(true);
+					break;
+				default:
+					LogUtil.debug("unknown micStatusHandler event: " + event);
+			}
+		}			
+		
 		private function noMicrophone():Boolean {
 			return ((Microphone.getMicrophone() == null) || (Microphone.names.length == 0) 
 				|| ((Microphone.names.length == 1) && (Microphone.names[0] == "Unknown Microphone")));
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/views/components/ToolbarButton.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/views/components/ToolbarButton.mxml
index d34ac06fff56779db38aa778c477c5e8e9717038..c7fc7683cc7738b729afae8c9ddc3b4e1715c69e 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/views/components/ToolbarButton.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/views/components/ToolbarButton.mxml
@@ -46,7 +46,7 @@
 			
 			private var images:Images = new Images();
 			private var dispatcher:Dispatcher = new Dispatcher();
-
+			private var mic:Microphone;
 			
 			public const DEFAULT_STATE:Number = 0;
 			public const ACTIVE_STATE:Number = 1;
@@ -67,17 +67,32 @@
 						phoneOptions.autoJoin = (vxml.@autoJoin.toString().toUpperCase() == "TRUE") ? true : false;
 						phoneOptions.skipCheck = (vxml.@skipCheck.toString().toUpperCase() == "TRUE") ? true : false;
 					}
+          
+          var joinEvent:BBBEvent;
+          
 					if (phoneOptions.skipCheck || noMicrophone()) {
+						// need to figure out if the user has a mic and if they do if it's muted ask for access
+						mic = Microphone.getMicrophone();
 						
-						/*
-						 * If the user had no mic, let her join but she'll just be listening.	
-						 * We should indicate a warning that the user is joining without mic
-						 * so that he will know that others won't be able to hear him.
-						*/
-						var joinEvent:BBBEvent = new BBBEvent("JOIN_VOICE_CONFERENCE_EVENT");
-						joinEvent.payload['useMicrophone'] = true;
-						dispatcher.dispatchEvent(joinEvent);
-						
+						if (mic == null) {
+							/*
+							 * If the user had no mic, let her join but she'll just be listening.	
+							 * We should indicate a warning that the user is joining without mic
+							 * so that he will know that others won't be able to hear him.
+							*/
+							joinEvent = new BBBEvent("JOIN_VOICE_CONFERENCE_EVENT");
+							joinEvent.payload['useMicrophone'] = false;
+							dispatcher.dispatchEvent(joinEvent);
+						} else if (mic.muted) {
+  							// user has disallowed access to the mic
+  							mic.addEventListener(StatusEvent.STATUS, micStatusEventHandler);
+  							Security.showSettings();
+						} else {
+							// user has allowed access to the mic already
+						  joinEvent = new BBBEvent("JOIN_VOICE_CONFERENCE_EVENT");
+							joinEvent.payload['useMicrophone'] = true;
+							dispatcher.dispatchEvent(joinEvent);
+					  }						
 					} else {
 						dispatcher.dispatchEvent(new BBBEvent("SHOW_MIC_SETTINGS"));
 					}
@@ -89,6 +104,26 @@
 				}
 			}
 			
+			private function micStatusEventHandler(event:StatusEvent):void {				
+        var joinEvent:BBBEvent;
+				switch(event.code) {
+					case "Microphone.Muted":						
+						LogUtil.warn("Access to microphone has been denied.");
+						joinEvent = new BBBEvent("JOIN_VOICE_CONFERENCE_EVENT");
+						joinEvent.payload['useMicrophone'] = false;
+						dispatcher.dispatchEvent(joinEvent);
+						break;
+					case "Microphone.Unmuted":
+						LogUtil.debug("Access to the microphone has been allowed.");
+						joinEvent = new BBBEvent("JOIN_VOICE_CONFERENCE_EVENT");
+						joinEvent.payload['useMicrophone'] = true;
+						dispatcher.dispatchEvent(joinEvent);
+						break;
+					default:
+						LogUtil.debug("unknown micStatusHandler event: " + event);
+				}
+			}			
+			
 			private function mouseOverHandler(event:MouseEvent):void {
 				if(_currentState == ACTIVE_STATE)
 					phoneIcon = images.headsetInactiveIcon;
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/FileUploadWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/FileUploadWindow.mxml
index dd8dd1480296a4f8f5dbe43a1c39954c55c990ac..d0a9151e56d49f886f2e34a6c438995a51535ab8 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/FileUploadWindow.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/FileUploadWindow.mxml
@@ -65,7 +65,7 @@
 			private var images:Images = new Images();
 			[Bindable] private var addIcon : Class = images.add;
 			[Bindable] private var bulletGoIcon : Class = images.bulletGo;
-			[Bindable] private var deleteIcon : Class = images.delete_icon;
+			[Bindable] private var deleteIcon : Class = images.cancel;
 	        
 	        private var thumbnailTimer:Timer = new Timer(5000);
 	        private var genThumbText:String = ResourceUtil.getInstance().getString('bbb.fileupload.genThumbText');
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/PresentationWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/PresentationWindow.mxml
index 4e8c78f8aa0a7108e0a09333c88e6137653558ae..28b5546dbd8d8c5f97fc545da3cbe4219cafedd7 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/PresentationWindow.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/PresentationWindow.mxml
@@ -27,12 +27,12 @@
 	xmlns:code="http://code.google.com/p/flexlib/" 
 	xmlns:containers="flexlib.containers.*"
 	xmlns:mate="http://mate.asfusion.com/"
-	paddingBottom="0" paddingTop="0" paddingLeft="0" paddingRight="0" 
 	showCloseButton="false" layout="absolute"
 	verticalScrollPolicy="off" 
 	horizontalScrollPolicy="off" 
 	showControls="true" resize="maximizeHandler()"
-	backgroundColor="#efefef"
+  styleNameFocus="presentationWindowStyleFocus"
+  styleNameNoFocus="presentationWindowStyleNoFocus"
 	implements="org.bigbluebutton.common.IBbbModuleWindow"
 	creationComplete="onCreationComplete()" 
 	width="{DEFAULT_WINDOW_WIDTH}" height="{DEFAULT_WINDOW_HEIGHT}" 
@@ -55,11 +55,9 @@
 	
 	<mx:Script>
 		<![CDATA[
-			import flash.geom.Point;
-			
+			import flash.geom.Point;			
 			import flexlib.containers.DockableToolBar;
-			import flexlib.mdi.events.MDIWindowEvent;
-			
+			import flexlib.mdi.events.MDIWindowEvent;			
 			import mx.binding.utils.BindingUtils;
 			import mx.collections.ArrayCollection;
 			import mx.containers.TitleWindow;
@@ -68,8 +66,7 @@
 			import mx.events.ListEvent;
 			import mx.events.ResizeEvent;
 			import mx.managers.PopUpManager;
-			import mx.rpc.events.*;
-			
+			import mx.rpc.events.*;			
 			import org.bigbluebutton.common.IBbbCanvas;
 			import org.bigbluebutton.common.Images;
 			import org.bigbluebutton.common.LogUtil;
@@ -93,21 +90,13 @@
 			import org.bigbluebutton.modules.present.managers.SlideManager;
 			import org.bigbluebutton.util.i18n.ResourceUtil;
              			
-            public static const TITLE:String = "Presentation";
+      public static const TITLE:String = "Presentation";
 			private static const NEXT_BUTTON:String = "Next";
 			private static const PREVIOUS_BUTTON:String = "Previous";
-			private static const GOTO_PAGE_BUTTON:String = "Go to Page..."
-			
-			private var images:Images = new Images();
-
-			[Bindable] private var uploadIcon:Class = images.upload;
-			[Bindable] private var forwardIcon:Class = images.forward;
-			[Bindable] private var backwardIcon:Class = images.backward;
-			[Bindable] private var magnifierIcon:Class = images.magnifier;
-			[Bindable] public var fitToWidthIcon:Class = images.fitToWidth;
-			[Bindable] public var fitToPageIcon:Class = images.fitToPage;
+			private static const GOTO_PAGE_BUTTON:String = "Go to Page...";
 						
-			[Bindable] private var thumbY:Number;
+			[Bindable] 
+      private var thumbY:Number;
 			public var uploadWindow:FileUploadWindow = null;
 			private var slideManager:SlideManager = new SlideManager();
 			private var pageDialog:GotoPageDialog;
@@ -496,6 +485,10 @@
 				slideView.switchToFitToPage(fitToPage);
 				fitSlideToWindowMaintainingAspectRatio();				
 			}
+      
+      private function onUploadButtonClicked():void {
+        dispatchEvent(new UploadEvent(UploadEvent.OPEN_UPLOAD_WINDOW));
+      }
 			          
 		]]>
 	</mx:Script>
@@ -503,32 +496,32 @@
 	<mx:Fade id="thumbFadeIn" alphaFrom="1" alphaTo="0" duration="100" />
 	<mx:Fade id="thumbFadeOut" alphaFrom="0" alphaTo="1" duration="100" />
 
-	<views:SlideView id="slideView" width="100%" height="100%" visible="false" mouseDown="mouseDown = true" backgroundColor="#efefef"
+	<views:SlideView id="slideView" width="100%" height="100%" visible="false" mouseDown="mouseDown = true"
 			 mouseUp="mouseDown = false" verticalScrollPolicy="off" horizontalScrollPolicy="off" />			    
-    <mx:ApplicationControlBar id="presCtrlBar" width="100%" height="{CONTROL_BAR_HEIGHT}">
-    	  <mx:Button id="uploadPres" icon="{uploadIcon}" visible="false" width="25" height="25"
+  <mx:ControlBar id="presCtrlBar" width="100%" height="{CONTROL_BAR_HEIGHT}" styleName="presentationWindowControlsStyle" >
+    	  <mx:Button id="uploadPres" visible="false" width="25" height="25" styleName="presentationUploadButtonStyle"
     	   		toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.uploadPresBtn.toolTip')}" 
-    	   		click="dispatchEvent(new UploadEvent(UploadEvent.OPEN_UPLOAD_WINDOW))"/>        	  
+    	   		click="onUploadButtonClicked()"/>        	  
     	  <mx:Spacer width="50%" id="spacer1"/>
-    	  <mx:Button id="backButton" icon="{backwardIcon}" visible="false" width="30" height="20"
+    	  <mx:Button id="backButton" visible="false" width="30" height="20" styleName="presentationBackButtonStyle"
     	   		toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.backBtn.toolTip')}" click="gotoPreviousSlide()"/>
     	  <mx:Button id="btnSlideNum" visible="false" label="" click="showThumbnails()" doubleClick="showPageDialog()" 
 					 toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.slideNumLbl.toolTip')}"/>
-    	  <mx:Button id="forwardButton" icon="{forwardIcon}" visible="false" width="30" height="20"
+    	  <mx:Button id="forwardButton" visible="false" width="30" height="20" styleName="presentationForwardButtonStyle"
     	   		toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.forwardBtn.toolTip')}" click="gotoNextSlide()"/>    				
 		<mx:Spacer width="10%" id="spacer2"/>
     	 
-		<mx:HSlider id="zoomSlider" visible="false" value="{slideView.zoomPercentage}"
+		<mx:HSlider id="zoomSlider" visible="false" value="{slideView.zoomPercentage}" styleName="presentationZoomSliderStyle"
     		minimum="100" maximum="400" dataTipPlacement="top" labels="['100%','400%']" 
     		useHandCursor="true" snapInterval="5" allowTrackClick="true" liveDragging="true" 
     		dataTipFormatFunction="removeDecimalFromDataTip" change="onSliderZoom()" width="100"/>
     	<mx:Spacer width="50%" id="spacer3"/>
-    	<mx:Button id="btnFitToWidth" icon="{fitToWidthIcon}" visible="false" width="25" height="25" 
+    	<mx:Button id="btnFitToWidth" visible="false" width="25" height="25" styleName="presentationFitToWidthButtonStyle"
 				   toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.fitToWidth.toolTip')}" 
 				   click="onFitToPage(false)"/>
-		<mx:Button id="btnFitToPage" icon="{fitToPageIcon}" visible="false" width="25" height="25" 
+		<mx:Button id="btnFitToPage" visible="false" width="25" height="25" styleName="presentationFitToPageButtonStyle"
 				   toolTip="{ResourceUtil.getInstance().getString('bbb.presentation.fitToPage.toolTip')}" 
 				   click="onFitToPage(true)"/>
     	<mx:Spacer width="5" id="spacer4"/>
-    </mx:ApplicationControlBar>
+    </mx:ControlBar>
 </pres:MDIWindow>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/SlideView.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/SlideView.mxml
index f29cb3915ccd7f4e945514fb76387728fbdbd6a1..c737579e7dc4315c294dc60dfc0bda935e3ca985 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/SlideView.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/SlideView.mxml
@@ -29,7 +29,7 @@
     creationComplete="onCreationComplete()" 
 	verticalScrollPolicy="off" 
 	horizontalScrollPolicy="off"      
-    rollOut="hideCursor()"
+    rollOut="hideCursor()" styleName="presentationSlideViewStyle"
     xmlns:views="org.bigbluebutton.modules.present.views.*"
     implements="org.bigbluebutton.common.IBbbCanvas">
     
@@ -487,7 +487,7 @@
 		]]>
 	</mx:Script>
 	<fimage:FocusableImage id="slideLoader" width="{slideModel.loaderW}" height="{slideModel.loaderH}" x="{slideModel.loaderX}" y="{slideModel.loaderY}" useHandCursor="true" buttonMode="true"
-		creationComplete="listenForSlideLoadedCompleteEvent()" scaleContent="false" showBusyCursor="true" completeEffect="Fade" />
+		creationComplete="listenForSlideLoadedCompleteEvent()" styleName="presentationSlideViewStyle" scaleContent="false" showBusyCursor="true" completeEffect="Fade" />
 	
    		
     <mx:HorizontalList id="thumbnailView" itemRenderer="org.bigbluebutton.modules.present.ui.views.Thumbnail" itemRollOver="changeIndex(event)" 
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/models/SlideViewModel.as b/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/models/SlideViewModel.as
index 7dacbf9ecea7424f5ce231949cbaa081e5a79ad7..046c1a7868d7d66700efd7d66ead93cbdc2d6ec9 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/models/SlideViewModel.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/models/SlideViewModel.as
@@ -202,7 +202,9 @@ package org.bigbluebutton.modules.present.ui.views.models
 				}					
 			} else {
 				if (viewportW < pageOrigW) {
-					viewportH = (viewportW/pageOrigW)*pageOrigH;
+					if (_calcPageH < viewportH) {
+						viewportH = (viewportW/pageOrigW)*pageOrigH;
+					}
 				}
 			}		
 		}	
@@ -287,7 +289,7 @@ package org.bigbluebutton.modules.present.ui.views.models
 				viewportH = (vrhp/vrwp)*parentW;				 
 				if (parentH < viewportH) {
 					viewportH = parentH;
-					viewportW = ((vrwp * viewportH)/viewportH);
+					viewportW = ((vrwp * viewportH)/vrhp);
 //					LogUtil.debug("calc viewport ***** resizing [" + viewportW + "," + viewportH + "] [" + parentW + "," + parentH + "," + fitToPage + "] [" + pageOrigW + "," + pageOrigH + "]");
 				}
 			} else {
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/business/VideoProxy.as b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/business/VideoProxy.as
index 740571ab3f97e99e76cc293d14d0ea7b02d1795f..b502ae93886138c018e7254fed4ba691f68c444a 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/business/VideoProxy.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/business/VideoProxy.as
@@ -18,12 +18,14 @@
 */
 package org.bigbluebutton.modules.videoconf.business
 {
-	import com.asfusion.mate.events.Dispatcher;
-	
+	import com.asfusion.mate.events.Dispatcher;	
 	import flash.events.AsyncErrorEvent;
 	import flash.events.IOErrorEvent;
 	import flash.events.NetStatusEvent;
 	import flash.events.SecurityErrorEvent;
+	import flash.media.H264Level;
+	import flash.media.H264Profile;
+	import flash.media.H264VideoStreamSettings;
 	import flash.net.NetConnection;
 	import flash.net.NetStream;
 	import flash.system.Capabilities;
@@ -31,19 +33,14 @@ package org.bigbluebutton.modules.videoconf.business
 	import mx.collections.ArrayCollection;
 	
 	import org.bigbluebutton.common.LogUtil;
-	import org.bigbluebutton.core.managers.UserManager;
 	import org.bigbluebutton.core.BBB;
+	import org.bigbluebutton.core.managers.UserManager;
 	import org.bigbluebutton.main.model.users.BBBUser;
 	import org.bigbluebutton.main.model.users.events.StreamStartedEvent;
+	import org.bigbluebutton.modules.videoconf.events.ConnectedEvent;
 	import org.bigbluebutton.modules.videoconf.events.StartBroadcastEvent;
 	import org.bigbluebutton.modules.videoconf.model.VideoConfOptions;
 
-// Uncomment if you want to build support for H264. But you need at least FP 11. (ralam july 23, 2011)		
-	 
- 	 import flash.media.H264VideoStreamSettings;
-	 import flash.media.H264Profile;
-	 import flash.media.H264Level;
-
 	
 	public class VideoProxy
 	{		
@@ -51,7 +48,8 @@ package org.bigbluebutton.modules.videoconf.business
 		
 		private var nc:NetConnection;
 		private var ns:NetStream;
-		
+		private var _url:String;
+    
 		private function parseOptions():void {
 			videoOptions = new VideoConfOptions();
 			videoOptions.parseOptions();	
@@ -59,66 +57,40 @@ package org.bigbluebutton.modules.videoconf.business
 		
 		public function VideoProxy(url:String)
 		{
-			parseOptions();
-			
+      _url = url;
+			parseOptions();			
 			nc = new NetConnection();
 			nc.client = this;
 			nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
 			nc.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
 			nc.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
 			nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
-			nc.connect(url);
+			
 		}
 		
+    public function connect():void {
+      nc.connect(_url);
+    }
+    
 		private function onAsyncError(event:AsyncErrorEvent):void{
 		}
 		
 		private function onIOError(event:NetStatusEvent):void{
 		}
 		
+    private function onConnectedToVideoApp():void{
+      var dispatcher:Dispatcher = new Dispatcher();
+      dispatcher.dispatchEvent(new ConnectedEvent(ConnectedEvent.VIDEO_CONNECTED));
+    }
+    
 		private function onNetStatus(event:NetStatusEvent):void{
 			switch(event.info.code){
-				case "NetConnection.Connect.Failed":
-					break;
 				case "NetConnection.Connect.Success":
 					ns = new NetStream(nc);
-					openAvailableVideos();
-					break;
-				case "NetConnection.Connect.Rejected":
-					break;
-				case "NetConnection.Connect.Closed":
-					break;
-				case "NetConnection.Connect.InvalidApp":
+          onConnectedToVideoApp();
 					break;
-				case "NetConnection.Connect.AppShutdown":
-					break;
-					
-				case "NetStream.Publish.Start":
-					LogUtil.debug("NetStream.Publish.Start for broadcast stream [");
-					break;
-					
-				case "NetStream.Publish.Idle":
-					LogUtil.debug("NetStream.Publish.Idle for broadcast stream [");
-					break;
-					
-				case "NetStream.Record.Failed":
-					LogUtil.debug("NetStream.Record.Failed for broadcast stream [");
-					break;
-					
-				case "NetStream.Record.Stop":
-					LogUtil.debug("NetStream.Record.Stop for broadcast stream [");
-					break;
-					
-				case "NetStream.Record.Start":
-					LogUtil.debug("NetStream.Record.Start for broadcast stream [");
-					break;
-					
-				case "NetStream.Unpublish.Success":
-					LogUtil.debug("NetStream.Unpublish.Success for broadcast stream [");
-					break;
-					
-				case "NetStream.Publish.BadName":
-					LogUtil.debug("NetStream.Publish.BadName for broadcast stream [");
+        default:
+					LogUtil.debug("[" + event.info.code + "] for [" + _url + "]");
 					break;
 			}
 		}
@@ -215,13 +187,6 @@ package org.bigbluebutton.modules.videoconf.business
 			trace("bandwidth = " + p_bw + " Kbps."); 
 		}
 		
-		public function openAvailableVideos():void{
-			var dispatcher:Dispatcher = new Dispatcher();
-			var users:ArrayCollection = UserManager.getInstance().getConference().users;
-			for (var i:int = 0; i < users.length; i++){
-				var user:BBBUser = (users.getItemAt(i) as BBBUser);
-				if (user.hasStream) dispatcher.dispatchEvent(new StreamStartedEvent(user.userID, user.name, user.streamName));
-			}
-		}
+
 	}
 }
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/business/VideoWindowItf.as b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/business/VideoWindowItf.as
index a16756cfb053830031986d0551d6ea918057858c..b3d071bfa26806e247d5d719723126cf2ae9a7a7 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/business/VideoWindowItf.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/business/VideoWindowItf.as
@@ -68,13 +68,19 @@ package org.bigbluebutton.modules.videoconf.business
 		protected var mousePositionOnDragStart:Point;
 		
 		public var streamName:String;
-
-    protected var _sharerUserID:String = null;
+    
+    private var windowType:String = "VideoWindowItf";
+    
+    public var userID:String = null;
 
     protected var _controlButtons:ControlButtons = new ControlButtons();
 		
     [Bindable] public var resolutions:Array;
-		
+
+    public function getWindowType():String {
+      return windowType;
+    }
+    
     protected function switchRole(presenter:Boolean):void {
       _controlButtons.handleNewRoleEvent(presenter);
     }
@@ -86,7 +92,7 @@ package org.bigbluebutton.modules.videoconf.business
         var uid:String = UserManager.getInstance().getConference().getMyUserId();
         LogUtil.debug("Stream resolution is [" + pattern.exec(stream)[1] + "]");
         LogUtil.debug("Userid [" + pattern.exec(stream)[2] + "]");
-        _sharerUserID = pattern.exec(stream)[2];
+        userID = pattern.exec(stream)[2];
         addControlButtons();
         return pattern.exec(stream)[1].split("x");
 			} else {
@@ -212,27 +218,7 @@ package org.bigbluebutton.modules.videoconf.business
 				// the window is docked, so it should not be moved on reset layout
 				return MainCanvas.ABSOLUTE;
 		}
-		
-		public function onDrag(event:MDIWindowEvent = null):void {
-			var e:DragWindowEvent = new DragWindowEvent(DragWindowEvent.DRAG);
-			e.mouseGlobal = this.localToGlobal(new Point(mouseX, mouseY));
-			e.window = this;
-			dispatchEvent(e);
-		}
-		
-		public function onDragStart(event:MDIWindowEvent = null):void {
-			var e:DragWindowEvent = new DragWindowEvent(DragWindowEvent.DRAG_START);
-			e.window = this;
-			dispatchEvent(e);
-		}
-		
-		public function onDragEnd(event:MDIWindowEvent = null):void {
-			var e:DragWindowEvent = new DragWindowEvent(DragWindowEvent.DRAG_END);
-			e.mouseGlobal = this.localToGlobal(new Point(mouseX, mouseY));
-			e.window = this;
-			dispatchEvent(e);
-		}
-		
+			
 		override public function close(event:MouseEvent = null):void{
 			var e:CloseWindowEvent = new CloseWindowEvent();
 			e.window = this;
@@ -240,42 +226,27 @@ package org.bigbluebutton.modules.videoconf.business
 			
 			super.close(event);
 		}
-		
-//		private var _controlButtons:ControlButtonsOverlay = null;
-    
+		   
 		private var _controlButtonsEnabled:Boolean = true;
 		
 		private var img_unlock_keep_aspect:Class = images.lock_open;
 		private var img_lock_keep_aspect:Class = images.lock_close;
 		private var img_fit_video:Class = images.arrow_in;
 		private var img_original_size:Class = images.shape_handles;
-		private var img_mute_icon:Class = images.sound_mute;
-    private var signOutIcon:Class = images.signOutIcon;
-    private var adminIcon:Class = images.admin;
-    private var chatIcon:Class = images.chatIcon;
+		private var img_mute_icon:Class = images.webcam_mute;
+    private var signOutIcon:Class = images.webcam_kickuser;
+    private var adminIcon:Class = images.webcam_make_presenter;
+    private var chatIcon:Class = images.webcam_private_chat;
     
     protected function addControlButtons():void {
-      _controlButtons.sharerUserID = _sharerUserID;
+      _controlButtons.sharerUserID = userID;
       _controlButtons.visible = true;
       this.addChild(_controlButtons);
     }
     
 		protected function get controlButtons():ControlButtons {
-			if (_controlButtons == null) {
-				
-        
-//				_controlButtons.add("originalSizeBtn", img_original_size, ResourceUtil.getInstance().getString('bbb.video.originalSizeBtn.tooltip'), onOriginalSizeClick);
-//        _controlButtons.add("muteUnmuteBtn", img_mute_icon, "mute / unmute", onMuteUnmuteClicked);
-//        _controlButtons.add("switchPresenter", adminIcon, "switch presenter", onSwitchPresenterClicked);
-//        _controlButtons.add("ejectUserBtn", signOutIcon, "eject user", onKickUserClicked);
-//        _controlButtons.add("privateChatBtn", chatIcon, "Start private chat", onPrivateChatClicked);
-//        
-				// hiding the other buttons
-				//_buttons.add("keepAspectBtn", img_lock_keep_aspect, ResourceUtil.getInstance().getString('bbb.video.keepAspectBtn.tooltip'), onKeepAspectClick);
-				//_buttons.add("fitVideoBtn", img_fit_video, ResourceUtil.getInstance().getString('bbb.video.fitVideoBtn.tooltip'), onFitVideoClick);
-				
-				_controlButtons.visible = false;
-								
+			if (_controlButtons == null) {				
+				_controlButtons.visible = false;							
 			} 
 			return _controlButtons;
 		}
@@ -283,6 +254,7 @@ package org.bigbluebutton.modules.videoconf.business
 		protected function createButtons():void {      
 			// creates the window keeping the aspect ratio 
 			onKeepAspectClick();
+      updateButtonsPosition();
 		}
 		
 		protected function updateButtonsPosition():void {
@@ -332,38 +304,7 @@ package org.bigbluebutton.modules.videoconf.business
 			_video.height = _videoHolder.height = originalHeight;
 			onFitVideoClick();
 		}		
-/*		
-    protected function onKickUserClicked(event:MouseEvent = null):void {
-      var gd:Dispatcher = new Dispatcher();
-      gd.dispatchEvent(new KickUserEvent(_sharerUserID)); 
-    }
     
-    protected function onPrivateChatClicked(event:MouseEvent = null):void {
-      var e:CoreEvent = new CoreEvent(EventConstants.START_PRIVATE_CHAT);
-      e.message.chatWith = _sharerUserID;
-      var gd:Dispatcher = new Dispatcher();
-      gd.dispatchEvent(e);
-    }
-       
-    protected function onSwitchPresenterClicked(event:MouseEvent = null):void {
-      var e:RoleChangeEvent = new RoleChangeEvent(RoleChangeEvent.ASSIGN_PRESENTER);
-      e.userid = _sharerUserID;
-      e.username = UsersUtil.getUserName(_sharerUserID);
-      var gd:Dispatcher = new Dispatcher();
-      gd.dispatchEvent(e);     
-    }
-    
-    protected function onMuteUnmuteClicked(event:MouseEvent = null):void {
-      var bu:BBBUser = UsersUtil.getUser(_sharerUserID);
-      if (bu != null) {
-        var e:ListenersCommand = new ListenersCommand(ListenersCommand.MUTE_USER);        
-        e.userid = bu.voiceUserid;
-        e.mute = ! bu.voiceMuted; 
-        var gd:Dispatcher = new Dispatcher();
-        gd.dispatchEvent(e);          
-      }
-    }
-*/    
 		protected function onFitVideoClick(event:MouseEvent = null):void {
 			var newWidth:int = _video.width + paddingHorizontal;
 			var newHeight:int = _video.height + paddingVertical;
@@ -377,20 +318,12 @@ package org.bigbluebutton.modules.videoconf.business
 		
 		protected function onKeepAspectClick(event:MouseEvent = null):void {
 			keepAspect = !keepAspect;
-			
-//			var keepAspectBtn:Button = controlButtons.get("keepAspectBtn");
-//			if (keepAspectBtn != null) { 
-//				keepAspectBtn.selected = keepAspect;
-//				keepAspectBtn.setStyle("icon", (keepAspect? img_lock_keep_aspect: img_unlock_keep_aspect));
-//			}
-			
-//			var fitVideoBtn:Button = controlButtons.get("fitVideoBtn");
-//			if (fitVideoBtn != null) {
-//				fitVideoBtn.enabled = !keepAspect;
-//			}		
-			
+					
 			onFitVideoClick();
 		}
 		
+    protected function userMuted(muted:Boolean):void {
+      _controlButtons.userMuted(muted);
+    }
 	}
 }
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/events/ConnectedEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/events/ConnectedEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..e845323b5889ae5851a776f3ee65b9628e672ded
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/events/ConnectedEvent.as
@@ -0,0 +1,14 @@
+package org.bigbluebutton.modules.videoconf.events
+{
+  import flash.events.Event;
+  
+  public class ConnectedEvent extends Event
+  {
+    public static const VIDEO_CONNECTED:String = "connected to video app event";
+    
+    public function ConnectedEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(type, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/events/ShareCameraRequestEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/events/ShareCameraRequestEvent.as
index aa9ec2bf5dccb9b0d0d1766b345eb9f2e73aac1d..c4fa440bf57f7a69c45822e6054fc462bb7c551e 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/events/ShareCameraRequestEvent.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/events/ShareCameraRequestEvent.as
@@ -24,6 +24,8 @@ package org.bigbluebutton.modules.videoconf.events
 	{
 		public static const SHARE_CAMERA_REQUEST:String = "ShareCameraRequestEvent";
 		
+    public var publishInClient:Boolean = true;
+    
 		public function ShareCameraRequestEvent(type:String = SHARE_CAMERA_REQUEST)
 		{
 			super(type, true, false);
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/events/VideoModuleStartEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/events/VideoModuleStartEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..f0095d63bf5070963edc856ffe5eb720d2d41a91
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/events/VideoModuleStartEvent.as
@@ -0,0 +1,14 @@
+package org.bigbluebutton.modules.videoconf.events
+{
+  import flash.events.Event;
+  
+  public class VideoModuleStartEvent extends Event
+  {
+    public static const START:String = "video module start event";
+    
+    public function VideoModuleStartEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(type, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/events/VideoModuleStopEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/events/VideoModuleStopEvent.as
new file mode 100755
index 0000000000000000000000000000000000000000..86811162f4b9b28a65627bc2b261f5357fdad7e7
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/events/VideoModuleStopEvent.as
@@ -0,0 +1,14 @@
+package org.bigbluebutton.modules.videoconf.events
+{
+  import flash.events.Event;
+  
+  public class VideoModuleStopEvent extends Event
+  {
+    public static const STOP:String = "video module stop event";
+    
+    public function VideoModuleStopEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
+    {
+      super(type, bubbles, cancelable);
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/maps/VideoEventMap.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/maps/VideoEventMap.mxml
index 8d19f2889a33eb148f6f04d843cb58aa00f556c4..762cd326d0f80382e85422c9ecc8acb17b24cfb3 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/maps/VideoEventMap.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/maps/VideoEventMap.mxml
@@ -23,203 +23,94 @@
 <EventMap xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="http://mate.asfusion.com/">
 	<mx:Script>
 		<![CDATA[
-      import mx.collections.ArrayCollection;
-      
-      import org.bigbluebutton.common.LogUtil;
-      import org.bigbluebutton.common.events.OpenWindowEvent;
-      import org.bigbluebutton.common.events.ToolbarButtonEvent;
-      import org.bigbluebutton.core.managers.UserManager;
+      import org.bigbluebutton.core.events.ConnectAppEvent;
       import org.bigbluebutton.main.events.BBBEvent;
       import org.bigbluebutton.main.events.MadePresenterEvent;
-      import org.bigbluebutton.main.model.users.BBBUser;
-      import org.bigbluebutton.main.model.users.events.BroadcastStartedEvent;
-      import org.bigbluebutton.main.model.users.events.BroadcastStoppedEvent;
+      import org.bigbluebutton.main.events.StoppedViewingWebcamEvent;
+      import org.bigbluebutton.main.events.UserJoinedEvent;
+      import org.bigbluebutton.main.events.UserLeftEvent;
       import org.bigbluebutton.main.model.users.events.StreamStartedEvent;
-      import org.bigbluebutton.modules.videoconf.business.VideoProxy;
-      import org.bigbluebutton.modules.videoconf.events.CloseAllWindowsEvent;
       import org.bigbluebutton.modules.videoconf.events.ClosePublishWindowEvent;
-      import org.bigbluebutton.modules.videoconf.events.OpenVideoWindowEvent;
+      import org.bigbluebutton.modules.videoconf.events.ConnectedEvent;
       import org.bigbluebutton.modules.videoconf.events.ShareCameraRequestEvent;
       import org.bigbluebutton.modules.videoconf.events.StartBroadcastEvent;
       import org.bigbluebutton.modules.videoconf.events.StopBroadcastEvent;
-      import org.bigbluebutton.modules.videoconf.views.PublishWindow;
-      import org.bigbluebutton.modules.videoconf.views.ToolbarButton;
-      import org.bigbluebutton.modules.videoconf.views.VideoWindow;
-      import org.bigbluebutton.modules.viewers.events.ViewCameraEvent;
-      import org.flexunit.runner.manipulation.filters.IncludeAllFilter;
-			
-			public var module:VideoconfModule;
-			private var button:ToolbarButton;
-			private var publishWindow:PublishWindow;
-			public var proxy:VideoProxy;
-
-			// This variable is used to avoid dispatching the BroadcastStoppedEvent
-			// when the user just open the publish window and close it before start
-			// publishing
-			private var _publishing:Boolean = false;		
-			
-			private function viewCamera(userid:String, stream:String, name:String, mock:Boolean = false):void {
-        LogUtil.debug("Viewing [" + userid + " stream [" + stream + "]");
-				if (UserManager.getInstance().getConference().amIThisUser(userid)) return;
-				
-				var window:VideoWindow = new VideoWindow();
-//				window.userId = userid;
-				window.videoOptions = proxy.videoOptions;
-				
-				window.resolutions = module.resolutions.split(",");
-				
-				if (mock) {
-					window.startVideo(module.mockConnection, stream);
-				}
-				else {
-					window.startVideo(module.connection, stream);
-				}
-				window.title = name;
-				var windowEvent:OpenWindowEvent = new OpenWindowEvent(OpenWindowEvent.OPEN_WINDOW_EVENT);
-				windowEvent.window = window;
-				globalDispatcher.dispatchEvent(windowEvent);
-				
-				// this event will dock the window, if it's enabled
-				var openVideoEvent:OpenVideoWindowEvent = new OpenVideoWindowEvent();
-				openVideoEvent.window = window;
-				globalDispatcher.dispatchEvent(openVideoEvent);
-			}
-
-			private function viewVideoFile(e:BBBEvent):void {
-				viewCamera("1", e.message, e.message, true);
-			}
-			
-			private function mockConnect():void {
-				module.mockConnect();
-			}
-			
-			public function addToolbarButton():void{
-				if (proxy.videoOptions.showButton) {
-					button = new ToolbarButton();	  
-					button.isPresenter = !module.presenterShareOnly;
-					var event:ToolbarButtonEvent = new ToolbarButtonEvent(ToolbarButtonEvent.ADD);
-					event.button = button;
-					globalDispatcher.dispatchEvent(event);
-				}
-			}
-			
-			private function openPublishWindow():void{
-				publishWindow = new PublishWindow();
-				publishWindow.videoOptions = proxy.videoOptions;
-				publishWindow.userrole = module.role;
-				publishWindow.quality = module.quality;
-				publishWindow.resolutions = module.resolutions.split(",");
-				
-				var windowEvent:OpenWindowEvent = new OpenWindowEvent(OpenWindowEvent.OPEN_WINDOW_EVENT);
-				windowEvent.window = publishWindow;
-				globalDispatcher.dispatchEvent(windowEvent);
-			}
-			
-
-
-			private function closePublishWindow():void{
-				publishWindow.close();
-			}
-
-
-			private function startPublishing(e:StartBroadcastEvent):void{
-			    LogUtil.debug("Publishing stream to: " + proxy.connection.uri + "/" + e.stream);
-				proxy.startPublishing(e);
-				var broadcastEvent:BroadcastStartedEvent = new BroadcastStartedEvent();
-				broadcastEvent.stream = e.stream;
-				broadcastEvent.userid = module.userid;
-				globalDispatcher.dispatchEvent(broadcastEvent);
-				publishWindow.title = module.username + " (you)";
-				_publishing = true;
-				button.publishingStatus(button.START_PUBLISHING);
-
-			}
-			
-			private function stopPublishing(e:StopBroadcastEvent):void{
-				if (_publishing) {
-					proxy.stopBroadcasting();
-					
-					var broadcastEvent:BroadcastStoppedEvent = new BroadcastStoppedEvent();
-					broadcastEvent.stream = publishWindow.streamName;
-					broadcastEvent.userid = module.userid;
-					globalDispatcher.dispatchEvent(broadcastEvent);
-					_publishing = false;
-				}
-				
-				//Make toolbar button enabled again
-
-				button.publishingStatus(button.STOP_PUBLISHING);
-				//button.show();
-			}
-			
-			public function stopModule():void {
-				closeAllWindows();
-				proxy.disconnect();
-			}
-			
-			public function closeAllWindows():void{
-				if (publishWindow != null) {
-					proxy.stopBroadcasting();
-					publishWindow.close();
-				}
-				globalDispatcher.dispatchEvent(new CloseAllWindowsEvent());
-			}
-			
-			private function switchToPresenter():void{
-				if (module.presenterShareOnly){
-					button.isPresenter = true;
-				}
-			}
-			
-			private function switchToViewer():void{
-				if (module.presenterShareOnly){
-					button.isPresenter = false;
-					if (publishWindow != null) publishWindow.close();
-				}
-			}
-			
-			
+      import org.bigbluebutton.modules.videoconf.events.VideoModuleStartEvent;
+      import org.bigbluebutton.modules.videoconf.events.VideoModuleStopEvent;
+      import org.bigbluebutton.modules.viewers.events.ViewCameraEvent;		
 		]]>
 	</mx:Script>
 	
+  <EventHandlers type="{VideoModuleStartEvent.START}">
+    <ObjectBuilder generator="{VideoEventMapDelegate}" cache="global" constructorArguments="{scope.dispatcher}"/>
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="start"/>
+  </EventHandlers>
+ 
+  <EventHandlers type="{VideoModuleStopEvent.STOP}">
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="stop"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{BBBEvent.CAMERA_SETTING}" >
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="handleCameraSetting" arguments="{event}"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{ConnectAppEvent.CONNECT_VIDEO_APP}">
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="connectToVideoApp" />
+  </EventHandlers>
+  
 	<EventHandlers type="{ShareCameraRequestEvent.SHARE_CAMERA_REQUEST}">
-		<InlineInvoker method="openPublishWindow" />
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="handleShareCameraRequestEvent" arguments="{event}"/>
 	</EventHandlers>
 
-	<EventHandlers type="{ClosePublishWindowEvent.CLOSE_PUBLISH_WINDOW}">
-		<InlineInvoker method="closePublishWindow" />
-	</EventHandlers>
-	
 	<EventHandlers type="{StartBroadcastEvent.START_BROADCAST}" >
-		<InlineInvoker method="startPublishing" arguments="{event}" />
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="startPublishing" arguments="{event}" />
 	</EventHandlers>
 	
 	<EventHandlers type="{StopBroadcastEvent.STOP_BROADCASTING}" >
-		<InlineInvoker method="stopPublishing" arguments="{event}" />
-	</EventHandlers>
-	
-	<EventHandlers type="{BBBEvent.START_VIDEO_STREAM}" >
-		<InlineInvoker method="viewVideoFile" arguments="{event}" />
-	</EventHandlers>
-	
-	<EventHandlers type="{BBBEvent.START_VIDEO_CONNECTION}">
-		<InlineInvoker method="mockConnect" />
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="stopPublishing" arguments="{event}" />
 	</EventHandlers>
 	
 	<EventHandlers type="{StreamStartedEvent.STREAM_STARTED}">
-		<InlineInvoker method="viewCamera" arguments="{[event.userID, event.stream, event.user]}" />
+    <ObjectBuilder generator="{VideoEventMapDelegate}" cache="global" constructorArguments="{scope.dispatcher}"/>
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="viewCamera" arguments="{[event.userID, event.stream, event.user]}" />
 	</EventHandlers>
 	
 	<EventHandlers type="{ViewCameraEvent.VIEW_CAMERA_EVENT}">
-		<InlineInvoker method="viewCamera" arguments="{[event.userid, event.stream, event.viewedName]}" />
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="viewCamera" arguments="{[event.userID, event.stream, event.viewedName]}" />
 	</EventHandlers>
-	
+
+  <EventHandlers type="{UserJoinedEvent.JOINED}">
+    <ObjectBuilder generator="{VideoEventMapDelegate}" cache="global" constructorArguments="{scope.dispatcher}"/>
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="handleUserJoinedEvent" arguments="{event}" />
+  </EventHandlers>
+
+  <EventHandlers type="{UserLeftEvent.LEFT}">
+    <ObjectBuilder generator="{VideoEventMapDelegate}" cache="global" constructorArguments="{scope.dispatcher}"/>
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="handleUserLeftEvent" arguments="{event}" />
+  </EventHandlers>
+  
 	<EventHandlers type="{MadePresenterEvent.SWITCH_TO_PRESENTER_MODE}" >
-		<InlineInvoker method="switchToPresenter" />	
+    <ObjectBuilder generator="{VideoEventMapDelegate}" cache="global" constructorArguments="{scope.dispatcher}"/>
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="switchToPresenter" arguments="{event}"/>	
 	</EventHandlers>
 	
 	<EventHandlers type="{MadePresenterEvent.SWITCH_TO_VIEWER_MODE}">
-		<InlineInvoker method="switchToViewer" />
+    <ObjectBuilder generator="{VideoEventMapDelegate}" cache="global" constructorArguments="{scope.dispatcher}"/>
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="switchToViewer" arguments="{event}"/>
 	</EventHandlers>
-	
+
+  <EventHandlers type="{ConnectedEvent.VIDEO_CONNECTED}">
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="connectedToVideoApp" />
+  </EventHandlers>
+ 
+  <EventHandlers type="{ClosePublishWindowEvent.CLOSE_PUBLISH_WINDOW}">
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="handleClosePublishWindowEvent" arguments="{event}"/>
+  </EventHandlers>
+  
+  <EventHandlers type="{StoppedViewingWebcamEvent.STOPPED_VIEWING_WEBCAM}">
+    <MethodInvoker generator="{VideoEventMapDelegate}" method="handleStoppedViewingWebcamEvent"  arguments="{event}"/>
+  </EventHandlers>
+  
+  <!-- ~~~~~~~~~~~~~~~~~~    INJECTORS     ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+  
 </EventMap>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/maps/VideoEventMapDelegate.as b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/maps/VideoEventMapDelegate.as
new file mode 100755
index 0000000000000000000000000000000000000000..59f30fef2408a2c649e65566eb5659e237491f7e
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/maps/VideoEventMapDelegate.as
@@ -0,0 +1,373 @@
+package org.bigbluebutton.modules.videoconf.maps
+{
+  import flash.events.IEventDispatcher;
+  
+  import mx.collections.ArrayCollection;
+  
+  import org.bigbluebutton.common.LogUtil;
+  import org.bigbluebutton.common.events.CloseWindowEvent;
+  import org.bigbluebutton.common.events.OpenWindowEvent;
+  import org.bigbluebutton.common.events.ToolbarButtonEvent;
+  import org.bigbluebutton.core.UsersUtil;
+  import org.bigbluebutton.core.events.ConnectAppEvent;
+  import org.bigbluebutton.core.managers.UserManager;
+  import org.bigbluebutton.core.vo.CameraSettingsVO;
+  import org.bigbluebutton.main.events.BBBEvent;
+  import org.bigbluebutton.main.events.MadePresenterEvent;
+  import org.bigbluebutton.main.events.StoppedViewingWebcamEvent;
+  import org.bigbluebutton.main.events.UserJoinedEvent;
+  import org.bigbluebutton.main.events.UserLeftEvent;
+  import org.bigbluebutton.main.model.users.BBBUser;
+  import org.bigbluebutton.main.model.users.events.BroadcastStartedEvent;
+  import org.bigbluebutton.main.model.users.events.BroadcastStoppedEvent;
+  import org.bigbluebutton.main.model.users.events.StreamStartedEvent;
+  import org.bigbluebutton.modules.videoconf.business.VideoProxy;
+  import org.bigbluebutton.modules.videoconf.business.VideoWindowItf;
+  import org.bigbluebutton.modules.videoconf.events.CloseAllWindowsEvent;
+  import org.bigbluebutton.modules.videoconf.events.ClosePublishWindowEvent;
+  import org.bigbluebutton.modules.videoconf.events.ConnectedEvent;
+  import org.bigbluebutton.modules.videoconf.events.OpenVideoWindowEvent;
+  import org.bigbluebutton.modules.videoconf.events.ShareCameraRequestEvent;
+  import org.bigbluebutton.modules.videoconf.events.StartBroadcastEvent;
+  import org.bigbluebutton.modules.videoconf.events.StopBroadcastEvent;
+  import org.bigbluebutton.modules.videoconf.model.VideoConfOptions;
+  import org.bigbluebutton.modules.videoconf.views.AvatarWindow;
+  import org.bigbluebutton.modules.videoconf.views.PublishWindow;
+  import org.bigbluebutton.modules.videoconf.views.ToolbarButton;
+  import org.bigbluebutton.modules.videoconf.views.VideoWindow;
+  import org.bigbluebutton.modules.viewers.events.ViewCameraEvent;
+  import org.flexunit.runner.manipulation.filters.IncludeAllFilter;
+  
+  public class VideoEventMapDelegate
+  {
+    private var options:VideoConfOptions = new VideoConfOptions();
+    private var webcamWindows:WindowManager = new WindowManager();
+    
+    private var button:ToolbarButton;
+    private var proxy:VideoProxy;
+    private var streamName:String;
+    
+    private var _dispatcher:IEventDispatcher;
+    private var _ready:Boolean = false;
+    private var _isPublishing:Boolean = false;
+    
+    public function VideoEventMapDelegate(dispatcher:IEventDispatcher)
+    {
+      _dispatcher = dispatcher;
+    }
+    
+    private function get me():String {
+      return UsersUtil.getMyUsername();
+    }
+    
+    public function start():void {
+      trace("[" + me + "] Video Module Started.");
+    }
+    
+    public function stop():void {
+      
+    }
+    
+    public function viewCamera(userID:String, stream:String, name:String, mock:Boolean = false):void {
+      trace("[" + me + "] viewCamera. ready = [" + _ready + "]");
+      
+      if (!_ready) return;
+      trace("[" + me + "] Viewing [" + userID + " stream [" + stream + "]");
+      if (! UserManager.getInstance().getConference().amIThisUser(userID)) {
+        openViewWindowFor(userID);			
+      }      
+    }
+
+    public function handleUserLeftEvent(event:UserLeftEvent):void {
+      trace("[" + me + "] handleUserLeftEvent. ready = [" + _ready + "]");
+      
+      if (!_ready) return;
+      
+      closeWindow(event.userID);
+    }
+    
+    public function handleUserJoinedEvent(event:UserJoinedEvent):void {
+      trace("[" + me + "] handleUserJoinedEvent. ready = [" + _ready + "]");
+      
+      if (!_ready) return;
+      
+      if (options.displayAvatar) {
+        openAvatarWindowFor(event.userID);
+      }
+    }
+    
+    private function addToolbarButton():void{
+      if (proxy.videoOptions.showButton) {
+        button = new ToolbarButton();	  
+        button.isPresenter = !options.presenterShareOnly;
+        var event:ToolbarButtonEvent = new ToolbarButtonEvent(ToolbarButtonEvent.ADD);
+        event.button = button;
+        _dispatcher.dispatchEvent(event);
+      }
+    }
+    
+    private function autoStart():void {       
+      _dispatcher.dispatchEvent(new ShareCameraRequestEvent());					       
+    }
+    
+    private function openWebcamWindows():void {
+      trace("[" + me + "] openWebcamWindows:: ready = [" + _ready + "]");
+      
+      var uids:ArrayCollection = UsersUtil.getUserIDs();
+      
+      for (var i:int = 0; i < uids.length; i++) {
+        var u:String = uids.getItemAt(i) as String;
+        trace("[" + me + "] openWebcamWindows:: open window for = [" + u + "]");
+        openWebcamWindowFor(u); 
+      }
+    }
+    
+    private function openWebcamWindowFor(userID:String):void {      
+      trace("[" + me + "] openWebcamWindowFor:: open window for = [" + userID + "]");
+      if (! UsersUtil.isMe(userID) && UsersUtil.hasWebcamStream(userID)) {
+        trace("[" + me + "] openWebcamWindowFor:: Not ME and user = [" + userID + "] is publishing.");
+        
+        if (webcamWindows.hasWindow(userID)) {
+          trace("[" + me + "] openWebcamWindowFor:: user = [" + userID + "] has a window open. Close it.");
+          closeWindow(userID);
+        }
+        trace("[" + me + "] openWebcamWindowFor:: View user's = [" + userID + "] webcam.");
+        openViewWindowFor(userID);
+      } else {
+        if (UsersUtil.isMe(userID) && options.autoStart) {
+          trace("[" + me + "] openWebcamWindowFor:: It's ME and AutoStart. Start publishing.");
+          autoStart();
+        } else {
+          if (options.displayAvatar) {
+            trace("[" + me + "] openWebcamWindowFor:: It's NOT ME and NOT AutoStart. Open Avatar for user = [" + userID + "]");
+            openAvatarWindowFor(userID);              
+          } else {
+            trace("[" + me + "] openWebcamWindowFor:: Is THERE another option for user = [" + userID + "]");
+          }
+        }
+      }
+    }
+    
+    private function openAvatarWindowFor(userID:String):void {      
+      var window:AvatarWindow = new AvatarWindow();
+      window.userID = userID;
+      window.title = UsersUtil.getUserName(userID);
+     
+      trace("[" + me + "] openAvatarWindowFor:: Closing window for [" + userID + "] [" + UsersUtil.getUserName(userID) + "]");
+      closeWindow(userID);
+            
+      webcamWindows.addWindow(window);        
+      
+      trace("[" + me + "] openAvatarWindowFor:: Opening AVATAR window for [" + userID + "] [" + UsersUtil.getUserName(userID) + "]");
+      
+      openWindow(window);
+      dockWindow(window);          
+    }
+    
+    private function openPublishWindowFor(userID:String, camIndex:int, camWidth:int, camHeight:int):void {
+      var publishWindow:PublishWindow = new PublishWindow();
+      publishWindow.userID = userID;
+      publishWindow.title = UsersUtil.getUserName(userID);
+      publishWindow.camIndex = camIndex;
+      publishWindow.setResolution(camWidth, camHeight);
+      publishWindow.videoOptions = options;
+      publishWindow.quality = options.videoQuality;
+      publishWindow.resolutions = options.resolutions.split(",");
+      
+
+      trace("[" + me + "] openPublishWindowFor:: Closing window for [" + userID + "] [" + UsersUtil.getUserName(userID) + "]");
+      closeWindow(userID);
+
+      webcamWindows.addWindow(publishWindow);
+      
+      trace("[" + me + "] openPublishWindowFor:: Opening PUBLISH window for [" + userID + "] [" + UsersUtil.getUserName(userID) + "]");
+      
+      openWindow(publishWindow);     
+      dockWindow(publishWindow);  
+    }
+    
+    private function closeWindow(userID:String):void {
+      if (! webcamWindows.hasWindow(userID)) {
+        trace("[" + me + "] closeWindow:: No window for [" + userID + "] [" + UsersUtil.getUserName(userID) + "]");
+        return;
+      }
+      
+      var win:VideoWindowItf = webcamWindows.removeWindow(userID);
+      if (win != null) {
+        trace("[" + me + "] closeWindow:: Closing [" + win.getWindowType() + "] for [" + userID + "] [" + UsersUtil.getUserName(userID) + "]");
+        win.close();
+        var cwe:CloseWindowEvent = new CloseWindowEvent();
+        cwe.window = win;
+        _dispatcher.dispatchEvent(cwe);
+      } else {
+        trace("[" + me + "] closeWindow:: Not Closing. No window for [" + userID + "] [" + UsersUtil.getUserName(userID) + "]");
+      }
+    }
+    
+    private function openViewWindowFor(userID:String):void {
+      trace("[" + me + "] openViewWindowFor:: Opening VIEW window for [" + userID + "] [" + UsersUtil.getUserName(userID) + "]");
+      
+      var window:VideoWindow = new VideoWindow();
+      window.userID = userID;
+      window.videoOptions = options;       
+      window.resolutions = options.resolutions.split(",");
+      window.title = UsersUtil.getUserName(userID);
+      
+      closeWindow(userID);
+            
+      var bbbUser:BBBUser = UsersUtil.getUser(userID);      
+      window.startVideo(proxy.connection, bbbUser.streamName);
+      
+      webcamWindows.addWindow(window);        
+      openWindow(window);
+      dockWindow(window);  
+    }
+    
+    private function openWindow(window:VideoWindowItf):void {
+      var windowEvent:OpenWindowEvent = new OpenWindowEvent(OpenWindowEvent.OPEN_WINDOW_EVENT);
+      windowEvent.window = window;
+      _dispatcher.dispatchEvent(windowEvent);      
+    }
+    
+    private function dockWindow(window:VideoWindowItf):void {
+      // this event will dock the window, if it's enabled
+      var openVideoEvent:OpenVideoWindowEvent = new OpenVideoWindowEvent();
+      openVideoEvent.window = window;
+      _dispatcher.dispatchEvent(openVideoEvent);         
+    }
+    
+    public function connectToVideoApp():void {
+      proxy = new VideoProxy(options.uri + "/" + UsersUtil.getInternalMeetingID());
+      proxy.connect();
+    }
+    
+    public function startPublishing(e:StartBroadcastEvent):void{
+      LogUtil.debug("[" + me + "] startPublishing:: Publishing stream to: " + proxy.connection.uri + "/" + e.stream);
+      streamName = e.stream;
+      proxy.startPublishing(e);
+      
+      _isPublishing = true;
+      UsersUtil.setIAmPublishing(true);
+      
+      var broadcastEvent:BroadcastStartedEvent = new BroadcastStartedEvent();
+      broadcastEvent.stream = e.stream;
+      broadcastEvent.userid = UsersUtil.getMyUserID();
+      broadcastEvent.isPresenter = UsersUtil.amIPresenter();
+      broadcastEvent.camSettings = UsersUtil.amIPublishing();
+      
+      _dispatcher.dispatchEvent(broadcastEvent);
+      button.publishingStatus(button.START_PUBLISHING);
+    }
+       
+    public function stopPublishing(e:StopBroadcastEvent):void{
+      trace("[" + me + "] Stop publishing. ready = [" + _ready + "]"); 
+      stopBroadcasting();    
+    }
+    
+    private function stopBroadcasting():void {
+      proxy.stopBroadcasting();
+      
+      _isPublishing = false;
+      UsersUtil.setIAmPublishing(false);
+      var broadcastEvent:BroadcastStoppedEvent = new BroadcastStoppedEvent();
+      broadcastEvent.stream = streamName;
+      broadcastEvent.userid = UsersUtil.getMyUserID();
+      _dispatcher.dispatchEvent(broadcastEvent);
+      
+      //Make toolbar button enabled again
+      button.publishingStatus(button.STOP_PUBLISHING);
+      
+      closeWindow(UsersUtil.getMyUserID());
+      
+      if (options.displayAvatar) {
+        trace("[" + me + "] Opening avatar");
+        openAvatarWindowFor(UsersUtil.getMyUserID());              
+      }      
+    }
+    
+    public function handleClosePublishWindowEvent(event:ClosePublishWindowEvent):void {
+      if (_isPublishing) {
+        stopBroadcasting();
+      }
+    }
+    
+    public function handleShareCameraRequestEvent(event:ShareCameraRequestEvent):void {
+      openWebcamPreview(event.publishInClient);
+    }
+    
+    private function openWebcamPreview(publishInClient:Boolean):void {
+      var openEvent:BBBEvent = new BBBEvent(BBBEvent.OPEN_WEBCAM_PREVIEW);
+      openEvent.payload.publishInClient = publishInClient;
+      openEvent.payload.resolutions = options.resolutions;
+      
+      _dispatcher.dispatchEvent(openEvent);      
+    }
+    
+    public function stopModule():void {
+      closeAllWindows();
+      proxy.disconnect();
+    }
+    
+    public function closeAllWindows():void{
+      if (_isPublishing) {
+        stopBroadcasting();
+      }
+      
+      _dispatcher.dispatchEvent(new CloseAllWindowsEvent());
+    }
+    
+    public function switchToPresenter(event:MadePresenterEvent):void{
+      trace("[" + me + "] Got Switch to presenter event. ready = [" + _ready + "]");
+      
+      if (!_ready) return;
+           
+      if (options.presenterShareOnly){
+        button.isPresenter = true;
+      }
+    }
+    
+    public function switchToViewer(event:MadePresenterEvent):void{
+      trace("[" + me + "] Got Switch to viewer event. ready = [" + _ready + "]");
+      
+      if (!_ready) return;
+            
+      if (options.presenterShareOnly){
+        button.isPresenter = false;
+        if (_isPublishing) {
+          stopBroadcasting();
+        }
+      }
+    }
+    
+    public function connectedToVideoApp():void{
+      trace("[" + me + "] Connected to video application.");
+      _ready = true;
+      addToolbarButton();
+      openWebcamWindows();        
+    }
+    
+    public function handleCameraSetting(event:BBBEvent):void {      
+      var cameraIndex:int = event.payload.cameraIndex;
+      var camWidth:int = event.payload.cameraWidth;
+      var camHeight:int = event.payload.cameraHeight;     
+      trace("VideoEventMapDelegate::handleCameraSettings [" + cameraIndex + "," + camWidth + "," + camHeight + "]");
+      var camSettings:CameraSettingsVO = new CameraSettingsVO();
+      camSettings.camIndex = cameraIndex;
+      camSettings.camWidth = camWidth;
+      camSettings.camHeight = camHeight;
+      
+      UsersUtil.setCameraSettings(camSettings);
+      
+      openPublishWindowFor(UsersUtil.getMyUserID(), cameraIndex, camWidth, camHeight);       
+    }
+    
+    public function handleStoppedViewingWebcamEvent(event:StoppedViewingWebcamEvent):void {
+      closeWindow(event.webcamUserID);
+            
+      if (options.displayAvatar) {
+        trace("[" + me + "] Opening avatar");
+        openAvatarWindowFor(event.webcamUserID);              
+      }        
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/maps/WindowManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/maps/WindowManager.as
new file mode 100755
index 0000000000000000000000000000000000000000..8fd7a3e3d1063791b882fcbd4998994585bbade6
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/maps/WindowManager.as
@@ -0,0 +1,59 @@
+package org.bigbluebutton.modules.videoconf.maps
+{
+  import flash.media.Video;
+  
+  import mx.collections.ArrayCollection;
+  
+  import org.bigbluebutton.core.UsersUtil;
+  import org.bigbluebutton.modules.videoconf.business.VideoWindowItf;
+  import org.bigbluebutton.modules.videoconf.views.AvatarWindow;
+    
+  public class WindowManager
+  {
+    private var webcamWindows:ArrayCollection = new ArrayCollection();
+    
+    private function get me():String {
+      return UsersUtil.getMyUsername();
+    }
+    
+    public function addWindow(window:VideoWindowItf):void {      
+      webcamWindows.addItem(window);
+      trace("[" + me + "] addWindow:: userID = [" + window.userID + "] numWindows = [" + webcamWindows.length + "]");
+    }
+    
+    public function removeWindow(userID:String):VideoWindowItf {
+      for (var i:int = 0; i < webcamWindows.length; i++) {
+        var win:VideoWindowItf = webcamWindows.getItemAt(i) as VideoWindowItf;
+        trace("[" + me + "] removeWindow:: [" + win.userID + " == " + userID + "] equal = [" + (win.userID == userID) + "]");
+        if (win.userID == userID) {
+          return webcamWindows.removeItemAt(i) as VideoWindowItf;
+        }
+      }      
+      
+      return null;
+    }
+    
+    public function hasWindow(userID:String):Boolean {
+      trace("[" + me + "] hasWindow:: user [" + userID + "] numWindows = [" + webcamWindows.length + "]");
+      for (var i:int = 0; i < webcamWindows.length; i++) {
+        var win:VideoWindowItf = webcamWindows.getItemAt(i) as VideoWindowItf;
+        trace("[" + me + "] hasWindow:: [" + win.userID + " == " + userID + "] equal = [" + (win.userID == userID) + "]");
+        if (win.userID == userID) {          
+          return true;
+        }
+      }
+      
+      return false;
+    }
+    
+    public function getWindow(userID:String):VideoWindowItf {
+      for (var i:int = 0; i < webcamWindows.length; i++) {
+        var win:VideoWindowItf = webcamWindows.getItemAt(i) as VideoWindowItf;
+        trace("[" + me + "] getWindow:: [" + win.userID + " == " + userID + "] equal = [" + (win.userID == userID) + "]");
+        if (win.userID == userID) return win;
+      }      
+      
+      return null;      
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/model/PublishingModel.as b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/model/PublishingModel.as
new file mode 100755
index 0000000000000000000000000000000000000000..360d8a1fd6f66a1bc7c478d4affd5f7bab34e0d8
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/model/PublishingModel.as
@@ -0,0 +1,15 @@
+package org.bigbluebutton.modules.videoconf.model
+{
+  public class PublishingModel
+  {
+    public var streamName;
+    public var camIndex:int;
+    public var camWidth:int;
+    public var camHeight:int;
+    public var isPublishing:Boolean = false;
+    
+    public function PublishingModel()
+    {
+    }
+  }
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/model/VideoConfOptions.as b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/model/VideoConfOptions.as
index b082650627eead48a04d09e25cfbc255f9261b87..023a35a67efd91d51a2f4dc261ce449a0c2dd796 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/model/VideoConfOptions.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/model/VideoConfOptions.as
@@ -4,6 +4,14 @@ package org.bigbluebutton.modules.videoconf.model
 	
 	public class VideoConfOptions
 	{
+    public var uri:String = "rtmp://localhost/video";
+
+    [Bindable]
+    public var videoQuality:Number = 100;
+    
+    [Bindable]
+    public var resolutions:String = "320x240,640x480,1280x720";
+    
 		[Bindable]
 		public var autoStart:Boolean = false;
 		
@@ -64,6 +72,9 @@ package org.bigbluebutton.modules.videoconf.model
     [Bindable]
     public var controlsForPresenter:Boolean = false; 
     
+    [Bindable]
+    public var displayAvatar:Boolean = false;
+    
     public function VideoConfOptions() {
       parseOptions();
     }
@@ -71,6 +82,15 @@ package org.bigbluebutton.modules.videoconf.model
 		public function parseOptions():void {
 			var vxml:XML = BBB.getConfigForModule("VideoconfModule");
 			if (vxml != null) {
+        if (vxml.@uri != undefined) {
+          uri = vxml.@uri.toString();
+        }		
+        if (vxml.@videoQuality != undefined) {
+          videoQuality = Number(vxml.@videoQuality.toString());
+        }	
+        if (vxml.@resolutions != undefined) {
+          resolutions = vxml.@resolutions.toString();
+        }
 				if (vxml.@showCloseButton != undefined) {
 					showCloseButton = (vxml.@showCloseButton.toString().toUpperCase() == "TRUE") ? true : false;
 				}
@@ -138,6 +158,9 @@ package org.bigbluebutton.modules.videoconf.model
 				if (vxml.@h264Profile != undefined) {
 					h264Profile = vxml.@h264Profile.toString();
 				}
+        if (vxml.@displayAvatar != undefined) {
+          displayAvatar = (vxml.@displayAvatar.toString().toUpperCase() == "TRUE") ? true : false;
+        }	
 			}
 		}
 	}
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/AvatarWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/AvatarWindow.mxml
new file mode 100755
index 0000000000000000000000000000000000000000..1838ce987415d043355f98f23120706ecf071d1e
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/AvatarWindow.mxml
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  BigBlueButton open source conferencing system - http://www.bigbluebutton.org
+  
+  Copyright (c) 2010 BigBlueButton Inc. and by respective authors (see below).
+  
+  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 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/>.
+ 
+  $Id: $
+--> 
+
+<pubVid:VideoWindowItf
+	xmlns:mx="http://www.adobe.com/2006/mxml" 
+	xmlns:pubVid="org.bigbluebutton.modules.videoconf.business.*"
+	implements="org.bigbluebutton.common.IBbbModuleWindow"
+  styleNameFocus="videoAvatarStyleFocus"
+  styleNameNoFocus="videoAvatarStyleNoFocus"
+	creationComplete="onCreationComplete()"
+	width="{defaultWidth + 6}" height="{defaultHeight + 6}" 
+	xmlns:mate="http://mate.asfusion.com/"
+	resize="onResize()" 
+	horizontalScrollPolicy="off"
+	verticalScrollPolicy="off"
+	layout="absolute">
+	
+  <mate:Listener type="{BBBEvent.USER_VOICE_MUTED}" method="handleUserVoiceMutedEvent" />
+  <mate:Listener type="{EventConstants.USER_TALKING}" method="handleUserTalkingEvent" />
+  <mate:Listener type="{EventConstants.SWITCHED_PRESENTER}" method="handleNewRoleEvent" />
+  <mate:Listener type="{CloseAllWindowsEvent.CLOSE_ALL_WINDOWS}" method="closeWindow" />
+  
+	<mx:Script>
+		<![CDATA[
+      import flexlib.mdi.events.MDIWindowEvent;     
+      import mx.core.UIComponent;
+      import mx.events.ResizeEvent;      
+      import org.bigbluebutton.common.Images;
+      import org.bigbluebutton.common.LogUtil;
+      import org.bigbluebutton.common.Role;
+      import org.bigbluebutton.common.events.CloseWindowEvent;
+      import org.bigbluebutton.common.events.LocaleChangeEvent;
+      import org.bigbluebutton.core.EventConstants;
+      import org.bigbluebutton.core.UsersUtil;
+      import org.bigbluebutton.core.events.CoreEvent;
+      import org.bigbluebutton.core.managers.UserManager;
+      import org.bigbluebutton.main.events.BBBEvent;
+      import org.bigbluebutton.main.views.MainCanvas;
+      import org.bigbluebutton.modules.videoconf.business.TalkingButtonOverlay;
+      import org.bigbluebutton.modules.videoconf.events.CloseAllWindowsEvent;
+      import org.bigbluebutton.modules.videoconf.events.OpenVideoWindowEvent;
+      import org.bigbluebutton.modules.videoconf.events.StartBroadcastEvent;
+      import org.bigbluebutton.modules.videoconf.model.VideoConfOptions;
+      import org.bigbluebutton.util.i18n.ResourceUtil;
+      
+			[Bindable] private var defaultWidth:Number = 320;
+			[Bindable] private var defaultHeight:Number = 240;
+			         
+			private var camWidth:Number = 320;
+			private var camHeight:Number = 240;
+		
+      private var windowType:String = "AvatarWindowType";
+      
+      override public function getWindowType():String {
+        return windowType;
+      }
+      
+      private var loader:Loader;
+      private var request:URLRequest;
+      
+      private function loadAvatar():void {
+        loader = new Loader();
+        request = new URLRequest(UsersUtil.getAvatarURL());
+        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadingComplete);
+        loader.load(request);
+        
+      }
+      
+      private function onLoadingComplete(event:Event):void {
+        loader.x = (_videoHolder.width - loader.width) / 2;
+        loader.y = (_videoHolder.height - loader.height) / 2;
+        _videoHolder.addChild(loader);
+        
+        onResize();
+      }
+      
+			private function onCreationComplete():void {
+				_videoHolder = new UIComponent();
+				_videoHolder.width = camWidth;
+				_videoHolder.height = camHeight;
+				this.addChild(_videoHolder);				
+
+        _video = new Video();
+
+				this.minWidth = _minWidth;
+				this.minHeight = _minHeight;
+				maximizeRestoreBtn.visible = false;
+        
+        showCloseButton = false;
+        
+				this.resizable = false;
+				setAspectRatio(camWidth, camHeight);
+        
+        addEventListener(MDIWindowEvent.RESIZE_START, onResizeStart);
+        addEventListener(MDIWindowEvent.RESIZE_END, onResizeEnd);
+        addEventListener(MouseEvent.MOUSE_OVER, showButtons);
+        addEventListener(MouseEvent.MOUSE_OUT, hideButtons);
+        
+        startPublishing();
+        
+        loadAvatar();
+			}
+			
+      override protected function onResize():void {
+        super.onResize();
+        
+        if (loader != null && _videoHolder != null) {
+          loader.x = (_videoHolder.width - loader.width) / 2;
+          loader.y = (_videoHolder.height - loader.height) / 2;          
+        }
+      }
+      
+      private function handleNewRoleEvent(event:CoreEvent):void {
+        switchRole(event.message.role == Role.PRESENTER)
+      }
+
+      private function handleUserVoiceMutedEvent(event:BBBEvent):void {
+        if (event.payload.userID ==  userID) {
+          userMuted(event.payload.muted);
+        }
+      }
+      
+      private function handleUserTalkingEvent(event:CoreEvent):void {
+        if (event.message.userID ==  userID) {
+          if (event.message.talking) {
+            notTalkingEffect.end();
+            talkingEffect.play([this]);            
+          } else {
+            talkingEffect.end();
+            notTalkingEffect.play([this]);
+          }
+        }
+      }
+      						
+			private function startPublishing():void{				
+				defaultWidth = originalWidth;
+				defaultHeight = originalHeight;
+
+				maximizeRestoreBtn.visible = true;
+				this.resizable = true;
+				onResize();
+												
+        createButtons();
+        addControlButtons();	
+        updateButtonsPosition();
+			}
+			
+			override public function close(event:MouseEvent=null):void{
+        closeThisWindow();
+				super.close(event);
+			}
+					
+			private function closeWindow(e:CloseAllWindowsEvent):void{
+				closeThisWindow();
+			}
+			
+			private function closeThisWindow():void {
+        trace("******************** Closing avatar window for user [" + userID + "]*********************");
+			}
+			
+			
+		]]>
+	</mx:Script>
+
+  <mx:Glow id="talkingEffect" duration="500" alphaFrom="1.0" alphaTo="0.3"
+           blurXFrom="0.0" blurXTo="30.0" blurYFrom="0.0" blurYTo="30.0" color="0x4A931D"/>
+  <mx:Glow id="notTalkingEffect" duration="500" alphaFrom="0.3" alphaTo="1.0"
+           blurXFrom="30.0" blurXTo="0.0" blurYFrom="30.0" blurYTo="0.0" color="0x4A931D"/>
+
+</pubVid:VideoWindowItf>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/ControlButtons.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/ControlButtons.mxml
index 9f894a292071d6860c028d4d63590df5fc6314c5..85c49525b40f646df6f79f0be0f706fed6bec108 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/ControlButtons.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/ControlButtons.mxml
@@ -5,8 +5,7 @@
     
   <mx:Script>
     <![CDATA[
-      import com.asfusion.mate.events.Dispatcher;
-      
+      import com.asfusion.mate.events.Dispatcher;     
       import org.bigbluebutton.common.Images;
       import org.bigbluebutton.common.LogUtil;
       import org.bigbluebutton.core.EventConstants;
@@ -22,20 +21,9 @@
       
       public var sharerUserID:String;
       [Bindable]
-      private var BUTTONS_SIZE:int = 20;
+      private var BUTTONS_SIZE:int = 31;
       private var BUTTONS_PADDING:int = 10;
-      
-      private var images:Images = new Images();
-      
-      [Bindable]
-      private var img_mute_icon:Class = images.sound_mute;
-      [Bindable]
-      private var signOutIcon:Class = images.signOutIcon;
-      [Bindable]
-      private var adminIcon:Class = images.admin;
-      [Bindable]
-      private var chatIcon:Class = images.chatIcon;
-      
+           
       [Bindable]
       private var showButton:Boolean;
       
@@ -48,6 +36,14 @@
         return BUTTONS_PADDING;
       }
       
+      public function userMuted(muted:Boolean):void {
+        if (muted) {
+          muteUnmuteBtn.styleName = "videoMutedButtonStyle";
+        } else {
+          muteUnmuteBtn.styleName = "videoUnmutedButtonStyle";
+        }
+      }
+      
       public function handleNewRoleEvent(presenter:Boolean):void {
         showControlButtons(presenter);
       }
@@ -108,8 +104,15 @@
       }
     ]]>
   </mx:Script>
-  <mx:Button id="muteUnmuteBtn" visible="false" click="onMuteUnmuteClicked()" icon="{img_mute_icon}" width="{BUTTONS_SIZE}" height="{BUTTONS_SIZE}"/>
-  <mx:Button id="switchPresenter" visible="false" click="onSwitchPresenterClicked()" icon="{adminIcon}" width="{BUTTONS_SIZE}" height="{BUTTONS_SIZE}"/>
-  <mx:Button id="ejectUserBtn" visible="false" click="onKickUserClicked()" icon="{signOutIcon}" width="{BUTTONS_SIZE}" height="{BUTTONS_SIZE}"/>
-  <mx:Button id="privateChatBtn" click="onPrivateChatClicked()" icon="{chatIcon}" width="{BUTTONS_SIZE}" height="{BUTTONS_SIZE}"/>
+  <mx:Button id="muteUnmuteBtn" visible="false" click="onMuteUnmuteClicked()"
+             width="{BUTTONS_SIZE}" height="{BUTTONS_SIZE}" styleName="videoUnmutedButtonStyle"/>
+  <mx:Spacer width="2"/>
+  <mx:Button id="switchPresenter" visible="false" click="onSwitchPresenterClicked()"
+             width="{BUTTONS_SIZE}" height="{BUTTONS_SIZE}" styleName="videoSwitchPresenterButtonStyle"/>
+  <mx:Spacer width="2"/>
+  <mx:Button id="ejectUserBtn" visible="false" click="onKickUserClicked()"
+             width="{BUTTONS_SIZE}" height="{BUTTONS_SIZE}" styleName="videoEjectUserButtonStyle"/>
+  <mx:Spacer width="2"/>
+  <mx:Button id="privateChatBtn" click="onPrivateChatClicked()"
+             width="{BUTTONS_SIZE}" height="{BUTTONS_SIZE}" styleName="videoPrivateChatButtonStyle"/>
 </mx:HBox>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/PublishWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/PublishWindow.mxml
index 14dfdff9fd2f93187dea6e26f6854f911a1461b2..41b46c6b80b8df6eb530693a68d666f3816dfd2f 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/PublishWindow.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/PublishWindow.mxml
@@ -24,30 +24,38 @@
 	xmlns:mx="http://www.adobe.com/2006/mxml" 
 	xmlns:pubVid="org.bigbluebutton.modules.videoconf.business.*"
 	implements="org.bigbluebutton.common.IBbbModuleWindow"
-	creationComplete="init()"
-	width="{defaultWidth + 6}" height="{defaultHeight + 75}" 
+  styleNameFocus="videoPublishStyleFocus"
+  styleNameNoFocus="videoPublishStyleNoFocus"
+	creationComplete="onCreationComplete()" 
+	width="{defaultWidth + 6}" height="{defaultHeight + 6}" 
 	xmlns:mate="http://mate.asfusion.com/"
 	resize="onResize()"
 	horizontalScrollPolicy="off"
 	verticalScrollPolicy="off"
 	layout="absolute">
 	
+  <mate:Listener type="{BBBEvent.USER_VOICE_MUTED}" method="handleUserVoiceMutedEvent" />
   <mate:Listener type="{EventConstants.USER_TALKING}" method="handleUserTalkingEvent" />
-  <mate:Listener type="{EventConstants.NEW_ROLE}" method="handleNewRoleEvent" />
+  <mate:Listener type="{EventConstants.SWITCHED_PRESENTER}" method="handleNewRoleEvent" />
+  <mate:Listener type="{CloseAllWindowsEvent.CLOSE_ALL_WINDOWS}" method="closeWindow" />
   
 	<mx:Script>
 		<![CDATA[
-      import flexlib.mdi.events.MDIWindowEvent;    
+      import flexlib.mdi.events.MDIWindowEvent;
+      
       import mx.core.UIComponent;
-      import mx.events.ResizeEvent;     
+      import mx.events.ResizeEvent;
+      
       import org.bigbluebutton.common.Images;
       import org.bigbluebutton.common.LogUtil;
+      import org.bigbluebutton.common.Role;
       import org.bigbluebutton.common.events.CloseWindowEvent;
       import org.bigbluebutton.common.events.LocaleChangeEvent;
       import org.bigbluebutton.core.EventConstants;
       import org.bigbluebutton.core.UsersUtil;
       import org.bigbluebutton.core.events.CoreEvent;
       import org.bigbluebutton.core.managers.UserManager;
+      import org.bigbluebutton.main.events.BBBEvent;
       import org.bigbluebutton.main.views.MainCanvas;
       import org.bigbluebutton.modules.videoconf.business.TalkingButtonOverlay;
       import org.bigbluebutton.modules.videoconf.events.CloseAllWindowsEvent;
@@ -56,17 +64,13 @@
       import org.bigbluebutton.modules.videoconf.events.StopBroadcastEvent;
       import org.bigbluebutton.modules.videoconf.model.VideoConfOptions;
       import org.bigbluebutton.util.i18n.ResourceUtil;
-      import org.bigbluebutton.common.Role;
       
-			[Bindable] public var camIcon:Class = images.control_play;
-			[Bindable] public var bbbLogo:Class = images.bbb_logo;
-
 			[Bindable] private var defaultWidth:Number = 320;
 			[Bindable] private var defaultHeight:Number = 240;
-			         
+			
+      public var camIndex:int = 0;
 			private var camWidth:Number = 320;
-			private var camHeight:Number = 240;
-			private var _userrole:String;
+      private var camHeight:Number = 240;
 			private var _camera:Camera = null;
 			public var quality:Number = 0;
 						
@@ -87,37 +91,31 @@
 			[Bindable]
 			public var videoOptions:VideoConfOptions;
 			
-			private function init():void{
+      private var windowType:String = "PublishWindowType";
+      
+      override public function getWindowType():String {
+        return windowType;
+      }
+      
+			private function onCreationComplete():void{
 				_videoHolder = new UIComponent();
 				_videoHolder.width = camWidth;
 				_videoHolder.height = camHeight;
 				this.addChild(_videoHolder);				
-				this.title = ResourceUtil.getInstance().getString('bbb.publishVideo.title');
-
-				checkIfMacCamera();
-				if (isPresenter()) showResControls(true);
-				if (Camera.names.length > 1) showVideoControls(true);
-				if (!isPresenter() && Camera.names.length == 1) startPublishing();
 
 				this.minWidth = _minWidth;
 				this.minHeight = _minHeight;
 				maximizeRestoreBtn.visible = false;
 				this.resizable = false;
-				
-				loadPrefs();
-				
+							
 				this.visible = videoOptions.publishWindowVisible;
 				
-				if (videoOptions.autoStart) {
-					/*
-					 * Need to have a timer to trigger auto-publishing of webcam.
-					 */
-					autoPublishTimer = new Timer(3000, 1);
-					autoPublishTimer.addEventListener(TimerEvent.TIMER, autopublishTimerHandler);
-					autoPublishTimer.start();
-				}
-				
-				// start the camera preview
+        addEventListener(MDIWindowEvent.RESIZE_START, onResizeStart);
+        addEventListener(MDIWindowEvent.RESIZE_END, onResizeEnd);
+        addEventListener(MouseEvent.MOUSE_OVER, showButtons);
+        addEventListener(MouseEvent.MOUSE_OUT, hideButtons);
+        addEventListener(MouseEvent.DOUBLE_CLICK, onDoubleClick);
+        
 				updateCamera();
 			}
 
@@ -130,37 +128,33 @@
         switchRole(event.message.role == Role.PRESENTER)
       }
       
+      private function handleUserVoiceMutedEvent(event:BBBEvent):void {
+        if (event.payload.userID ==  userID) {
+          userMuted(event.payload.muted);
+        }
+      }
+      
       private function handleUserTalkingEvent(event:CoreEvent):void {
-        if (event.message.userID ==  _sharerUserID) {
+        if (event.message.userID ==  userID) {
           if (event.message.talking) {
             notTalkingEffect.end();
-            talkingEffect.play([_videoHolder]);            
+            talkingEffect.play([this]);            
           } else {
             talkingEffect.end();
-            notTalkingEffect.play([_videoHolder]);
+            notTalkingEffect.play([this]);
           }
         }
       }
-      
-			private function loadPrefs():void{
-				var sharedObject:SharedObject = SharedObject.getLocal("bbbUserProperties", "/");
-				var webcam:String = sharedObject.data["webcam"] as String;
-				for (var i:Number = 0; i<Camera.names.length; i++){
-					if (Camera.names[i] == webcam) cmbCameraSelector.selectedIndex = i;
-				}
-			}
-			
+      		
 			private function updateCamera():void {
 				stopCamera();
-			
-				btnStartPublish.enabled = false;
-				
+					
 				if (Camera.names.length == 0) {
 					showWarning('bbb.video.publish.hint.noCamera');
 					return;
 				}
 				
-				_camera = Camera.getCamera(cmbCameraSelector.selectedIndex.toString());
+        _camera = Camera.getCamera();
 				if (_camera == null) {
 					showWarning('bbb.video.publish.hint.cantOpenCamera');
 					return;
@@ -181,17 +175,15 @@
 					onCameraAccessAllowed();
 				}
 
-			    _camera.addEventListener(ActivityEvent.ACTIVITY, onActivityEvent);
-			    _camera.addEventListener(StatusEvent.STATUS, onStatusEvent);
-
-				setComboResolution();
+			  _camera.addEventListener(ActivityEvent.ACTIVITY, onActivityEvent);
+			  _camera.addEventListener(StatusEvent.STATUS, onStatusEvent);
 				
 				_camera.setKeyFrameInterval(videoOptions.camKeyFrameInterval);
 				_camera.setMode(camWidth, camHeight, videoOptions.camModeFps);
 				_camera.setQuality(videoOptions.camQualityBandwidth, videoOptions.camQualityPicture);
 				
 				if (_camera.width != camWidth || _camera.height != camHeight) {
-					LogUtil.debug("Resolution " + camWidth + "x" + camHeight + " is not supported, using " + _camera.width + "x" + _camera.height + " instead");
+					trace("Resolution " + camWidth + "x" + camHeight + " is not supported, using " + _camera.width + "x" + _camera.height + " instead");
 					setResolution(_camera.width, _camera.height);
 				}				
 				
@@ -211,36 +203,43 @@
 				}				
 
 				_videoHolder.addChild(_video);
-        
+                
    		}
    		      
-			private function onActivityEvent(e:ActivityEvent):void {
-			    if (_waitingForActivation && e.activating) {
-			        _activationTimer.stop();
-					showWarning('bbb.video.publish.hint.videoPreview', false, "0xFFFF00");
-			     	btnStartPublish.enabled = true;
-			     	_waitingForActivation = false;
-			    }
+			private function onActivityEvent(e:ActivityEvent):void {        
+        if (_waitingForActivation && e.activating) {
+          trace("Cam activity event:  waitingForActivation = [" + _waitingForActivation + "] activating = [" + e.activating + "]");
+          _activationTimer.stop();
+          showWarning('bbb.video.publish.hint.videoPreview', false, "0xFFFF00");
+          _waitingForActivation = false;
+              
+          trace("Starting auto-publisher timer.");             
+          autoPublishTimer = new Timer(3000, 1);
+          autoPublishTimer.addEventListener(TimerEvent.TIMER, autopublishTimerHandler);
+          autoPublishTimer.start();
+        }
 			}
 
 			private function onStatusEvent(e:StatusEvent):void {
 				if (e.code == "Camera.Unmuted") {
 					onCameraAccessAllowed();
 					// this is just to overwrite the message of waiting for approval
-				    showWarning('bbb.video.publish.hint.openingCamera');
-			    } else if (e.code == "Camera.Muted") {
-			    	onCameraAccessDisallowed();
-			    }
+          showWarning('bbb.video.publish.hint.openingCamera');
+        } else if (e.code == "Camera.Muted") {
+          onCameraAccessDisallowed();
+        }
 			}
 			
 			private function onCameraAccessAllowed():void {
 				// set timer to ensure that the camera activates.  If not, it might be in use by another application
 				_waitingForActivation = true;
-				if (_activationTimer != null)
-					_activationTimer.stop();
-			    _activationTimer = new Timer(10000, 1);
-			    _activationTimer.addEventListener(TimerEvent.TIMER, activationTimeout);
-			    _activationTimer.start();
+				if (_activationTimer != null) {
+          _activationTimer.stop();
+        }
+					
+        _activationTimer = new Timer(10000, 1);
+        _activationTimer.addEventListener(TimerEvent.TIMER, activationTimeout);
+        _activationTimer.start();
 			}
 			
 			private function onCameraAccessDisallowed():void {
@@ -257,9 +256,10 @@
 			private function startPublishing():void{
 				if (_camera == null) return;
 
-				if (autoPublishTimer != null)
-					autoPublishTimer.stop();
-
+				if (autoPublishTimer != null) {
+          autoPublishTimer.stop();
+        }
+					
 				showWarning('bbb.video.publish.hint.publishing', true, "0xFFFF00");
 				
 				defaultWidth = originalWidth;
@@ -270,63 +270,52 @@
 				e.camera = _camera;
 				dispatchEvent(e);
 				
-				showVideoControls(false);
-				showResControls(false);
-
 				maximizeRestoreBtn.visible = true;
 				this.resizable = true;
 				onResize();
 				
-				addEventListener(MDIWindowEvent.RESIZE_START, onResizeStart);
-				addEventListener(MDIWindowEvent.RESIZE_END, onResizeEnd);
-				addEventListener(MDIWindowEvent.DRAG_START, onDragStart);
-				addEventListener(MDIWindowEvent.DRAG, onDrag);
-				addEventListener(MDIWindowEvent.DRAG_END, onDragEnd);
-				addEventListener(MouseEvent.MOUSE_OVER, showButtons);
-				addEventListener(MouseEvent.MOUSE_OUT, hideButtons);
-				addEventListener(MouseEvent.DOUBLE_CLICK, onDoubleClick);
+
 				
         // Store the userid for the publisher. This allows us to control
         // the user's status from the video window
-        _sharerUserID = UsersUtil.getMyUserID();
+        userID = UsersUtil.getMyUserID();
 				
         createButtons();
         addControlButtons();
-        
-				// this event will dock the window, if it's enabled
-				var openVideoEvent:OpenVideoWindowEvent = new OpenVideoWindowEvent();
-				openVideoEvent.window = this;
-				dispatchEvent(openVideoEvent);					
+        			
 			}
 			
+      private var _isClosing:Boolean = false;
+      
 			override public function close(event:MouseEvent=null):void{
-				stopPublishing();
-				super.close(event);
+        trace("PublishWindow::close");
+			  if (!_isClosing) {
+          _isClosing = true;
+          stopPublishing();
+        }
 			}
 			
 			private function stopCamera():void {
+        _camera = null;
 				if (_video != null) {
 					_videoHolder.removeChild(_video);
 					_video.attachCamera(null);
 					_video.clear();
 					_video = null;
 				}
-				_camera = null;
+				
 			}
 			
 			private function stopPublishing():void{
+        trace("PublishWindow::stopPublishing");
 				stopCamera();
 				var e:StopBroadcastEvent = new StopBroadcastEvent()
 				e.stream = streamName;
 				dispatchEvent(e);
 			}
 			
-			private function setComboResolution():void {
-				var res:Array = cmbResolution.selectedLabel.split( "x" );
-				setResolution(Number(res[0]), Number(res[1]));
-			}
-			
-			private function setResolution(width:int, height:int):void {
+		
+			public function setResolution(width:int, height:int):void {
 				camWidth = originalWidth = width;
 				camHeight = originalHeight = height;
 				setAspectRatio(camWidth, camHeight);
@@ -337,63 +326,20 @@
          		 */	 	
 				var curTime:Number = new Date().getTime();	
         var uid:String = UserManager.getInstance().getConference().getMyUserId();
-        this.streamName = cmbResolution.selectedLabel.concat("-" + uid) + "-" + curTime;
-			}
-			
-			public function set userrole(role:String):void{
-				this._userrole = role;
+        var res:String = camWidth + "x" + camHeight;
+        this.streamName = res.concat("-" + uid) + "-" + curTime;
 			}
-			
+						
 			private function isPresenter():Boolean{
-				if (this._userrole == "MODERATOR" || this._userrole == "PRESENTER") return true;
+				if (UsersUtil.amIModerator() || UsersUtil.amIPresenter()) return true;
 				else return false;
 			}
-			
-			private function showVideoControls(show:Boolean):void{
-				if (show){
-					videoOptionsBar.visible = true;
-					btnStartPublish.visible = true;
-					cmbCameraSelector.visible = true;
-				} else{					
-					videoOptionsBar.visible = false;
-					videoOptionsBar.width = 0;
-					videoOptionsBar.height = 0;
-					btnStartPublish.visible = false;
-					cmbCameraSelector.visible = false;
-					videoOptionsBar.visible = false;
-				}
-			}
-			
-			private function showResControls(show:Boolean):void{
-				if (show) cmbResolution.visible = true;
-				else cmbResolution.visible = false;
-			}
-			
+						
 			private function closeWindow(e:CloseAllWindowsEvent):void{
-				closeThisWindow();
-			}
-			
-			private function closeThisWindow():void {
-				stopCamera();
-				this.close();
+        trace("PublishWindow::closeWindow");
+        stopCamera();
 			}
-			
-			private function checkIfMacCamera():void{
-				for (var i:int = 0; i<Camera.names.length; i++){
-					if (Camera.names[i] == "USB Video Class Video") {
-						/**
-						 * Set as default for Macs
-						 */
-						cmbCameraSelector.selectedIndex = i;
-					}
-				}
-			}
-			
-			override protected function resourcesChanged():void{
-				super.resourcesChanged();
-			}		
-			
-			
+							
 			private var hideWarningTimer:Timer = null;
 			
 			private function showWarning(resourceName:String, autoHide:Boolean=false, color:String="0xFF0000"):void {
@@ -421,19 +367,15 @@
 		]]>
 	</mx:Script>
 
-  <mx:Glow id="talkingEffect" duration="500" alphaFrom="1.0" alphaTo="0.3"
-           blurXFrom="0.0" blurXTo="30.0" blurYFrom="0.0" blurYTo="30.0" color="0xFF0000"/>
+  <mx:Glow id="talkingEffect" duration="500" alphaFrom="1.0" alphaTo="0.3" 
+           blurXFrom="0.0" blurXTo="30.0" blurYFrom="0.0" blurYTo="30.0" color="0x4A931D"/>
   <mx:Glow id="notTalkingEffect" duration="500" alphaFrom="0.3" alphaTo="1.0"
-           blurXFrom="30.0" blurXTo="0.0" blurYFrom="30.0" blurYTo="0.0" color="0xFF0000"/>
+           blurXFrom="30.0" blurXTo="0.0" blurYFrom="30.0" blurYTo="0.0" color="0x4A931D"/>
   
 	<mx:Fade id="dissolveOut" duration="1000" alphaFrom="1.0" alphaTo="0.0"/>
 	<mx:Fade id="dissolveIn" duration="1000" alphaFrom="0.0" alphaTo="1.0"/>
-	<mx:Text id="lblWarning" width="100%" textAlign="right" fontSize="14" fontWeight="bold" y="{this.height - (videoOptionsBar.visible? videoOptionsBar.height: 0) - lblWarning.height - 30}" visible="false" selectable="false" hideEffect="{dissolveOut}" showEffect="{dissolveIn}"/>
-	<mx:ControlBar id="videoOptionsBar" visible="true">
-		<mx:Button id="btnStartPublish" toolTip="{ResourceUtil.getInstance().getString('bbb.publishVideo.startPublishBtn.toolTip')}" icon="{camIcon}" click="startPublishing()" enabled="false"/>
-		<mx:ComboBox id="cmbCameraSelector" dataProvider="{Camera.names}" width="150" visible="false" change="updateCamera()"/>
-		<mx:ComboBox id="cmbResolution" dataProvider="{resolutions}" width="20%" visible="false" change="updateCamera()"/>
-	</mx:ControlBar>
-	
-	<mate:Listener type="{CloseAllWindowsEvent.CLOSE_ALL_WINDOWS}" method="closeWindow" />
+	<mx:Text id="lblWarning" width="100%" textAlign="right" fontSize="14" fontWeight="bold" y="{this.height - lblWarning.height - 30}" 
+           visible="false" selectable="false" hideEffect="{dissolveOut}" showEffect="{dissolveIn}"/>
+
+
 </pubVid:VideoWindowItf>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/ToolbarButton.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/ToolbarButton.mxml
index 9afb2fbe702ed4b4f73e9249bd53c42c846ce1e1..16dab102e1c6c1751d52eb9d464a2e021dda7a28 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/ToolbarButton.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/ToolbarButton.mxml
@@ -44,17 +44,14 @@
 			private var images:Images = new Images();
 			[Bindable] public var camIcon:Class = images.webcam;
 
-
 			public const OFF_STATE:Number = 0;
 			public const ON_STATE:Number = 1;
 			
 			public const STOP_PUBLISHING:Number = 0;
 			public const START_PUBLISHING:Number = 1;
-			
-			
+						
 			private var _currentState:Number = OFF_STATE;
 
-
 			
 			private var dispatcher:Dispatcher;
 			
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/VideoWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/VideoWindow.mxml
index 958c5387932d5aa5de35e4208d5276418c7f0afc..529837030e9791fa7d796cafdfba6c5fb1c165ef 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/VideoWindow.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/VideoWindow.mxml
@@ -23,31 +23,35 @@
 <viewVid:VideoWindowItf  
   xmlns:viewVid="org.bigbluebutton.modules.videoconf.business.*"
 	xmlns:mx="http://www.adobe.com/2006/mxml" 
-	creationComplete="init()"
+	creationComplete="onCreationComplete()"
 	implements="org.bigbluebutton.common.IBbbModuleWindow"
 	xmlns:mate="http://mate.asfusion.com/"
+  styleNameFocus="videoViewStyleFocus"
+  styleNameNoFocus="videoViewStyleNoFocus"
 	resize="onResize()"
 	layout="absolute">
 	
+  <mate:Listener type="{BBBEvent.USER_VOICE_MUTED}" method="handleUserVoiceMutedEvent" />
   <mate:Listener type="{EventConstants.USER_TALKING}" method="handleUserTalkingEvent" />
-  <mate:Listener type="{EventConstants.NEW_ROLE}" method="handleNewRoleEvent" />
+  <mate:Listener type="{EventConstants.SWITCHED_PRESENTER}" method="handleNewRoleEvent" />
+  <mate:Listener type="{CloseAllWindowsEvent.CLOSE_ALL_WINDOWS}" method="closeWindow" />
   
 	<mx:Script>
 		<![CDATA[
       import com.asfusion.mate.events.Dispatcher;      
-      import flexlib.mdi.events.MDIWindowEvent;      
-      import mx.controls.Alert;
+      import flexlib.mdi.events.MDIWindowEvent;     
       import mx.core.UIComponent;      
       import org.bigbluebutton.common.LogUtil;
+      import org.bigbluebutton.common.Role;
       import org.bigbluebutton.common.events.CloseWindowEvent;
       import org.bigbluebutton.core.EventConstants;
       import org.bigbluebutton.core.events.CoreEvent;
       import org.bigbluebutton.main.events.BBBEvent;
+      import org.bigbluebutton.main.events.StoppedViewingWebcamEvent;
       import org.bigbluebutton.main.views.MainCanvas;
       import org.bigbluebutton.modules.videoconf.business.TalkingButtonOverlay;
       import org.bigbluebutton.modules.videoconf.events.CloseAllWindowsEvent;
       import org.bigbluebutton.modules.videoconf.model.VideoConfOptions;
-      import org.bigbluebutton.common.Role;
       
 			private var ns:NetStream;			
 			private var globalDispatcher:Dispatcher;
@@ -55,7 +59,13 @@
 			[Bindable]
 			public var videoOptions:VideoConfOptions;
 			
-			private function init():void{
+      private var windowType:String = "VideoWindowType";
+      
+      override public function getWindowType():String {
+        return windowType;
+      }
+      
+			private function onCreationComplete():void{
 				_videoHolder = new UIComponent();
 				_videoHolder.addChild(_video);
 				this.addChild(_videoHolder);
@@ -64,9 +74,6 @@
 				addEventListener(MDIWindowEvent.RESIZE_END, onResizeEnd);
 				addEventListener(MDIWindowEvent.CLOSE, onCloseEvent);
 
-				addEventListener(MDIWindowEvent.DRAG_START, onDragStart);
-				addEventListener(MDIWindowEvent.DRAG, onDrag);
-				addEventListener(MDIWindowEvent.DRAG_END, onDragEnd);
 				addEventListener(MouseEvent.MOUSE_OVER, showButtons);
 				addEventListener(MouseEvent.MOUSE_OUT, hideButtons);
 				addEventListener(MouseEvent.DOUBLE_CLICK, onDoubleClick);
@@ -100,29 +107,38 @@
         switchRole(event.message.role == Role.PRESENTER)
       }
       
+      private function handleUserVoiceMutedEvent(event:BBBEvent):void {
+        if (event.payload.userID ==  userID) {
+          userMuted(event.payload.muted);
+        }
+      }
+      
+      private var _closing:Boolean = false;
+      
 			private function onCloseEvent(event:MDIWindowEvent = null):void {
 				LogUtil.debug("ViewWindow closing " + streamName);
-				var bbbEvt:BBBEvent = new BBBEvent("ViewVideoCloseEvent");
-				bbbEvt.message = streamName;
-				dispatchEvent(bbbEvt);
+        if (!_closing) {
+          _closing = true;
+          var stopEvent:StoppedViewingWebcamEvent = new StoppedViewingWebcamEvent();
+          stopEvent.webcamUserID = userID;
+          globalDispatcher.dispatchEvent(stopEvent);          
+        }
+
 			}
 			
       private function handleUserTalkingEvent(event:CoreEvent):void {
-        if (event.message.userID ==  _sharerUserID) {
+        if (event.message.userID ==  userID) {
           if (event.message.talking) {
             notTalkingEffect.end();
-            talkingEffect.play([_videoHolder]);            
+            talkingEffect.play([this]);            
           } else {
             talkingEffect.end();
-            notTalkingEffect.play([_videoHolder]);
+            notTalkingEffect.play([this]);
           }
         }
       }
       
-      protected function onTalkingClicked(event:MouseEvent = null):void {
-        // do nothing
-      }
-      
+    
 			public function startVideo(connection:NetConnection, stream:String):void{
 				ns = new NetStream(connection);
 				ns.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
@@ -143,7 +159,7 @@
 
 
 				if (videoOptions.smoothVideo) {
-					LogUtil.debug("Smoothing video.")
+					trace("Smoothing video.")
 					_video.smoothing = true;
 				} 
 				
@@ -151,7 +167,7 @@
 					var filter:ConvolutionFilter = new flash.filters.ConvolutionFilter();
 					filter.matrixX = 3;
 					filter.matrixY = 3;
-					LogUtil.debug("Applying convolution filter =[" + videoOptions.convolutionFilter + "]");					
+					trace("Applying convolution filter =[" + videoOptions.convolutionFilter + "]");					
 					filter.matrix = videoOptions.convolutionFilter;
 					filter.bias =  videoOptions.filterBias;
 					filter.divisor = videoOptions.filterDivisor;
@@ -170,7 +186,7 @@
 			}
 			
 			public function onMetaData(info:Object):void{
-				LogUtil.debug("metadata: width=" + info.width + " height=" + info.height);
+				trace("metadata: width=" + info.width + " height=" + info.height);
 				_video.width = info.width;
 				_video.height = info.height;
 				setAspectRatio(info.width, info.height);
@@ -215,9 +231,9 @@
 	</mx:Script>
   
   <mx:Glow id="talkingEffect" duration="500" alphaFrom="1.0" alphaTo="0.3"
-           blurXFrom="0.0" blurXTo="10.0" blurYFrom="0.0" blurYTo="10.0" color="0xFF0000"/>
+           blurXFrom="0.0" blurXTo="10.0" blurYFrom="0.0" blurYTo="10.0" color="0x4A931D"/>
   <mx:Glow id="notTalkingEffect" duration="500" alphaFrom="0.3" alphaTo="1.0"
-           blurXFrom="10.0" blurXTo="0.0" blurYFrom="10.0" blurYTo="0.0" color="0xFF0000"/>
+           blurXFrom="10.0" blurXTo="0.0" blurYFrom="10.0" blurYTo="0.0" color="0x4A931D"/>
 	
-  <mate:Listener type="{CloseAllWindowsEvent.CLOSE_ALL_WINDOWS}" method="closeWindow" />
+
 </viewVid:VideoWindowItf>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videodock/views/DockOptions.as b/bigbluebutton-client/src/org/bigbluebutton/modules/videodock/views/DockOptions.as
index b6064234769977c335c3c4ffb7d9d7a21d9fd71c..221975faebcf2f768d843f2accd1f1e0540126d3 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/videodock/views/DockOptions.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videodock/views/DockOptions.as
@@ -4,6 +4,9 @@ package org.bigbluebutton.modules.videodock.views
 
 	public class DockOptions
 	{
+    [Bindable]
+    public var showControls:Boolean = true;
+    
 		[Bindable]
 		public var autoDock:Boolean = true;
 		
@@ -32,6 +35,9 @@ package org.bigbluebutton.modules.videodock.views
 		{
 			var vxml:XML = BBB.getConfigForModule("VideodockModule");
 			if (vxml != null) {
+        if (vxml.@showControls != undefined) {
+          showControls = (vxml.@showControls.toString().toUpperCase() == "TRUE") ? true : false;
+        }
 				if (vxml.@autoDock != undefined) {
 					autoDock = (vxml.@autoDock.toString().toUpperCase() == "TRUE") ? true : false;
 				}
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/videodock/views/VideoDock.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/videodock/views/VideoDock.mxml
index 0192e03427ba204f371110f36efd92c5f741e44b..367d02eb8c4203c9d2265694dc897de81f954446 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/videodock/views/VideoDock.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/videodock/views/VideoDock.mxml
@@ -22,28 +22,34 @@ $Id: $
 
 <MDIWindow xmlns="flexlib.mdi.containers.*" 
 		   xmlns:mx="http://www.adobe.com/2006/mxml" 
-		   creationComplete="init()" 
+		   creationComplete="onCreationComplete()" 
 		   implements="org.bigbluebutton.common.IBbbModuleWindow"
 		   title="{ResourceUtil.getInstance().getString('bbb.videodock.title')}"
-		   xmlns:mate="http://mate.asfusion.com/"
-		   layout="absolute" visible="false"
-		   horizontalAlign="center"
+		   xmlns:mate="http://mate.asfusion.com/" styleNameFocus="videoDockStyleFocus"
+		   layout="absolute" visible="false" styleNameNoFocus="videoDockStyleNoFocus"
+		   horizontalAlign="center" 
 		   verticalAlign="middle"
 		   resize="onChildAdd()">
 	
 	<mx:Script>
 		<![CDATA[
-			import mx.events.ChildExistenceChangedEvent;			
-			import org.bigbluebutton.common.LogUtil;
-			import org.bigbluebutton.common.events.CloseWindowEvent;
-			import org.bigbluebutton.common.events.DragWindowEvent;
-			import org.bigbluebutton.common.events.OpenWindowEvent;
-			import org.bigbluebutton.core.BBB;
-			import org.bigbluebutton.main.model.users.Conference;
-			import org.bigbluebutton.main.views.MainCanvas;
-			import org.bigbluebutton.modules.videoconf.business.VideoWindowItf;
-			import org.bigbluebutton.modules.videoconf.events.OpenVideoWindowEvent;
-			import org.bigbluebutton.util.i18n.ResourceUtil;
+      //backgroundImage="{backgroundImage}"
+      import com.asfusion.mate.events.Dispatcher;
+      
+      import mx.events.ChildExistenceChangedEvent;
+      
+      import org.bigbluebutton.common.Images;
+      import org.bigbluebutton.common.LogUtil;
+      import org.bigbluebutton.common.events.CloseWindowEvent;
+      import org.bigbluebutton.common.events.DragWindowEvent;
+      import org.bigbluebutton.common.events.OpenWindowEvent;
+      import org.bigbluebutton.core.BBB;
+      import org.bigbluebutton.core.events.ConnectAppEvent;
+      import org.bigbluebutton.main.model.users.Conference;
+      import org.bigbluebutton.main.views.MainCanvas;
+      import org.bigbluebutton.modules.videoconf.business.VideoWindowItf;
+      import org.bigbluebutton.modules.videoconf.events.OpenVideoWindowEvent;
+      import org.bigbluebutton.util.i18n.ResourceUtil;
 			
 			private var childrenDimension:Dictionary = new Dictionary();
 			private var borderColor:String;
@@ -59,9 +65,15 @@ $Id: $
 			
 			private var options:DockOptions = new DockOptions();
 			
-			private function init():void {				
+      private var images:Images = new Images();
+      
+      [Bindable]
+      private var backgroundImage:Class = images.video_dock_bg;
+      
+			private function onCreationComplete():void {				
 				this.showCloseButton = false;		
-				
+				this.showControls = options.showControls;
+        
 				this.minWidth = options.width;
 				this.minHeight = options.height;
 				this.maxWidth = this.parent.width;
@@ -74,6 +86,10 @@ $Id: $
 				addEventListener(ChildExistenceChangedEvent.CHILD_REMOVE, onChildRemove);
 				
 				if (options.maximize) this.maximize();
+        
+        var gDispatcher:Dispatcher = new Dispatcher();
+        var evt:ConnectAppEvent = new ConnectAppEvent(ConnectAppEvent.CONNECT_VIDEO_APP);
+        gDispatcher.dispatchEvent(evt);
 			}
 			
 			/**
@@ -122,33 +138,7 @@ $Id: $
 				//return MainCanvas.BOTTOM_RIGHT;
 				return options.position;
 			}
-			
-			private function onDragVideoWindow(e:DragWindowEvent):void{
-				switch (e.mode) {
-					case DragWindowEvent.DRAG:
-						if (hitTestPoint(e.mouseGlobal.x, e.mouseGlobal.y, true)) {
-							setStyle("borderColor","0xFF0000");
-							e.window.width = e.window.minWidth;
-							e.window.height = e.window.minHeight;
-						} else {
-							setStyle("borderColor",borderColor);
-							restoreWindowDimensions(e.window);
-						}
-						break;
-					case DragWindowEvent.DRAG_START:
-						borderColor = getStyle("borderColor");
-						removeVideoChild(e.window as VideoWindowItf);
-						saveWindowDimensions(e.window);
-						break;
-					case DragWindowEvent.DRAG_END:
-						setStyle("borderColor",borderColor);
-						restoreWindowDimensions(e.window);
-						if (hitTestPoint(e.mouseGlobal.x, e.mouseGlobal.y, true))
-							addVideoChild(e.window as VideoWindowItf);
-						break;
-				}
-			}
-			
+					
 			private function saveWindowDimensions(window:MDIWindow):void {
 				var dimensions:Object = {width:window.width, height:window.height};
 				childrenDimension[window] = dimensions;
@@ -171,13 +161,16 @@ $Id: $
 			
 			private function onCloseWindow(e:CloseWindowEvent):void {
 				// it should not just undock the window, it should close the window forever
-				if (isVideoWindow(e.window) && this.contains(e.window as VideoWindowItf))
-					this.removeChild(e.window as VideoWindowItf);
+				if (isVideoWindow(e.window) && this.contains(e.window as VideoWindowItf)) {
+          this.removeChild(e.window as VideoWindowItf);
+        }
+					
 			}
 			
 			private function onOpenWindow(e:OpenVideoWindowEvent):void {
-				if (isVideoWindow(e.window) && options.autoDock)
-					addVideoChild(e.window as VideoWindowItf);
+				if (isVideoWindow(e.window) && options.autoDock) {
+          addVideoChild(e.window as VideoWindowItf);
+        }					
 			}
 			
 			private function addVideoChild(window:VideoWindowItf):void {
@@ -197,7 +190,7 @@ $Id: $
 				window.minimizeBtn.visible = false;
 				window.maximizeRestoreBtn.visible = false;
 				window.resizable = false;
-//				window.buttonsEnabled = false;
+        window.draggable = false;
 
 				window.addEventListener(MouseEvent.CLICK, onWindowClick);
 
@@ -208,25 +201,6 @@ $Id: $
 				this.addChild(window);
 			}
 			
-			private function removeVideoChild(window:VideoWindowItf):void {
-				if (!this.contains(window))
-					return;
-				
-				window.minimizeBtn.visible = true;
-				window.maximizeRestoreBtn.visible = true;
-				window.resizable = true;
-//				window.buttonsEnabled = true;
-				
-				window.removeEventListener(MouseEvent.CLICK, onWindowClick);
-	
-				this.removeChild(window);
-				var e:OpenWindowEvent = new OpenWindowEvent(OpenWindowEvent.OPEN_WINDOW_EVENT);
-				e.window = window;
-				dispatchEvent(e);
-				
-				restoreWindowDimensions(window);
-			}
-			
 			override public function close(event:MouseEvent = null):void {
 				removeAllChildren();
 				super.close(event);
@@ -398,7 +372,6 @@ $Id: $
 		]]>
 	</mx:Script>
 	
-	<mate:Listener type="{DragWindowEvent.DRAG_WINDOW_EVENT}" method="onDragVideoWindow" />
 	<mate:Listener type="{OpenVideoWindowEvent.OPEN_VIDEO_WINDOW_EVENT}" method="onOpenWindow" />
 	<mate:Listener type="{CloseWindowEvent.CLOSE_WINDOW_EVENT}" method="onCloseWindow" />
 </MDIWindow>
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/viewers/events/ViewCameraEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/viewers/events/ViewCameraEvent.as
index 8cbd6f34d0e5977d600cc32e142e5f7635f63547..5ea142c1302bc2dc5b4816aef1a5482c00857b86 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/viewers/events/ViewCameraEvent.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/viewers/events/ViewCameraEvent.as
@@ -26,12 +26,12 @@ package org.bigbluebutton.modules.viewers.events
 		
 		public var stream:String;
 		public var viewedName:String;
-		public var userid:Number;
+		public var userID:String;
 		
-		public function ViewCameraEvent(userid:Number, stream:String, viewedName:String)
+		public function ViewCameraEvent(userID:String, stream:String, viewedName:String)
 		{
 			super(VIEW_CAMERA_EVENT,true);
-			this.userid = userid;
+			this.userID = userID;
 			this.stream = stream;
 			this.viewedName = viewedName;
 		}
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/viewers/views/StatusItemRenderer.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/viewers/views/StatusItemRenderer.mxml
index 08d3cfc54e392f3a5f0ef8a72507b761d6bce239..0aba9ab7925b2cf1b8cd5553d8f566951eddb62c 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/viewers/views/StatusItemRenderer.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/viewers/views/StatusItemRenderer.mxml
@@ -25,28 +25,31 @@
 	verticalScrollPolicy="off" horizontalScrollPolicy="off"
 	creationComplete="onCreationComplete()" > 
 	
-	<mate:Listener type="ViewVideoCloseEvent" method="onViewVideoCloseEvent"/>
+	<mate:Listener type="{StoppedViewingWebcamEvent.STOPPED_VIEWING_WEBCAM}" method="onViewVideoCloseEvent"/>
 	<mate:Listener type="{ViewersRollEvent.VIEWERS_ROLL_OVER}" method="onRollOver" />
 	<mate:Listener type="{ViewersRollEvent.VIEWERS_ROLL_OUT}" method="onRollOut" />
 	
 	<mx:Script>
 		<![CDATA[
-			import com.asfusion.mate.events.Dispatcher;			
-			import mx.controls.Alert;
-			import mx.events.ListEvent;			
-			import org.bigbluebutton.common.Images;
-			import org.bigbluebutton.common.LogUtil;
-			import org.bigbluebutton.common.Role;
-			import org.bigbluebutton.core.managers.UserManager;
-			import org.bigbluebutton.main.events.BBBEvent;
-			import org.bigbluebutton.main.model.users.Conference;
-			import org.bigbluebutton.main.model.users.events.KickUserEvent;
-			import org.bigbluebutton.main.model.users.events.LowerHandEvent;
-			import org.bigbluebutton.modules.viewers.events.ViewCameraEvent;
-			import org.bigbluebutton.util.i18n.ResourceUtil;
+      import com.asfusion.mate.events.Dispatcher;
+      
+      import mx.controls.Alert;
+      import mx.events.ListEvent;
+      
+      import org.bigbluebutton.common.Images;
+      import org.bigbluebutton.common.LogUtil;
+      import org.bigbluebutton.common.Role;
+      import org.bigbluebutton.core.managers.UserManager;
+      import org.bigbluebutton.main.events.BBBEvent;
+      import org.bigbluebutton.main.events.StoppedViewingWebcamEvent;
+      import org.bigbluebutton.main.model.users.Conference;
+      import org.bigbluebutton.main.model.users.events.KickUserEvent;
+      import org.bigbluebutton.main.model.users.events.LowerHandEvent;
+      import org.bigbluebutton.modules.viewers.events.ViewCameraEvent;
+      import org.bigbluebutton.util.i18n.ResourceUtil;
 			
 			private var images:Images = new Images();
-			[Bindable] public var kickIcon:Class = images.delete_icon;
+			[Bindable] public var kickIcon:Class = images.cancel;
 			
 			private var isModerator:Boolean = false;
 			private var allowKickUser:Boolean = false;
@@ -77,9 +80,9 @@
 				dispatchEvent(new ViewCameraEvent(data.userID, data.streamName, data.name));
    			}
    			
-   			private function onViewVideoCloseEvent(event:BBBEvent):void {
-   				LogUtil.debug("ViewWindoClosing event: " + event.message);
-   				if (data.streamName == event.message) {
+   			private function onViewVideoCloseEvent(event:StoppedViewingWebcamEvent):void {
+   				LogUtil.debug("ViewWindoClosing event: " + event.webcamUserID);
+   				if (data.userID == event.webcamUserID) {
    					streamIcon.enabled = true;
    				}
    			}
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/viewers/views/ViewersWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/viewers/views/ViewersWindow.mxml
index 12de02927512697071bc57d824534e58bcc3e24f..a2fd5a5a763f665dae3862d95207e18422747e2e 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/viewers/views/ViewersWindow.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/viewers/views/ViewersWindow.mxml
@@ -33,24 +33,20 @@
 
     <mx:Script>
         <![CDATA[
-          import com.asfusion.mate.events.Dispatcher;
-          
-          import flexlib.mdi.events.MDIWindowEvent;
-          
+          import com.asfusion.mate.events.Dispatcher;          
+          import flexlib.mdi.events.MDIWindowEvent;          
           import mx.binding.utils.BindingUtils;
           import mx.collections.ArrayCollection;
           import mx.controls.Alert;
           import mx.controls.listClasses.IListItemRenderer;
           import mx.events.DataGridEvent;
-          import mx.events.ListEvent;
-          
+          import mx.events.ListEvent;          
           import org.bigbluebutton.common.Images;
           import org.bigbluebutton.common.Role;
           import org.bigbluebutton.common.events.LocaleChangeEvent;
           import org.bigbluebutton.core.EventConstants;
           import org.bigbluebutton.core.events.CoreEvent;
           import org.bigbluebutton.core.managers.UserManager;
-          import org.bigbluebutton.main.events.ParticipantJoinEvent;
           import org.bigbluebutton.main.model.users.BBBUser;
           import org.bigbluebutton.main.model.users.Conference;
           import org.bigbluebutton.main.model.users.events.ConferenceCreatedEvent;
@@ -184,7 +180,7 @@
     
    <mx:ControlBar width="100%"> 
    		 <mx:Button id="presentBtn" label="{ResourceUtil.getInstance().getString('bbb.viewers.presentBtn.label')}" visible="{isModerator}"
-    	   			width="130" height="20"
+    	   			width="130" height="20" styleName="switchPresenterButtonStyle"
     	   			toolTip="{ResourceUtil.getInstance().getString('bbb.viewers.presentBtn.toolTip')}"
     	   			click="assignPresenterClicked()"/>
      	 <mx:Spacer width="100%"/>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardToolbar.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardToolbar.mxml
index 8459a14a72393f7f3097eb5f041c199cc5014485..3468973e19ea24409ebd84e22fb6ccd7e3913787 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardToolbar.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardToolbar.mxml
@@ -25,8 +25,7 @@
 		xmlns:view="org.bigbluebutton.modules.whiteboard.views.*"
 		xmlns:wbBtns="org.bigbluebutton.modules.whiteboard.views.buttons.*"
 		xmlns:mate="http://mate.asfusion.com/" creationComplete="onCreationComplete()"
-		visible="true" backgroundColor="0xCCCCCC" cornerRadius="5" borderStyle="solid" 
-	    paddingBottom="3" paddingTop="3" paddingLeft="3" paddingRight="3" >
+    visible="{showWhiteboardToolbar}" styleName="whiteboardToolbarStyle">
 	
 	<mate:Listener type="{MadePresenterEvent.SWITCH_TO_PRESENTER_MODE}" method="presenterMode" />
 	<mate:Listener type="{MadePresenterEvent.SWITCH_TO_VIEWER_MODE}" method="viewerMode" />
@@ -57,7 +56,7 @@
 	
 	<mx:Script>
 		<![CDATA[
-            import flash.ui.Keyboard;
+      import flash.ui.Keyboard;
 			import mx.events.MoveEvent;
 			import mx.events.ResizeEvent;
 			import mx.managers.CursorManager;			
@@ -82,7 +81,7 @@
 			import org.bigbluebutton.common.LogUtil;
 			
 			private var images:Images = new Images();
-            [Bindable] private var hand_icon:Class = images.hand_icon;
+      [Bindable] private var hand_icon:Class = images.hand_icon;
 			[Bindable] private var pencil_icon:Class = images.pencil_icon;
 			[Bindable] private var undo_icon:Class = images.undo_icon;
 			[Bindable] private var delete_icon:Class = images.delete_icon;
@@ -90,8 +89,8 @@
 			[Bindable] private var ellipse_icon:Class = images.circle_icon;
 			[Bindable] private var thick_icon:Class = images.whiteboard_thick;
 			[Bindable] private var thin_icon:Class = images.whiteboard_thin;
-            [Bindable] private var scribble_icon:Class = images.scribble_icon;
-            [Bindable] private var text_icon:Class = images.text_icon;            
+      [Bindable] private var scribble_icon:Class = images.scribble_icon;
+      [Bindable] private var text_icon:Class = images.text_icon;            
 			[Bindable] private var triangle_icon:Class = images.triangle_icon;
 			[Bindable] private var line_icon:Class = images.line_icon;
 			[Bindable] private var fill_icon:Class = images.fill_icon;
@@ -101,84 +100,71 @@
 			[Bindable] private var select_icon:Class = images.select_icon;
 			[Bindable] private var grid_icon:Class = images.grid_icon;
 			
+      [Bindable] private var showWhiteboardToolbar:Boolean = true;
+      
 			public var canvas:WhiteboardCanvas;
 			private var presentationWindow:PresentationWindow;
 			
 			[Bindable] private var colorPickerColours:Array = ['0x000000', '0xFFFFFF' , '0xFF0000', '0xFF8800',
                 '0xCCFF00', '0x00FF00', '0x00FF88', '0x00FFFF', '0x0088FF', '0x0000FF', '0x8800FF', '0xFF00FF', '0xC0C0C0'];
 			
-            private function onCreationComplete():void {
-                setToolType(WhiteboardConstants.TYPE_ZOOM, null);
-            }
+      private function onCreationComplete():void {
+        setToolType(WhiteboardConstants.TYPE_ZOOM, null);
+      }
                        
 			private function handleWhiteboardButtonPressed(e:WhiteboardButtonEvent):void {
-                setToolType(e.graphicType, e.toolType);
-            }
+        setToolType(e.graphicType, e.toolType);
+      }
             
-            private function setToolType(graphicType:String, toolType:String):void {                
-                canvas.setGraphicType(graphicType);
-                canvas.setTool(toolType);
+      private function setToolType(graphicType:String, toolType:String):void {                
+        canvas.setGraphicType(graphicType);
+        canvas.setTool(toolType);
                 
-                if (panzoomBtn != null) {
-                    panzoomBtn.setTool(graphicType, toolType);
-                }
+        if (panzoomBtn != null) {
+          panzoomBtn.setTool(graphicType, toolType);
+        }
                 
-                if (scribbleBtn != null) {
-                    scribbleBtn.setTool(graphicType, toolType); 
-                }
+        if (scribbleBtn != null) {
+          scribbleBtn.setTool(graphicType, toolType); 
+        }
                                 
-                if (rectangleBtn != null) {
-                    rectangleBtn.setTool(graphicType, toolType); 
-                }
+        if (rectangleBtn != null) {
+          rectangleBtn.setTool(graphicType, toolType); 
+        }
                 
-                if (circleBtn != null) {
-                    circleBtn.setTool(graphicType, toolType);
-                }
+        if (circleBtn != null) {
+          circleBtn.setTool(graphicType, toolType);
+        }
                 
-                if (triangleBtn != null) {
-                    triangleBtn.setTool(graphicType, toolType);
-                }
+        if (triangleBtn != null) {
+          triangleBtn.setTool(graphicType, toolType);
+        }
                                 
-                if (lineBtn != null) {
-                    lineBtn.setTool(graphicType, toolType);
-                }
+        if (lineBtn != null) {
+          lineBtn.setTool(graphicType, toolType);
+        }
                 
-                if (textBtn != null) {
-                    textBtn.setTool(graphicType, toolType);
-                }
+        if (textBtn != null) {
+          textBtn.setTool(graphicType, toolType);
+        }
                                 
-                if(graphicType == WhiteboardConstants.TYPE_CLEAR) {
-                    dispatchEvent(new WhiteboardDrawEvent(WhiteboardDrawEvent.CLEAR));
-                }
+        if(graphicType == WhiteboardConstants.TYPE_CLEAR) {
+          dispatchEvent(new WhiteboardDrawEvent(WhiteboardDrawEvent.CLEAR));
+        }
                 
-                if (graphicType == WhiteboardConstants.TYPE_UNDO) {
-                    sendUndoCommand();
-                }
+        if (graphicType == WhiteboardConstants.TYPE_UNDO) {
+          sendUndoCommand();
+        }
 			}
 						
-			/**
-			 * Sets the color 
-			 * @param e event containing the color (e.target.selectedColor)
-			 * 
-			 */		
 			protected function changeColor(e:Event):void {
 				canvas.changeColor(e);
 			}
 			
-			/**
-			 * Sets the fill color 
-			 * @param e event containing the color (e.target.selectedColor)
-			 * 
-			 */		
 			protected function changeFillColor(e:Event):void {
 				canvas.changeFillColor(e);
 			}
 			
-			/**
-			 * Sets the thickness 
-			 * @param e event containing the thickness (e.target.value)
-			 * 
-			 */		
 			protected function changeThickness(e:Event):void {
 				canvas.changeThickness(e);
 			}
@@ -192,61 +178,69 @@
 			}
 						
 			private function presenterMode(e:MadePresenterEvent):void {
-                if (canvas == null) return;
+        if (canvas == null) return;
+        
 				canvas.makeTextObjectsEditable(e);
-                this.visible = true;
-                setToolType(WhiteboardConstants.TYPE_ZOOM, null);
+        hideOrDisplayToolbar();
+        setToolType(WhiteboardConstants.TYPE_ZOOM, null);
 			}
 			
 			private function viewerMode(e:MadePresenterEvent):void {
-				canvas.makeTextObjectsUneditable(e);
-			    this.visible = false;
-            }
+        canvas.makeTextObjectsUneditable(e);
+        hideOrDisplayToolbar();
+      }
 			
 			private function undoShortcut(e:ShortcutEvent):void{
 				LogUtil.debug("Ctrl-Z got into undoShortcut");
 				sendUndoCommand();
 			}
 			
-			private function showToolbar(e:PresentationEvent):void {
-				this.visible = true;
-			}
-			
 			private function sendUndoCommand():void {
-				if (!canvas.isPageEmpty()) 
+				if (!canvas.isPageEmpty()) {          
 					dispatchEvent(new WhiteboardDrawEvent(WhiteboardDrawEvent.UNDO));
+        }
 			}
 						
 			public function positionToolbar(window:PresentationWindow):void {
+        trace("Positioning whiteboard toolbar");
 				presentationWindow = window;
 				presentationWindow.addEventListener(MoveEvent.MOVE, setPositionAndDepth);
 				presentationWindow.addEventListener(ResizeEvent.RESIZE, setPositionAndDepth);
 				presentationWindow.addEventListener(MouseEvent.CLICK, setPositionAndDepth);
 				this.x = presentationWindow.x + presentationWindow.width + 3;
 				this.y = presentationWindow.y + 30;
+        hideOrDisplayToolbar();
 				parent.setChildIndex(this, parent.numChildren - 1);
 			}
 			
 			private function setPositionAndDepth(e:Event = null):void {
 				this.x = presentationWindow.x + presentationWindow.width + 3;
 				this.y = presentationWindow.y + 30;
+        hideOrDisplayToolbar();
 				parent.setChildIndex(this, parent.numChildren - 1);
 			}
 			
 			private function closeToolbar(e:StopWhiteboardModuleEvent):void {
 				parent.removeChild(this);
 			}
-            
+      
+      private function hideOrDisplayToolbar():void {
+        if (presentationWindow != null && presentationWindow.visible && ! presentationWindow.minimized) {
+          trace("Positioning whiteboard toolbar: showing");
+          showWhiteboardToolbar = true;
+        } else {
+          trace("Positioning whiteboard toolbar: not showing");
+          showWhiteboardToolbar = false;
+        }
+      }
            
-            private function graphicObjSelected(event:GraphicObjectFocusEvent):void  {
-                var gobj:GraphicObject = event.data;
-//                LogUtil.debug("!!!!SELECTED:" );
-            }
+      private function graphicObjSelected(event:GraphicObjectFocusEvent):void  {
+        var gobj:GraphicObject = event.data;
+      }
             
-            private function graphicObjDeselected(event:GraphicObjectFocusEvent):void  {
-                var gobj:GraphicObject = event.data;
- //               LogUtil.debug("!!!!DESELECTED:" + " " );
-            }
+      private function graphicObjDeselected(event:GraphicObjectFocusEvent):void  {
+        var gobj:GraphicObject = event.data;
+      }
 			           
 		]]>
 	</mx:Script>
@@ -255,20 +249,20 @@
 	that identifies the "category" of the tool (ex. shape vs text), and the other specifies the 
 	tool itself (ex. line tool vs triangle tool, even though both are "shapes")
 	-->
-    <wbBtns:PanZoomButton id="panzoomBtn"/>
-    <mx:Spacer height="10"/>
-	<wbBtns:ScribbleButton id="scribbleBtn"/>
-	<wbBtns:RectangleButton id="rectangleBtn"/>
-	<wbBtns:CircleButton id="circleBtn"/>
-	<wbBtns:TriangleButton id="triangleBtn"/>
-	<wbBtns:LineButton id="lineBtn"/>
-	<wbBtns:TextButton id="textBtn"/>
+  <wbBtns:PanZoomButton id="panzoomBtn" visible="{showWhiteboardToolbar}"/>
+  <mx:Spacer height="10" visible="{showWhiteboardToolbar}"/>
+	<wbBtns:ScribbleButton id="scribbleBtn" visible="{showWhiteboardToolbar}"/>
+	<wbBtns:RectangleButton id="rectangleBtn" visible="{showWhiteboardToolbar}"/>
+	<wbBtns:CircleButton id="circleBtn" visible="{showWhiteboardToolbar}"/>
+	<wbBtns:TriangleButton id="triangleBtn" visible="{showWhiteboardToolbar}"/>
+	<wbBtns:LineButton id="lineBtn" visible="{showWhiteboardToolbar}"/>
+	<wbBtns:TextButton id="textBtn" visible="{showWhiteboardToolbar}"/>
 		
-	<mx:Spacer height="5"/>
-	<wbBtns:ClearButton id="clearBtn"/>
-	<wbBtns:UndoButton id="undoBtn"/>
+	<mx:Spacer height="5" visible="{showWhiteboardToolbar}"/>
+	<wbBtns:ClearButton id="clearBtn" visible="{showWhiteboardToolbar}"/>
+	<wbBtns:UndoButton id="undoBtn" visible="{showWhiteboardToolbar}" />
 	
-	<mx:Spacer height="5"/>
+	<mx:Spacer height="5" visible="{showWhiteboardToolbar}"/>
 	
 	<!--
 	Properties that were removed from original color picker:
@@ -281,14 +275,16 @@
 	of ColorPickers, one for the "line" color for the outlines of shapes, and the other for
 	the "fill" color that is used only if "fill" is enabled in WhiteboardCanvasModel
 	-->
-	<mx:ColorPicker change="changeColor(event)" id="cpik"  selectedColor="0x000000" toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.color')}"/>
+	<mx:ColorPicker change="changeColor(event)" id="cpik"  visible="{showWhiteboardToolbar}"
+                  selectedColor="0x000000" width="30" 
+                  toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.color')}"/>
    
-	<mx:Spacer height="3" />
-	<mx:Image source="{thick_icon}" horizontalAlign="center" width="20"/>
-	<mx:VSlider height="50" id="sld" change="changeThickness(event)" 
+	<mx:Spacer height="3" visible="{showWhiteboardToolbar}"/>
+	<mx:Image source="{thick_icon}" horizontalAlign="center" width="30" visible="{showWhiteboardToolbar}"/>
+	<mx:VSlider height="50" id="sld" change="changeThickness(event)" visible="{showWhiteboardToolbar}"
 				toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.thickness')}" 
-				minimum="2" maximum="20" 
+				minimum="2" maximum="30" 
 				useHandCursor="true" value="2" showDataTip="true" snapInterval="1" dataTipOffset="0" labelOffset="0" />
-	<mx:Image source="{thin_icon}" horizontalAlign="center" width="20" />
+	<mx:Image source="{thin_icon}" horizontalAlign="center" width="30" visible="{showWhiteboardToolbar}"/>
 	
 </mx:VBox>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/CircleButton.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/CircleButton.mxml
index 04c46c32a483ed9f20387c3d91fb9af044ee3aac..a887c70ac79440138d5301f611b4e03cc7db8e14 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/CircleButton.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/CircleButton.mxml
@@ -1,8 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <mx:Button xmlns:mx="http://www.adobe.com/2006/mxml"
-		   width="20" height="20" 
-		   click="onClick()" 
-		   icon="{ellipse_icon}" 
+           width="30" height="30"
+		   click="onClick()" styleName="whiteboardCircleButtonStyle"
 		   toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.ellipse')}" 
 		   toggle="true">
 	<mx:Script>
@@ -12,10 +11,7 @@
 			import org.bigbluebutton.modules.whiteboard.business.shapes.WhiteboardConstants;
 			import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent;
 			import org.bigbluebutton.util.i18n.ResourceUtil;
-			
-			private var images:Images = new Images();			
-			[Bindable] private var ellipse_icon:Class = images.circle_icon;
-			
+						
 			private function onClick():void {
 				var event:WhiteboardButtonEvent = new WhiteboardButtonEvent(WhiteboardButtonEvent.WHITEBOARD_BUTTON_PRESSED);
 				event.graphicType = WhiteboardConstants.TYPE_SHAPE;
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/ClearButton.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/ClearButton.mxml
index dd666c2301d81c58b948e170250f806600eb9849..221cfa39a80a8c62c522b24fc0be46990ab134d1 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/ClearButton.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/ClearButton.mxml
@@ -1,17 +1,14 @@
 <?xml version="1.0" encoding="utf-8"?>
 <mx:Button xmlns:mx="http://www.adobe.com/2006/mxml"
-		   width="20" height="20" click="onClick()" icon="{delete_icon}" 
+           width="30" height="30"
+       click="onClick()" styleName="whiteboardClearButtonStyle"
 		   toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.clear')}">
 	<mx:Script>
 		<![CDATA[
-            import org.bigbluebutton.common.Images;
             import org.bigbluebutton.modules.whiteboard.business.shapes.WhiteboardConstants;
             import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent;
             import org.bigbluebutton.util.i18n.ResourceUtil;
-			
-			private var images:Images = new Images();
-			[Bindable] private var delete_icon:Class = images.delete_icon;
-			
+						
             private function onClick():void {
                 var event:WhiteboardButtonEvent = new WhiteboardButtonEvent(WhiteboardButtonEvent.WHITEBOARD_BUTTON_PRESSED);
                 event.graphicType = WhiteboardConstants.TYPE_CLEAR;
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/LineButton.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/LineButton.mxml
index f6334b33bb728f04291d24fc6764dce048af7b2a..d22ef38a9341cbbb294943ac9496845c79ef4759 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/LineButton.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/LineButton.mxml
@@ -1,18 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
 <mx:Button xmlns:mx="http://www.adobe.com/2006/mxml"
-		   width="20" height="20" click="onClick()" icon="{line_icon}" 
+           width="30" height="30"
+       click="onClick()" styleName="whiteboardLineButtonStyle"
 		   toolTip="{ResourceUtil.getInstance().getString('ltbcustom.bbb.highlighter.toolbar.line')}" toggle="true">
 	<mx:Script>
 		<![CDATA[
-            import org.bigbluebutton.common.Images;
             import org.bigbluebutton.modules.whiteboard.business.shapes.DrawObject;
             import org.bigbluebutton.modules.whiteboard.business.shapes.WhiteboardConstants;
             import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent;
             import org.bigbluebutton.util.i18n.ResourceUtil;
-			
-			private var images:Images = new Images();
-			[Bindable] private var line_icon:Class = images.line_icon;
-			
+						
             private function onClick():void {
                 var event:WhiteboardButtonEvent = new WhiteboardButtonEvent(WhiteboardButtonEvent.WHITEBOARD_BUTTON_PRESSED);
                 event.graphicType = WhiteboardConstants.TYPE_SHAPE;
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/PanZoomButton.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/PanZoomButton.mxml
index af859c73082c15f9573e91e829c85822d7cff0d1..bca208eef6abd993428d3ca79a1bc4e1c28428bb 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/PanZoomButton.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/PanZoomButton.mxml
@@ -1,18 +1,14 @@
 <?xml version="1.0" encoding="utf-8"?>
 <mx:Button xmlns:mx="http://www.adobe.com/2006/mxml"
-		   width="20" height="20" click="onClick()" icon="{hand_icon}" 
+           width="30" height="30"
+       click="onClick()" styleName="whiteboardPanZoomButtonStyle"
 		   toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.panzoom')}" toggle="true">
 	<mx:Script>
 		<![CDATA[
-            import org.bigbluebutton.common.Images;
             import org.bigbluebutton.modules.whiteboard.business.shapes.WhiteboardConstants;
             import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent;
             import org.bigbluebutton.util.i18n.ResourceUtil;
-			
-			private var images:Images = new Images();
-			
-			[Bindable] private var hand_icon:Class = images.hand_icon;
-			
+						
             private function onClick():void {
                 var event:WhiteboardButtonEvent = new WhiteboardButtonEvent(WhiteboardButtonEvent.WHITEBOARD_BUTTON_PRESSED);
                 event.graphicType = WhiteboardConstants.TYPE_ZOOM;
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/RectangleButton.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/RectangleButton.mxml
index 8d17ffa9dab688dd50d32e8508c95e404f8ea1bb..65dacddc947c7e2ea07e1fd0d1d64c2334852b31 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/RectangleButton.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/RectangleButton.mxml
@@ -1,19 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
 <mx:Button xmlns:mx="http://www.adobe.com/2006/mxml"
-		   width="20" height="20"
-		   click="onClick()" 
-		   icon="{rectangle_icon}" toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.rectangle')}" toggle="true">
+           width="30" height="30"
+		   click="onClick()" styleName="whiteboardRectangleButtonStyle"
+		   toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.rectangle')}" toggle="true">
 	<mx:Script>
 		<![CDATA[
-            import org.bigbluebutton.common.Images;
             import org.bigbluebutton.modules.whiteboard.business.shapes.DrawObject;
             import org.bigbluebutton.modules.whiteboard.business.shapes.WhiteboardConstants;
             import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent;
             import org.bigbluebutton.util.i18n.ResourceUtil;
-			
-			private var images:Images = new Images();
-			[Bindable] private var rectangle_icon:Class = images.square_icon;
-			
+				
             private function onClick():void {
                 var event:WhiteboardButtonEvent = new WhiteboardButtonEvent(WhiteboardButtonEvent.WHITEBOARD_BUTTON_PRESSED);
                 event.graphicType = WhiteboardConstants.TYPE_SHAPE;
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/ScribbleButton.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/ScribbleButton.mxml
index 97f7fd2d32f47f902c18e2b93752fa553b982666..6a6e6571fc2f0b419db4c810fdfe3aeaac2ab68b 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/ScribbleButton.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/ScribbleButton.mxml
@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <mx:Button xmlns:mx="http://www.adobe.com/2006/mxml"
-		   width="20" height="20" click="onClick()"  
-		   icon="{scribble_icon}" toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.pencil')}" 
+           width="30" height="30"
+       click="onClick()"  styleName="whiteboardScribbleButtonStyle"
+		   toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.pencil')}" 
 		   toggle="true" selected="true">
 	<mx:Script>
 		<![CDATA[
@@ -10,11 +11,7 @@
             import org.bigbluebutton.modules.whiteboard.business.shapes.WhiteboardConstants;
             import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent;
             import org.bigbluebutton.util.i18n.ResourceUtil;
-			
-			private var images:Images = new Images();
-			
-			[Bindable] private var scribble_icon:Class = images.scribble_icon;
-			
+						
             private function onClick():void {
                 var event:WhiteboardButtonEvent = new WhiteboardButtonEvent(WhiteboardButtonEvent.WHITEBOARD_BUTTON_PRESSED);
                 event.graphicType = WhiteboardConstants.TYPE_SHAPE;
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/TextButton.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/TextButton.mxml
index c0f7e59f8efbe0d48e52ef0d38632075c7626291..10d26e2234b42319c03d7a04b2f7b61315b3c8d3 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/TextButton.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/TextButton.mxml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <mx:Button xmlns:mx="http://www.adobe.com/2006/mxml"
-		   width="20" height="20" click="onClick()" icon="{text_icon}" 
+           width="30" height="30"
+       click="onClick()" styleName="whiteboardTextButtonStyle"
 		   toolTip="{ResourceUtil.getInstance().getString('ltbcustom.bbb.highlighter.toolbar.text')}" toggle="true">
 	<mx:Script>
 		<![CDATA[
@@ -8,10 +9,7 @@
             import org.bigbluebutton.modules.whiteboard.business.shapes.WhiteboardConstants;
             import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent;
             import org.bigbluebutton.util.i18n.ResourceUtil;
-			
-			private var images:Images = new Images();
-			[Bindable] private var text_icon:Class = images.text_icon;
-			
+						
             private function onClick():void {
                 var event:WhiteboardButtonEvent = new WhiteboardButtonEvent(WhiteboardButtonEvent.WHITEBOARD_BUTTON_PRESSED);
                 event.graphicType = WhiteboardConstants.TYPE_TEXT;
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/TriangleButton.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/TriangleButton.mxml
index 0a603f1ac46bd334f11356d8ef3d508659543839..25623b78bb88a608bb634cd2ea293d92a2a53772 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/TriangleButton.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/TriangleButton.mxml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <mx:Button xmlns:mx="http://www.adobe.com/2006/mxml"
-		   width="20" height="20" click="onClick()" icon="{triangle_icon}" 
+           width="30" height="30"
+       click="onClick()" styleName="whiteboardTriangleButtonStyle"
 		   toolTip="{ResourceUtil.getInstance().getString('ltbcustom.bbb.highlighter.toolbar.triangle')}" 
 		   toggle="true">
 	<mx:Script>
@@ -10,10 +11,7 @@
             import org.bigbluebutton.modules.whiteboard.business.shapes.WhiteboardConstants;
             import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent;
             import org.bigbluebutton.util.i18n.ResourceUtil;
-			
-			private var images:Images = new Images();
-			[Bindable] private var triangle_icon:Class = images.triangle_icon;
-			
+					
             private function onClick():void {
                 var event:WhiteboardButtonEvent = new WhiteboardButtonEvent(WhiteboardButtonEvent.WHITEBOARD_BUTTON_PRESSED);
                 event.graphicType = WhiteboardConstants.TYPE_SHAPE;
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/UndoButton.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/UndoButton.mxml
index 347324984559ab5be9bd66d747bdd7b85ec1311e..6affcb9711819dae0857f84f7388171ad42d91e1 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/UndoButton.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/buttons/UndoButton.mxml
@@ -1,17 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
 <mx:Button xmlns:mx="http://www.adobe.com/2006/mxml"
-		   width="20" height="20" click="onClick()" icon="{undo_icon}" 
+           width="30" height="30"
+       click="onClick()" styleName="whiteboardUndoButtonStyle"
 		   toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.undo')}">
 	<mx:Script>
 		<![CDATA[
-            import org.bigbluebutton.common.Images;
+
             import org.bigbluebutton.modules.whiteboard.business.shapes.WhiteboardConstants;
             import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent;
             import org.bigbluebutton.util.i18n.ResourceUtil;
-			
-			private var images:Images = new Images();
-			[Bindable] private var undo_icon:Class = images.undo_icon;
-			
+						
             private function onClick():void {
                 var event:WhiteboardButtonEvent = new WhiteboardButtonEvent(WhiteboardButtonEvent.WHITEBOARD_BUTTON_PRESSED);
                 event.graphicType = WhiteboardConstants.TYPE_UNDO;
diff --git a/bigbluebutton-client/src/org/red5/flash/bwcheck/BandwidthDetection.as b/bigbluebutton-client/src/org/red5/flash/bwcheck/BandwidthDetection.as
new file mode 100644
index 0000000000000000000000000000000000000000..7d1160ab9bd1bb47ec3e526c5582ac4203dc24fd
--- /dev/null
+++ b/bigbluebutton-client/src/org/red5/flash/bwcheck/BandwidthDetection.as
@@ -0,0 +1,53 @@
+package org.red5.flash.bwcheck
+{
+	import flash.events.EventDispatcher;
+	import flash.net.NetConnection;
+	import org.red5.flash.bwcheck.events.BandwidthDetectEvent;
+	
+	[Event(name=BandwidthDetectEvent.DETECT_STATUS, type="org.red5.flash.bwcheck.events.BandwidthDetectEvent")]
+	[Event(name=BandwidthDetectEvent.DETECT_COMPLETE, type="org.red5.flash.bwcheck.events.BandwidthDetectEvent")]
+	
+	public class BandwidthDetection extends EventDispatcher
+	{
+		protected var nc:NetConnection;
+		
+		public function BandwidthDetection()
+		{
+			
+		}
+		
+		protected function dispatch(info:Object, eventName:String):void
+		{
+			var event:BandwidthDetectEvent = new BandwidthDetectEvent(eventName);
+			event.info = info;
+			dispatchEvent(event);
+		}
+		
+		protected function dispatchStatus(info:Object):void
+		{
+			var event:BandwidthDetectEvent = new BandwidthDetectEvent(BandwidthDetectEvent.DETECT_STATUS);
+			event.info = info;
+			dispatchEvent(event);
+		}
+		
+		protected function dispatchComplete(info:Object):void
+		{
+			var event:BandwidthDetectEvent = new BandwidthDetectEvent(BandwidthDetectEvent.DETECT_COMPLETE);
+			event.info = info;
+			dispatchEvent(event);
+		}
+		
+		protected function dispatchFailed(info:Object):void
+		{
+			var event:BandwidthDetectEvent = new BandwidthDetectEvent(BandwidthDetectEvent.DETECT_FAILED);
+			event.info = info;
+			dispatchEvent(event);
+		}
+		
+		public function set connection(connect:NetConnection):void
+		{
+			nc = connect;
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/red5/flash/bwcheck/ClientServerBandwidth.as b/bigbluebutton-client/src/org/red5/flash/bwcheck/ClientServerBandwidth.as
new file mode 100644
index 0000000000000000000000000000000000000000..22a97d38461ec4467f5740123b227bb07d59aad7
--- /dev/null
+++ b/bigbluebutton-client/src/org/red5/flash/bwcheck/ClientServerBandwidth.as
@@ -0,0 +1,143 @@
+package org.red5.flash.bwcheck
+{
+	
+	import flash.net.Responder;
+	
+	public class ClientServerBandwidth extends BandwidthDetection
+	{
+		
+		private var res:Responder;
+		private var payload:Array = new Array();
+		
+		private var latency:int = 0;
+		private var cumLatency:int = 1;
+		private var bwTime:int = 0;
+		private var count:int = 0;
+		private var sent:int = 0;
+		private var kbitUp:int = 0;
+		private var KBytes:int = 0;
+		private var deltaUp:int = 0;
+		private var deltaTime:int = 0;
+		private var overhead:int = 0;
+		private var pakInterval:int = 0;
+		private var timePassed:int = 0;
+		private var now:int = 0;
+		
+		private var pakSent:Array = new Array();
+		private var pakRecv:Array = new Array();
+		private var beginningValues:Object = {};
+		private var info:Object = new Object();
+		
+		private var _service:String;
+		
+		public function ClientServerBandwidth()
+		{
+			for (var i:int = 0; i < 1200; i++){
+				payload[i] = Math.random();	//16K approx
+			}
+			
+			res = new Responder(onResult, onStatus);
+			
+			
+		}
+		
+		public function set service(service:String):void
+		{
+			_service = service;
+		}
+		
+		public function start():void
+		{
+			nc.client = this;
+			var obj:Array = new Array();
+			nc.call(_service, res);
+		}
+		
+		private function onResult(obj:Object):void
+		{
+			this.now = (new Date()).getTime()/1;
+			if(sent == 0) {
+				this.beginningValues = obj;
+				this.beginningValues.time = now;
+				this.pakSent[sent++] = now;
+				nc.call(_service, res, now);
+			} else {
+				this.pakRecv[this.count] = now;
+				this.pakInterval = (this.pakRecv[this.count] - this.pakSent[this.count])*1;
+				this.count++;
+				this.timePassed = (now - this.beginningValues.time);
+				
+				if (this.count == 1) {
+					this.latency = Math.min(timePassed, 800);
+					this.latency = Math.max(this.latency, 10);
+					this.overhead = obj.cOutBytes - this.beginningValues.cOutBytes;
+					
+					this.pakSent[sent++] = now;
+					nc.call(_service, res, now, payload);
+					dispatchStatus(info);
+					
+				}
+				// If we have a hi-speed network with low latency send more to determine
+				// better bandwidth numbers, send no more than 6 packets
+				if ( (this.count >= 1) && (timePassed<1000))
+				{
+					this.pakSent[sent++] = now;
+					this.cumLatency++;
+					nc.call(_service, res, now, payload);
+					dispatchStatus(info);
+				} else if ( this.sent == this.count ) {	
+					// See if we need to normalize latency
+					if ( this.latency >= 100 )
+					{ // make sure we detect sattelite and modem correctly
+						if (  this.pakRecv[1] - this.pakRecv[0] > 1000 )
+						{
+							this.latency = 100;
+						}
+					}
+					payload = new Array();
+					// Got back responses for all the packets compute the bandwidth.
+					var stats:Object = obj;
+					deltaUp = (stats.cOutBytes - this.beginningValues.cOutBytes)*8/1000;
+					deltaTime = ((now - this.beginningValues.time) - (this.latency * this.cumLatency) )/1000;
+					if ( deltaTime <= 0 )
+						deltaTime = (now - this.beginningValues.time)/1000;
+					
+					kbitUp = Math.round(deltaUp/deltaTime);
+					KBytes = (stats.cOutBytes - this.beginningValues.cOutBytes)/1024;
+					
+					var info:Object = new Object();
+					info.kbitUp = kbitUp;
+					info.deltaUp = deltaUp;
+					info.deltaTime = deltaTime;
+					info.latency = latency;
+					info.KBytes = KBytes;
+					
+					dispatchComplete(info);
+				}
+			}
+		}
+		
+		override protected function dispatchStatus(obj:Object):void
+		{
+			obj.count = this.count;
+			obj.sent = this.sent;
+			obj.timePassed = timePassed;
+			obj.latency = this.latency;
+			obj.overhead = this.overhead;
+			obj.pakInterval = this.pakInterval;
+			obj.cumLatency = this.cumLatency;
+
+			super.dispatchStatus(info);	
+		}
+		
+		private function onStatus(obj:Object):void
+		{
+			switch (obj.code)
+			{
+				case "NetConnection.Call.Failed":
+					dispatchFailed(obj);
+				break;
+			}
+		}
+	}
+}
diff --git a/bigbluebutton-client/src/org/red5/flash/bwcheck/ServerClientBandwidth.as b/bigbluebutton-client/src/org/red5/flash/bwcheck/ServerClientBandwidth.as
new file mode 100644
index 0000000000000000000000000000000000000000..84b892589b001befab7f42b9ae3ec7a3fb18520d
--- /dev/null
+++ b/bigbluebutton-client/src/org/red5/flash/bwcheck/ServerClientBandwidth.as
@@ -0,0 +1,55 @@
+package org.red5.flash.bwcheck
+{
+	import flash.net.Responder;
+	
+	public class ServerClientBandwidth extends BandwidthDetection
+	{
+		
+		private var _service:String;
+		private var info:Object = new Object();
+		private var res:Responder;
+		
+		public function ServerClientBandwidth()
+		{
+			res = new Responder(onResult, onStatus);
+		}
+
+		public function onBWCheck(obj:Object):void
+		{
+				dispatchStatus(obj);
+		}
+			
+		public function onBWDone(obj:Object):void 
+		{ 
+			dispatchComplete(obj);
+		} 
+		
+		public function set service(service:String):void
+		{
+			_service = service;
+		}
+		
+		public function start():void
+		{
+			nc.client = this;
+			nc.call(_service,res);
+		}
+		
+		private function onResult(obj:Object):void
+		{
+			dispatchStatus(obj);
+				
+		}
+		
+		private function onStatus(obj:Object):void
+		{
+			switch (obj.code)
+			{
+				case "NetConnection.Call.Failed":
+					dispatchFailed(obj);
+				break;
+			}
+
+		}
+	}
+}
diff --git a/bigbluebutton-client/src/org/red5/flash/bwcheck/app/BandwidthDetectionApp.as b/bigbluebutton-client/src/org/red5/flash/bwcheck/app/BandwidthDetectionApp.as
new file mode 100644
index 0000000000000000000000000000000000000000..77b3e2f4b7c9b7ee847af6e415f879148abeb852
--- /dev/null
+++ b/bigbluebutton-client/src/org/red5/flash/bwcheck/app/BandwidthDetectionApp.as
@@ -0,0 +1,131 @@
+package org.red5.flash.bwcheck.app
+{
+	import flash.events.NetStatusEvent;
+	import flash.net.NetConnection;
+	import flash.net.Responder;
+	
+	import mx.core.Application;
+	
+	import org.bigbluebutton.common.LogUtil;
+
+	import org.red5.flash.bwcheck.ClientServerBandwidth;
+	import org.red5.flash.bwcheck.ServerClientBandwidth;
+	import org.red5.flash.bwcheck.events.BandwidthDetectEvent;
+	
+	public class BandwidthDetectionApp extends Application
+	{
+		private var _serverURL:String = "localhost";
+		private var _serverApplication:String = "";
+		private var _clientServerService:String = "";
+		private var _serverClientService:String = "";
+		
+		private var nc:NetConnection;
+		
+		public function BandwidthDetectionApp()
+		{
+			
+		}
+		
+		public function set serverURL(url:String):void
+		{
+			_serverURL = url;
+		}
+		
+		public function set serverApplication(app:String):void
+		{
+			_serverApplication = app;
+		}
+		
+		public function set clientServerService(service:String):void
+		{
+			_clientServerService = service;
+		}
+		
+		public function set serverClientService(service:String):void
+		{
+			_serverClientService = service;
+		}
+		
+		public function connect():void
+		{
+			nc = new NetConnection();
+			nc.objectEncoding = flash.net.ObjectEncoding.AMF0;
+			nc.client = this;
+			nc.addEventListener(NetStatusEvent.NET_STATUS, onStatus);	
+			nc.connect("rtmp://" + _serverURL + "/" + _serverApplication);
+		}
+		
+		
+		private function onStatus(event:NetStatusEvent):void
+		{
+			switch (event.info.code)
+			{
+				case "NetConnection.Connect.Success":
+					LogUtil.debug(event.info.code);
+					LogUtil.debug("Detecting Server Client Bandwidth");
+					ServerClient();
+				break;	
+			}
+			
+		}
+		
+		public function ClientServer():void
+		{
+			var clientServer:ClientServerBandwidth  = new ClientServerBandwidth();
+			//connect();
+			clientServer.connection = nc;
+			clientServer.service = _clientServerService;
+			clientServer.addEventListener(BandwidthDetectEvent.DETECT_COMPLETE,onClientServerComplete);
+			clientServer.addEventListener(BandwidthDetectEvent.DETECT_STATUS,onClientServerStatus);
+			clientServer.addEventListener(BandwidthDetectEvent.DETECT_FAILED,onDetectFailed);
+			clientServer.start();
+		}
+		
+		public function ServerClient():void
+		{
+			var serverClient:ServerClientBandwidth = new ServerClientBandwidth();
+			//connect();
+			serverClient.connection = nc;
+			serverClient.service = _serverClientService;
+			serverClient.addEventListener(BandwidthDetectEvent.DETECT_COMPLETE,onServerClientComplete);
+			serverClient.addEventListener(BandwidthDetectEvent.DETECT_STATUS,onServerClientStatus);
+			serverClient.addEventListener(BandwidthDetectEvent.DETECT_FAILED,onDetectFailed);
+			
+			serverClient.start();
+		}
+		
+		public function onDetectFailed(event:BandwidthDetectEvent):void
+		{
+			LogUtil.debug("Detection failed with error: " + event.info.application + " " + event.info.description);
+		}
+		
+		public function onClientServerComplete(event:BandwidthDetectEvent):void
+		{			
+			LogUtil.debug("kbitUp = " + event.info.kbitUp + ", deltaUp= " + event.info.deltaUp + ", deltaTime = " + event.info.deltaTime + ", latency = " + event.info.latency + " KBytes " + event.info.KBytes);
+			LogUtil.debug("Client to Server Bandwidth Detection Complete");
+		}
+		
+		public function onClientServerStatus(event:BandwidthDetectEvent):void
+		{
+			if (event.info) {
+				LogUtil.debug("count: "+event.info.count+ " sent: "+event.info.sent+" timePassed: "+event.info.timePassed+" latency: "+event.info.latency+" overhead:  "+event.info.overhead+" packet interval: " + event.info.pakInterval + " cumLatency: " + event.info.cumLatency);
+			}
+		}
+		
+		public function onServerClientComplete(event:BandwidthDetectEvent):void
+		{
+			LogUtil.debug("kbit Down: " + event.info.kbitDown + " Delta Down: " + event.info.deltaDown + " Delta Time: " + event.info.deltaTime + " Latency: " + event.info.latency);
+			LogUtil.debug("Server Client Bandwidth Detect Complete");
+			LogUtil.debug("Detecting Client Server Bandwidth)";
+			ClientServer();
+		}
+		
+		public function onServerClientStatus(event:BandwidthDetectEvent):void
+		{	
+			if (event.info) {
+				LogUtil.debug("count: "+event.info.count+ " sent: "+event.info.sent+" timePassed: "+event.info.timePassed+" latency: "+event.info.latency+" cumLatency: " + event.info.cumLatency);
+			}
+		}
+
+	}
+}
diff --git a/bigbluebutton-client/src/org/red5/flash/bwcheck/events/BandwidthDetectEvent.as b/bigbluebutton-client/src/org/red5/flash/bwcheck/events/BandwidthDetectEvent.as
new file mode 100644
index 0000000000000000000000000000000000000000..3720aad5161245c95ef1d1f024ab3c713f780632
--- /dev/null
+++ b/bigbluebutton-client/src/org/red5/flash/bwcheck/events/BandwidthDetectEvent.as
@@ -0,0 +1,30 @@
+package org.red5.flash.bwcheck.events
+{
+	import flash.events.Event;
+	
+	public class BandwidthDetectEvent extends Event
+	{
+		public static const DETECT_STATUS:String = "detect_status";
+		public static const DETECT_COMPLETE:String = "detect_complete";
+		public static const DETECT_FAILED:String = "detect_failed";
+		
+		private var _info:Object;
+		
+		public function BandwidthDetectEvent(eventName:String)
+        {
+            super (eventName);
+        }
+        
+        public function set info(obj:Object):void
+        {
+        	_info = obj;
+        }
+        
+        public function get info():Object
+        {
+        	return _info;	
+        }
+      
+
+	}
+}
\ No newline at end of file
diff --git a/bigbluebutton-web/grails-app/conf/bigbluebutton.properties b/bigbluebutton-web/grails-app/conf/bigbluebutton.properties
index 9a24ea09b58f54a3093f07ebc167174a431c0539..3ac8dc6f8431189a1f9f264663fa9afe3e082f05 100755
--- a/bigbluebutton-web/grails-app/conf/bigbluebutton.properties
+++ b/bigbluebutton-web/grails-app/conf/bigbluebutton.properties
@@ -97,6 +97,11 @@ bigbluebutton.web.logoutURL=default
 # successfully joining the meeting.
 defaultClientUrl=${bigbluebutton.web.serverURL}/client/BigBlueButton.html
 
+# The default avatar image to display if nothing is passed on the JOIN API (avatarURL)
+# call. This avatar is displayed if the user isn't sharing the webcam and
+# the option (displayAvatar) is enabled in config.xml
+defaultAvatarURL=${bigbluebutton.web.serverURL}/client/avatar.png
+
 apiVersion=0.8
 
 # Salt which is used by 3rd-party apps to authenticate api calls
diff --git a/bigbluebutton-web/grails-app/conf/spring/resources.xml b/bigbluebutton-web/grails-app/conf/spring/resources.xml
index f0c2e32c3c3f217494f408644441c651ae2911b6..c23bd41d15d41e46874298744a81cac1a0e997ef 100755
--- a/bigbluebutton-web/grails-app/conf/spring/resources.xml
+++ b/bigbluebutton-web/grails-app/conf/spring/resources.xml
@@ -83,6 +83,7 @@
     <property name="defaultClientUrl" value="${defaultClientUrl}"/>
     <property name="defaultMeetingDuration" value="${defaultMeetingDuration}"/>
     <property name="disableRecordingDefault" value="${disableRecordingDefault}"/>
+    <property name="defaultAvatarURL" value="${defaultAvatarURL}"/>
   </bean>
         
 	<import resource="doc-conversion.xml" />
diff --git a/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ApiController.groovy b/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ApiController.groovy
index dc823c64af3219cbfd4556153f1160056a81fe3d..4bc98f14a753ecac67ef57fa50bc3e403e4c8d93 100755
--- a/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ApiController.groovy
+++ b/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ApiController.groovy
@@ -304,6 +304,7 @@ class ApiController {
 	us.internalUserId = internalUserID
     us.conferencename = meeting.getName()
     us.meetingID = meeting.getInternalId()
+	us.externMeetingID = meeting.getExternalId()
     us.externUserID = externUserID
     us.fullname = fullName 
     us.role = role
@@ -315,7 +316,17 @@ class ApiController {
     us.record = meeting.isRecord()
     us.welcome = meeting.getWelcomeMessage()
 	us.logoutUrl = meeting.getLogoutUrl();
-    
+	
+	if (! StringUtils.isEmpty(params.defaulLayout)) {
+		us.defaultLayout = params.defaulLayout;
+	}
+
+    if (! StringUtils.isEmpty(params.avatarURL)) {
+        us.avatarURL = params.avatarURL;
+    } else {
+        us.avatarURL = meeting.defaultAvatarURL
+    }
+    	     
 	// Store the following into a session so we can handle
 	// logout, restarts properly.
 	session['meeting-id'] = us.meetingID
@@ -324,9 +335,7 @@ class ApiController {
 	
 	meetingService.addUserSession(session['user-token'], us);
 	
-	log.info("Session user token for " + us.fullname + " [" + session['user-token'] + "]")
-	
-	
+	log.info("Session user token for " + us.fullname + " [" + session['user-token'] + "]")	
     session.setMaxInactiveInterval(SESSION_TIMEOUT);
     
 	//check if exists the param redirect
@@ -763,6 +772,7 @@ class ApiController {
               fullname(us.fullname)
               confname(us.conferencename)
               meetingID(us.meetingID)
+			  externMeetingID(us.externMeetingID)
               externUserID(us.externUserID)
 			  internalUserID(us.internalUserId)
               role(us.role)
@@ -774,6 +784,8 @@ class ApiController {
               record(us.record)
               welcome(us.welcome)
 			  logoutUrl(us.logoutUrl)
+			  defaultLayout(us.defaultLayout)
+			  avatarURL(us.avatarURL)
             }
           }
         }
diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/api/ParamsProcessorUtil.java b/bigbluebutton-web/src/java/org/bigbluebutton/api/ParamsProcessorUtil.java
index 0f0065ede277084f610aa8baff107400bbf11ebe..107a28b629a8562fc5e2c47e73328ca65c9a977a 100755
--- a/bigbluebutton-web/src/java/org/bigbluebutton/api/ParamsProcessorUtil.java
+++ b/bigbluebutton-web/src/java/org/bigbluebutton/api/ParamsProcessorUtil.java
@@ -31,6 +31,7 @@ public class ParamsProcessorUtil {
 	private String defaultServerUrl;
 	private int defaultNumDigitsForTelVoice;
 	private String defaultClientUrl;
+	private String defaultAvatarURL;
 	private int defaultMeetingDuration;
 	private boolean disableRecordingDefault;
 	
@@ -286,6 +287,7 @@ public class ParamsProcessorUtil {
 	        .withName(meetingName).withMaxUsers(maxUsers).withModeratorPass(modPass)
 	        .withViewerPass(viewerPass).withRecording(record).withDuration(meetingDuration)
 	        .withLogoutUrl(logoutUrl).withTelVoice(telVoice).withWebVoice(webVoice).withDialNumber(dialNumber)
+	        .withDefaultAvatarURL(defaultAvatarURL)
 	        .withMetadata(meetingInfo).withWelcomeMessage(welcomeMessage).build();
 	    
 	    return meeting;
@@ -495,6 +497,10 @@ public class ParamsProcessorUtil {
 		this.disableRecordingDefault = disabled;
 	}
 	
+	public void setdefaultAvatarURL(String url) {
+		this.defaultAvatarURL = url;
+	}
+	
 	public ArrayList<String> decodeIds(String encodeid){
 		ArrayList<String> ids=new ArrayList<String>();
 		try {
diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Meeting.java b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Meeting.java
index dbc94b6a413b135dc803e890b340b8755df06b04..32dcb87b25fa14bd18bd8df93171b2b9573979e2 100755
--- a/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Meeting.java
+++ b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Meeting.java
@@ -46,7 +46,8 @@ public class Meeting {
 	private int maxUsers;
 	private boolean record;
 	private String dialNumber;
-
+	private String defaultAvatarURL;
+	
 	private Map<String, String> metadata;	
 	private final ConcurrentMap<String, User> users; 
 	
@@ -58,6 +59,7 @@ public class Meeting {
 		moderatorPass = builder.moderatorPass;
 		maxUsers = builder.maxUsers;
 		logoutUrl = builder.logoutUrl;
+		defaultAvatarURL = builder.defaultAvatarURL;
 		record = builder.record;
     	duration = builder.duration;
     	webVoice = builder.webVoice;
@@ -152,6 +154,10 @@ public class Meeting {
 		return welcomeMsg;
 	}
 
+	public String getDefaultAvatarURL() {
+		return defaultAvatarURL;
+	}
+	
 	public String getLogoutUrl() {
 		return logoutUrl;
 	}
@@ -249,6 +255,7 @@ public class Meeting {
     	private String logoutUrl;
     	private Map<String, String> metadata;
     	private String dialNumber;
+    	private String defaultAvatarURL;
     	private long createdTime;
     	
     	public Builder(String externalId, String internalId, long createTime) {
@@ -307,6 +314,11 @@ public class Meeting {
     		return this;
     	}
     	
+    	public Builder withDefaultAvatarURL(String w) {
+    		defaultAvatarURL = w;
+    		return this;
+    	}
+    	
     	public Builder withLogoutUrl(String l) {
     		logoutUrl = l;
     		return this;
diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/UserSession.java b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/UserSession.java
index c5a437b6e7f6d50e4fb1733f3c24ce39a585e37c..70a28866c36a0f96035e29473428c8d7c3bcc2b1 100755
--- a/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/UserSession.java
+++ b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/UserSession.java
@@ -4,6 +4,7 @@ public class UserSession {
 	String internalUserId = null;
     String conferencename = null;
     String meetingID = null;
+    String externMeetingID = null;
     String externUserID = null;
     String fullname = null; 
     String role = null;
@@ -15,4 +16,6 @@ public class UserSession {
     String record = null;
     String welcome = null;
     String logoutUrl = null;
+    String defaultLayout = "NOLAYOUT";
+    String avatarURL;
 }
diff --git a/record-and-playback/presentation/playback/presentation/lib/popcorn-complete.min.js b/record-and-playback/presentation/playback/presentation/lib/popcorn-complete.min.js
index f324d54362471bebecde22941d406ef443499053..8aeee4f2b58abed7b4b0fc7ffadfe30ae8db1cb4 100755
--- a/record-and-playback/presentation/playback/presentation/lib/popcorn-complete.min.js
+++ b/record-and-playback/presentation/playback/presentation/lib/popcorn-complete.min.js
@@ -1,200 +1,160 @@
 /*
- * popcorn.js version 1.2
+ * popcorn.js version 1.3
  * http://popcornjs.org
  *
  * Copyright 2011, Mozilla Foundation
  * Licensed under the MIT license
  */
 
-(function(g,b){function d(e,m){return function(){if(n.plugin.debug)return e.apply(this,arguments);try{return e.apply(this,arguments)}catch(q){n.plugin.errors.push({plugin:m,thrown:q,source:e.toString()});this.emit("error",n.plugin.errors)}}}if(b.addEventListener){var a=Array.prototype,c=Object.prototype,f=a.forEach,h=a.slice,p=c.hasOwnProperty,o=c.toString,l=g.Popcorn,i=/^(#([\w\-\_\.]+))$/,r=[],k=false,j={events:{hash:{},apis:{}}},v=function(){return g.requestAnimationFrame||g.webkitRequestAnimationFrame||
-g.mozRequestAnimationFrame||g.oRequestAnimationFrame||g.msRequestAnimationFrame||function(e){g.setTimeout(e,16)}}(),w=function(e){var m=e.media.currentTime,q=e.options.frameAnimation,s=e.data.disabled,t=e.data.trackEvents,u=t.animating,x=t.startIndex,A=n.registryByName,B=0,D,E;for(x=Math.min(x+1,t.byStart.length-2);x>0&&t.byStart[x];){B=t.byStart[x];E=(D=B._natives)&&D.type;if(!D||A[E]||e[E])if(B.start<=m&&B.end>m&&s.indexOf(E)===-1){if(!B._running){B._running=true;D.start.call(e,null,B);q&&B&&B._running&&
-B.natives.frame&&D.frame.call(e,null,B,m)}}else if(B._running===true){B._running=false;D.end.call(e,null,B);if(q&&B._natives.frame){B=u.indexOf(B);B>=0&&u.splice(B,1)}}x--}},n=function(e,m){return new n.p.init(e,m||null)};n.version="1.2";n.isSupported=true;n.instances=[];n.p=n.prototype={init:function(e,m){var q,s=this;if(typeof e==="function")if(b.readyState==="complete")e(b,n);else{r.push(e);if(!k){k=true;var t=function(){b.removeEventListener("DOMContentLoaded",t,false);for(var x=0,A=r.length;x<
-A;x++)r[x].call(b,n);r=null};b.addEventListener("DOMContentLoaded",t,false)}}else{this.media=(q=i.exec(e))&&q.length&&q[2]?b.getElementById(q[2]):e;this[this.media.nodeName&&this.media.nodeName.toLowerCase()||"video"]=this.media;n.instances.push(this);this.options=m||{};this.isDestroyed=false;this.data={timeUpdate:n.nop,disabled:[],events:{},hooks:{},history:[],state:{volume:this.media.volume},trackRefs:{},trackEvents:{byStart:[{start:-1,end:-1}],byEnd:[{start:-1,end:-1}],animating:[],startIndex:0,
-endIndex:0,previousUpdateTime:-1}};var u=function(){s.media.removeEventListener("loadeddata",u,false);var x;x=s.media.duration;x=x!=x?Number.MAX_VALUE:x+1;n.addTrackEvent(s,{start:x,end:x});if(s.options.frameAnimation){s.data.timeUpdate=function(){n.timeUpdate(s,{});s.emit("timeupdate");!s.isDestroyed&&v(s.data.timeUpdate)};!s.isDestroyed&&v(s.data.timeUpdate)}else{s.data.timeUpdate=function(A){n.timeUpdate(s,A)};s.isDestroyed||s.media.addEventListener("timeupdate",s.data.timeUpdate,false)}};s.media.readyState>=
-2?u():s.media.addEventListener("loadeddata",u,false);return this}}};n.p.init.prototype=n.p;n.forEach=function(e,m,q){if(!e||!m)return{};q=q||this;var s,t;if(f&&e.forEach===f)return e.forEach(m,q);if(o.call(e)==="[object NodeList]"){s=0;for(t=e.length;s<t;s++)m.call(q,e[s],s,e);return e}for(s in e)p.call(e,s)&&m.call(q,e[s],s,e);return e};n.extend=function(e){var m=h.call(arguments,1);n.forEach(m,function(q){for(var s in q)e[s]=q[s]});return e};n.extend(n,{noConflict:function(e){if(e)g.Popcorn=l;return n},
-error:function(e){throw Error(e);},guid:function(e){n.guid.counter++;return(e?e:"")+(+new Date+n.guid.counter)},sizeOf:function(e){var m=0,q;for(q in e)m++;return m},isArray:Array.isArray||function(e){return o.call(e)==="[object Array]"},nop:function(){},position:function(e){e=e.getBoundingClientRect();var m={},q=b.documentElement,s=b.body,t,u,x;t=q.clientTop||s.clientTop||0;u=q.clientLeft||s.clientLeft||0;x=g.pageYOffset&&q.scrollTop||s.scrollTop;q=g.pageXOffset&&q.scrollLeft||s.scrollLeft;t=Math.ceil(e.top+
-x-t);u=Math.ceil(e.left+q-u);for(var A in e)m[A]=Math.round(e[A]);return n.extend({},m,{top:t,left:u})},disable:function(e,m){var q=e.data.disabled;q.indexOf(m)===-1&&q.push(m);w(e);return e},enable:function(e,m){var q=e.data.disabled,s=q.indexOf(m);s>-1&&q.splice(s,1);w(e);return e},destroy:function(e){var m=e.data.events,q,s,t;for(s in m){q=m[s];for(t in q)delete q[t];m[s]=null}if(!e.isDestroyed){e.data.timeUpdate&&e.media.removeEventListener("timeupdate",e.data.timeUpdate,false);e.isDestroyed=
-true}}});n.guid.counter=1;n.extend(n.p,function(){var e={};n.forEach("load play pause currentTime playbackRate volume duration preload playbackRate autoplay loop controls muted buffered readyState seeking paused played seekable ended".split(/\s+/g),function(m){e[m]=function(q){if(typeof this.media[m]==="function"){if(q!=null&&/play|pause/.test(m))this.media.currentTime=n.util.toSeconds(q);this.media[m]();return this}if(q!=null){this.media[m]=q;return this}return this.media[m]}});return e}());n.forEach("enable disable".split(" "),
-function(e){n.p[e]=function(m){return n[e](this,m)}});n.extend(n.p,{roundTime:function(){return-~this.media.currentTime},exec:function(e,m){n.addTrackEvent(this,{start:e,end:e+1,_running:false,_natives:{start:m||n.nop,end:n.nop,type:"cue"}});return this},mute:function(e){e=e==null||e===true?"muted":"unmuted";if(e==="unmuted"){this.media.muted=false;this.media.volume=this.data.state.volume}if(e==="muted"){this.data.state.volume=this.media.volume;this.media.muted=true}this.emit(e);return this},unmute:function(e){return this.mute(e==
-null?false:!e)},position:function(){return n.position(this.media)},toggle:function(e){return n[this.data.disabled.indexOf(e)>-1?"enable":"disable"](this,e)},defaults:function(e,m){if(n.isArray(e)){n.forEach(e,function(q){for(var s in q)this.defaults(s,q[s])},this);return this}if(!this.options.defaults)this.options.defaults={};this.options.defaults[e]||(this.options.defaults[e]={});n.extend(this.options.defaults[e],m);return this}});n.Events={UIEvents:"blur focus focusin focusout load resize scroll unload",
-MouseEvents:"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave click dblclick",Events:"loadstart progress suspend emptied stalled play pause loadedmetadata loadeddata waiting playing canplay canplaythrough seeking seeked timeupdate ended ratechange durationchange volumechange"};n.Events.Natives=n.Events.UIEvents+" "+n.Events.MouseEvents+" "+n.Events.Events;j.events.apiTypes=["UIEvents","MouseEvents","Events"];(function(e,m){for(var q=j.events.apiTypes,s=e.Natives.split(/\s+/g),
-t=0,u=s.length;t<u;t++)m.hash[s[t]]=true;q.forEach(function(x){m.apis[x]={};for(var A=e[x].split(/\s+/g),B=A.length,D=0;D<B;D++)m.apis[x][A[D]]=true})})(n.Events,j.events);n.events={isNative:function(e){return!!j.events.hash[e]},getInterface:function(e){if(!n.events.isNative(e))return false;var m=j.events,q=m.apiTypes;m=m.apis;for(var s=0,t=q.length,u,x;s<t;s++){x=q[s];if(m[x][e]){u=x;break}}return u},all:n.Events.Natives.split(/\s+/g),fn:{trigger:function(e,m){var q;if(this.data.events[e]&&n.sizeOf(this.data.events[e])){if(q=
-n.events.getInterface(e)){q=b.createEvent(q);q.initEvent(e,true,true,g,1);this.media.dispatchEvent(q);return this}n.forEach(this.data.events[e],function(s){s.call(this,m)},this)}return this},listen:function(e,m){var q=this,s=true,t=n.events.hooks[e],u;if(!this.data.events[e]){this.data.events[e]={};s=false}if(t){t.add&&t.add.call(this,{},m);if(t.bind)e=t.bind;if(t.handler){u=m;m=function(x){t.handler.call(q,x,u)}}s=true;if(!this.data.events[e]){this.data.events[e]={};s=false}}this.data.events[e][m.name||
-m.toString()+n.guid()]=m;!s&&n.events.all.indexOf(e)>-1&&this.media.addEventListener(e,function(x){n.forEach(q.data.events[e],function(A){typeof A==="function"&&A.call(q,x)})},false);return this},unlisten:function(e,m){if(this.data.events[e]&&this.data.events[e][m]){delete this.data.events[e][m];return this}this.data.events[e]=null;return this}},hooks:{canplayall:{bind:"canplaythrough",add:function(e,m){var q=false;if(this.media.readyState){m.call(this,e);q=true}this.data.hooks.canplayall={fired:q}},
-handler:function(e,m){if(!this.data.hooks.canplayall.fired){m.call(this,e);this.data.hooks.canplayall.fired=true}}}}};n.forEach([["trigger","emit"],["listen","on"],["unlisten","off"]],function(e){n.p[e[0]]=n.p[e[1]]=n.events.fn[e[0]]});n.addTrackEvent=function(e,m){if(m&&m._natives&&m._natives.type&&e.options.defaults&&e.options.defaults[m._natives.type])m=n.extend({},e.options.defaults[m._natives.type],m);if(m._natives){m._id=!m.id?n.guid(m._natives.type):m.id;e.data.history.push(m._id)}m.start=
-n.util.toSeconds(m.start,e.options.framerate);m.end=n.util.toSeconds(m.end,e.options.framerate);var q=e.data.trackEvents.byStart,s=e.data.trackEvents.byEnd,t;for(t=q.length-1;t>=0;t--)if(m.start>=q[t].start){q.splice(t+1,0,m);break}for(q=s.length-1;q>=0;q--)if(m.end>s[q].end){s.splice(q+1,0,m);break}if(m._natives&&(n.registryByName[m._natives.type]||e[m._natives.type])){s=e.media.currentTime;if(m.end>s&&m.start<=s&&e.data.disabled.indexOf(m._natives.type)===-1){m._running=true;m._natives.start.call(e,
-null,m);if(e.options.frameAnimation&&m._natives.frame){e.data.trackEvents.animating.push(m);m._natives.frame.call(e,null,m,s)}}}t<=e.data.trackEvents.startIndex&&m.start<=e.data.trackEvents.previousUpdateTime&&e.data.trackEvents.startIndex++;q<=e.data.trackEvents.endIndex&&m.end<e.data.trackEvents.previousUpdateTime&&e.data.trackEvents.endIndex++;this.timeUpdate(e,null,true);m._id&&n.addTrackEvent.ref(e,m)};n.addTrackEvent.ref=function(e,m){e.data.trackRefs[m._id]=m;return e};n.removeTrackEvent=function(e,
-m){for(var q,s,t=e.data.history.length,u=e.data.trackEvents.byStart.length,x=0,A=0,B=[],D=[],E=[],z=[];--u>-1;){q=e.data.trackEvents.byStart[x];s=e.data.trackEvents.byEnd[x];if(!q._id){B.push(q);D.push(s)}if(q._id){q._id!==m&&B.push(q);s._id!==m&&D.push(s);if(q._id===m){A=x;q._natives._teardown&&q._natives._teardown.call(e,q)}}x++}u=e.data.trackEvents.animating.length;x=0;if(u)for(;--u>-1;){q=e.data.trackEvents.animating[x];q._id||E.push(q);q._id&&q._id!==m&&E.push(q);x++}A<=e.data.trackEvents.startIndex&&
-e.data.trackEvents.startIndex--;A<=e.data.trackEvents.endIndex&&e.data.trackEvents.endIndex--;e.data.trackEvents.byStart=B;e.data.trackEvents.byEnd=D;e.data.trackEvents.animating=E;for(u=0;u<t;u++)e.data.history[u]!==m&&z.push(e.data.history[u]);e.data.history=z;n.removeTrackEvent.ref(e,m)};n.removeTrackEvent.ref=function(e,m){delete e.data.trackRefs[m];return e};n.getTrackEvents=function(e){var m=[];e=e.data.trackEvents.byStart;for(var q=e.length,s=0,t;s<q;s++){t=e[s];t._id&&m.push(t)}return m};
-n.getTrackEvents.ref=function(e){return e.data.trackRefs};n.getTrackEvent=function(e,m){return e.data.trackRefs[m]};n.getTrackEvent.ref=function(e,m){return e.data.trackRefs[m]};n.getLastTrackEventId=function(e){return e.data.history[e.data.history.length-1]};n.timeUpdate=function(e,m){var q=e.media.currentTime,s=e.data.trackEvents.previousUpdateTime,t=e.data.trackEvents,u=t.animating,x=t.endIndex,A=t.startIndex,B=0,D=t.byStart.length,E=t.byEnd.length,z=n.registryByName,F,H,G;if(s<=q){for(;t.byEnd[x]&&
-t.byEnd[x].end<=q;){F=t.byEnd[x];G=(s=F._natives)&&s.type;if(!s||z[G]||e[G]){if(F._running===true){F._running=false;s.end.call(e,m,F);e.emit("trackend",n.extend({},F,{plugin:G,type:"trackend"}))}x++}else{n.removeTrackEvent(e,F._id);return}}for(;t.byStart[A]&&t.byStart[A].start<=q;){H=t.byStart[A];G=(s=H._natives)&&s.type;if(!s||z[G]||e[G]){if(H.end>q&&H._running===false&&e.data.disabled.indexOf(G)===-1){H._running=true;s.start.call(e,m,H);e.emit("trackstart",n.extend({},H,{plugin:G,type:"trackstart"}));
-e.options.frameAnimation&&H&&H._running&&H._natives.frame&&u.push(H)}A++}else{n.removeTrackEvent(e,H._id);return}}if(e.options.frameAnimation)for(;B<u.length;){z=u[B];if(z._running){z._natives.frame.call(e,m,z,q);B++}else u.splice(B,1)}}else if(s>q){for(;t.byStart[A]&&t.byStart[A].start>q;){H=t.byStart[A];G=(s=H._natives)&&s.type;if(!s||z[G]||e[G]){if(H._running===true){H._running=false;s.end.call(e,m,H);e.emit("trackend",n.extend({},F,{plugin:G,type:"trackend"}))}A--}else{n.removeTrackEvent(e,H._id);
-return}}for(;t.byEnd[x]&&t.byEnd[x].end>q;){F=t.byEnd[x];G=(s=F._natives)&&s.type;if(!s||z[G]||e[G]){if(F.start<=q&&F._running===false&&e.data.disabled.indexOf(G)===-1){F._running=true;s.start.call(e,m,F);e.emit("trackstart",n.extend({},H,{plugin:G,type:"trackstart"}));e.options.frameAnimation&&F&&F._running&&F._natives.frame&&u.push(F)}x--}else{n.removeTrackEvent(e,F._id);return}}if(e.options.frameAnimation)for(;B<u.length;){z=u[B];if(z._running){z._natives.frame.call(e,m,z,q);B++}else u.splice(B,
-1)}}t.endIndex=x;t.startIndex=A;t.previousUpdateTime=q;t.byStart.length<D&&t.startIndex--;t.byEnd.length<E&&t.endIndex--};n.extend(n.p,{getTrackEvents:function(){return n.getTrackEvents.call(null,this)},getTrackEvent:function(e){return n.getTrackEvent.call(null,this,e)},getLastTrackEventId:function(){return n.getLastTrackEventId.call(null,this)},removeTrackEvent:function(e){n.removeTrackEvent.call(null,this,e);return this},removePlugin:function(e){n.removePlugin.call(null,this,e);return this},timeUpdate:function(e){n.timeUpdate.call(null,
-this,e);return this},destroy:function(){n.destroy.call(null,this);return this}});n.manifest={};n.registry=[];n.registryByName={};n.plugin=function(e,m,q){if(n.protect.natives.indexOf(e.toLowerCase())>=0)n.error("'"+e+"' is a protected function name");else{var s=["start","end"],t={},u=typeof m==="function",x=["_setup","_teardown","start","end","frame"],A=function(E,z){E=E||n.nop;z=z||n.nop;return function(){E.apply(this,arguments);z.apply(this,arguments)}};n.manifest[e]=q=q||m.manifest||{};x.forEach(function(E){m[E]=
-d(m[E]||n.nop,e)});var B=function(E,z){if(!z)return this;var F=z._natives={},H="",G;n.extend(F,E);z._natives.type=e;z._running=false;F.start=F.start||F["in"];F.end=F.end||F.out;F._teardown=A(function(){var I=h.call(arguments);I.unshift(null);I[1]._running&&F.end.apply(this,I)},F._teardown);z.compose=z.compose&&z.compose.split(" ")||[];z.effect=z.effect&&z.effect.split(" ")||[];z.compose=z.compose.concat(z.effect);z.compose.forEach(function(I){H=n.compositions[I]||{};x.forEach(function(J){F[J]=A(F[J],
-H[J])})});z._natives.manifest=q;if(!("start"in z))z.start=z["in"]||0;if(!z.end&&z.end!==0)z.end=z.out||Number.MAX_VALUE;if(!p.call(z,"toString"))z.toString=function(){var I=["start: "+z.start,"end: "+z.end,"id: "+(z.id||z._id)];z.target!=null&&I.push("target: "+z.target);return e+" ( "+I.join(", ")+" )"};if(!z.target){G="options"in q&&q.options;z.target=G&&"target"in G&&G.target}z._natives._setup&&z._natives._setup.call(this,z);n.addTrackEvent(this,n.extend(z,z));n.forEach(E,function(I,J){J!=="type"&&
-s.indexOf(J)===-1&&this.on(J,I)},this);return this};n.p[e]=t[e]=function(E){E=n.extend({},this.options.defaults&&this.options.defaults[e]||{},E);return B.call(this,u?m.call(this,E):m,E)};var D={fn:t[e],definition:m,base:m,parents:[],name:e};n.registry.push(n.extend(t,D,{type:e}));n.registryByName[e]=D;return t}};n.plugin.errors=[];n.plugin.debug=false;n.removePlugin=function(e,m){if(!m){m=e;e=n.p;if(n.protect.natives.indexOf(m.toLowerCase())>=0){n.error("'"+m+"' is a protected function name");return}var q=
-n.registry.length,s;for(s=0;s<q;s++)if(n.registry[s].name===m){n.registry.splice(s,1);delete n.registryByName[m];delete n.manifest[m];delete e[m];return}}q=e.data.trackEvents.byStart;s=e.data.trackEvents.byEnd;var t=e.data.trackEvents.animating,u,x;u=0;for(x=q.length;u<x;u++){if(q[u]&&q[u]._natives&&q[u]._natives.type===m){q[u]._natives._teardown&&q[u]._natives._teardown.call(e,q[u]);q.splice(u,1);u--;x--;if(e.data.trackEvents.startIndex<=u){e.data.trackEvents.startIndex--;e.data.trackEvents.endIndex--}}s[u]&&
-s[u]._natives&&s[u]._natives.type===m&&s.splice(u,1)}u=0;for(x=t.length;u<x;u++)if(t[u]&&t[u]._natives&&t[u]._natives.type===m){t.splice(u,1);u--;x--}};n.compositions={};n.compose=function(e,m,q){n.manifest[e]=q||m.manifest||{};n.compositions[e]=m};n.plugin.effect=n.effect=n.compose;var y=/\?/,C={url:"",data:"",dataType:"",success:n.nop,type:"GET",async:true,xhr:function(){return new g.XMLHttpRequest}};n.xhr=function(e){e.dataType=e.dataType&&e.dataType.toLowerCase()||null;if(e.dataType&&(e.dataType===
-"jsonp"||e.dataType==="script"))n.xhr.getJSONP(e.url,e.success,e.dataType==="script");else{e=n.extend({},C,e);e.ajax=e.xhr();if(e.ajax){if(e.type==="GET"&&e.data){e.url+=(y.test(e.url)?"&":"?")+e.data;e.data=null}e.ajax.open(e.type,e.url,e.async);e.ajax.send(e.data||null);return n.xhr.httpData(e)}}};n.xhr.httpData=function(e){var m,q=null,s,t=null;e.ajax.onreadystatechange=function(){if(e.ajax.readyState===4){try{q=JSON.parse(e.ajax.responseText)}catch(u){}m={xml:e.ajax.responseXML,text:e.ajax.responseText,
-json:q};if(!m.xml||!m.xml.documentElement){m.xml=null;try{s=new DOMParser;t=s.parseFromString(e.ajax.responseText,"text/xml");if(!t.getElementsByTagName("parsererror").length)m.xml=t}catch(x){}}if(e.dataType)m=m[e.dataType];e.success.call(e.ajax,m)}};return m};n.xhr.getJSONP=function(e,m,q){var s=b.head||b.getElementsByTagName("head")[0]||b.documentElement,t=b.createElement("script"),u=e.split("?")[1],x=false,A=[],B,D;if(u&&!q)A=u.split("&");if(A.length)D=A[A.length-1].split("=");B=A.length?D[1]?
-D[1]:D[0]:"jsonp";if(!u&&!q)e+="?callback="+B;if(B&&!q){if(window[B])B=n.guid(B);window[B]=function(E){m&&m(E);x=true};e=e.replace(D.join("="),D[0]+"="+B)}t.addEventListener("load",function(){q&&m&&m();x&&delete window[B];s.removeChild(t)},false);t.src=e;s.insertBefore(t,s.firstChild)};n.getJSONP=n.xhr.getJSONP;n.getScript=n.xhr.getScript=function(e,m){return n.xhr.getJSONP(e,m,true)};n.util={toSeconds:function(e,m){var q=/^([0-9]+:){0,2}[0-9]+([.;][0-9]+)?$/,s,t,u;if(typeof e==="number")return e;
-typeof e==="string"&&!q.test(e)&&n.error("Invalid time format");q=e.split(":");s=q.length-1;t=q[s];if(t.indexOf(";")>-1){t=t.split(";");u=0;if(m&&typeof m==="number")u=parseFloat(t[1],10)/m;q[s]=parseInt(t[0],10)+u}s=q[0];return{1:parseFloat(s,10),2:parseInt(s,10)*60+parseFloat(q[1],10),3:parseInt(s,10)*3600+parseInt(q[1],10)*60+parseFloat(q[2],10)}[q.length||1]}};n.p.cue=n.p.exec;n.protect={natives:function(e){return Object.keys?Object.keys(e):function(m){var q,s=[];for(q in m)p.call(m,q)&&s.push(q);
-return s}(e)}(n.p).map(function(e){return e.toLowerCase()})};n.forEach({listen:"on",unlisten:"off",trigger:"emit",exec:"cue"},function(e,m){var q=n.p[m];n.p[m]=function(){if(typeof console!=="undefined"&&console.warn){console.warn("Deprecated method '"+m+"', "+(e==null?"do not use.":"use '"+e+"' instead."));n.p[m]=q}return n.p[e].apply(this,[].slice.call(arguments))}});g.Popcorn=n}else{g.Popcorn={isSupported:false};for(a="removeInstance addInstance getInstanceById removeInstanceById forEach extend effects error guid sizeOf isArray nop position disable enable destroyaddTrackEvent removeTrackEvent getTrackEvents getTrackEvent getLastTrackEventId timeUpdate plugin removePlugin compose effect xhr getJSONP getScript".split(/\s+/);a.length;)g.Popcorn[a.shift()]=
-function(){}}})(window,window.document);(function(g,b){var d=g.document,a=g.location,c=/:\/\//,f=a.href.replace(a.href.split("/").slice(-1)[0],""),h=function(o,l,i){o=o||0;l=(l||o||0)+1;i=i||1;l=Math.ceil((l-o)/i)||0;var r=0,k=[];for(k.length=l;r<l;){k[r++]=o;o+=i}return k};b.sequence=function(o,l){return new b.sequence.init(o,l)};b.sequence.init=function(o,l){this.parent=d.getElementById(o);this.seqId=b.guid("__sequenced");this.queue=[];this.playlist=[];this.inOuts={ofVideos:[],ofClips:[]};this.dims={width:0,height:0};this.active=0;this.playing=
-this.cycling=false;this.times={last:0};this.events={};var i=this,r=0;b.forEach(l,function(k,j){var v=d.createElement("video");v.preload="auto";v.controls=true;v.style.display=j&&"none"||"";v.id=i.seqId+"-"+j;i.queue.push(v);var w=k["in"],n=k.out;i.inOuts.ofVideos.push({"in":w!==undefined&&w||1,out:n!==undefined&&n||0});i.inOuts.ofVideos[j].out=i.inOuts.ofVideos[j].out||i.inOuts.ofVideos[j]["in"]+2;v.src=!c.test(k.src)?f+k.src:k.src;v.setAttribute("data-sequence-owner",o);v.setAttribute("data-sequence-guid",
-i.seqId);v.setAttribute("data-sequence-id",j);v.setAttribute("data-sequence-clip",[i.inOuts.ofVideos[j]["in"],i.inOuts.ofVideos[j].out].join(":"));i.parent.appendChild(v);i.playlist.push(b("#"+v.id))});i.inOuts.ofVideos.forEach(function(k){k={"in":r,out:r+(k.out-k["in"])};i.inOuts.ofClips.push(k);r=k.out+1});b.forEach(this.queue,function(k,j){function v(){if(!j){i.dims.width=k.videoWidth;i.dims.height=k.videoHeight}k.currentTime=i.inOuts.ofVideos[j]["in"]-0.5;k.removeEventListener("canplaythrough",
-v,false);return true}k.addEventListener("canplaythrough",v,false);k.addEventListener("play",function(){i.playing=true},false);k.addEventListener("pause",function(){i.playing=false},false);k.addEventListener("timeupdate",function(w){w=w.srcElement||w.target;w=+(w.dataset&&w.dataset.sequenceId||w.getAttribute("data-sequence-id"));var n=Math.floor(k.currentTime);if(i.times.last!==n&&w===i.active){i.times.last=n;n===i.inOuts.ofVideos[w].out&&b.sequence.cycle.call(i,w)}},false)});return this};b.sequence.init.prototype=
-b.sequence.prototype;b.sequence.cycle=function(o){this.queue||b.error("Popcorn.sequence.cycle is not a public method");var l=this.queue,i=this.inOuts.ofVideos,r=l[o],k=0,j;if(l[o+1])k=o+1;if(l[o+1]){l=l[k];i=i[k];b.extend(l,{width:this.dims.width,height:this.dims.height});j=this.playlist[k];r.pause();this.active=k;this.times.last=i["in"]-1;j.currentTime(i["in"]);j[k?"play":"pause"]();this.trigger("cycle",{position:{previous:o,current:k}});if(k){r.style.display="none";l.style.display=""}this.cycling=
-false}else this.playlist[o].pause();return this};var p=["timeupdate","play","pause"];b.extend(b.sequence.prototype,{eq:function(o){return this.playlist[o]},remove:function(){this.parent.innerHTML=null},clip:function(o){return this.inOuts.ofVideos[o]},duration:function(){for(var o=0,l=this.inOuts.ofClips,i=0;i<l.length;i++)o+=l[i].out-l[i]["in"]+1;return o-1},play:function(){this.playlist[this.active].play();return this},exec:function(o,l){var i=this.active;this.inOuts.ofClips.forEach(function(r,k){if(o>=
-r["in"]&&o<=r.out)i=k});o+=this.inOuts.ofVideos[i]["in"]-this.inOuts.ofClips[i]["in"];b.addTrackEvent(this.playlist[i],{start:o-1,end:o,_running:false,_natives:{start:l||b.nop,end:b.nop,type:"exec"}});return this},listen:function(o,l){var i=this,r=this.playlist,k=r.length,j=0;if(!l)l=b.nop;if(b.Events.Natives.indexOf(o)>-1)b.forEach(r,function(v){v.listen(o,function(w){w.active=i;if(p.indexOf(o)>-1)l.call(v,w);else++j===k&&l.call(v,w)})});else{this.events[o]||(this.events[o]={});r=l.name||b.guid("__"+
-o);this.events[o][r]=l}return this},unlisten:function(){},trigger:function(o,l){var i=this;if(!(b.Events.Natives.indexOf(o)>-1)){this.events[o]&&b.forEach(this.events[o],function(r){r.call(i,{type:o},l)});return this}}});b.forEach(b.manifest,function(o,l){b.sequence.prototype[l]=function(i){var r={},k=[],j,v,w,n,y;for(j=0;j<this.inOuts.ofClips.length;j++){k=this.inOuts.ofClips[j];v=h(k["in"],k.out);w=v.indexOf(i.start);n=v.indexOf(i.end);if(w>-1)r[j]=b.extend({},k,{start:v[w],clipIdx:w});if(n>-1)r[j]=
-b.extend({},k,{end:v[n],clipIdx:n})}j=Object.keys(r).map(function(e){return+e});k=h(j[0],j[1]);for(j=0;j<k.length;j++){w={};n=k[j];var C=r[n];if(C){y=this.inOuts.ofVideos[n];v=C.clipIdx;y=h(y["in"],y.out);if(C.start){w.start=y[v];w.end=y[y.length-1]}if(C.end){w.start=y[0];w.end=y[v]}}else{w.start=this.inOuts.ofVideos[n]["in"];w.end=this.inOuts.ofVideos[n].out}this.playlist[n][l](b.extend({},i,w))}return this}})})(this,Popcorn);(function(g){document.addEventListener("DOMContentLoaded",function(){var b=document.querySelectorAll("[data-timeline-sources]");g.forEach(b,function(d,a){var c=b[a],f,h,p;if(!c.id)c.id=g.guid("__popcorn");if(c.nodeType&&c.nodeType===1){p=g("#"+c.id);f=(c.getAttribute("data-timeline-sources")||"").split(",");f[0]&&g.forEach(f,function(o){h=o.split("!");if(h.length===1){h=o.match(/(.*)[\/\\]([^\/\\]+\.\w+)$/)[2].split(".");h[0]="parse"+h[1].toUpperCase();h[1]=o}f[0]&&p[h[0]]&&p[h[0]](h[1])});p.autoplay&&
-p.play()}})},false)})(Popcorn);(function(g,b){function d(f){f=typeof f==="string"?f:[f.language,f.region].join("-");var h=f.split("-");return{iso6391:f,language:h[0]||"",region:h[1]||""}}var a=g.navigator,c=d(a.userLanguage||a.language);b.locale={get:function(){return c},set:function(f){c=d(f);b.locale.broadcast();return c},broadcast:function(f){var h=b.instances,p=h.length,o=0,l;for(f=f||"locale:changed";o<p;o++){l=h[o];f in l.data.events&&l.trigger(f)}}}})(this,this.Popcorn);(function(g){var b=Object.prototype.hasOwnProperty;g.parsers={};g.parser=function(d,a,c){if(g.protect.natives.indexOf(d.toLowerCase())>=0)g.error("'"+d+"' is a protected function name");else{if(typeof a==="function"&&!c){c=a;a=""}if(!(typeof c!=="function"||typeof a!=="string")){var f={};f[d]=function(h,p){if(!h)return this;var o=this;g.xhr({url:h,dataType:a,success:function(l){var i,r,k=0;l=c(l).data||[];if(i=l.length){for(;k<i;k++){r=l[k];for(var j in r)b.call(r,j)&&o[j]&&o[j](r[j])}p&&p()}}});
-return this};g.extend(g.p,f);return f}}}})(Popcorn);(function(g){var b=function(a,c){a=a||g.nop;c=c||g.nop;return function(){a.apply(this,arguments);c.apply(this,arguments)}},d=/^(#([\w\-\_\.]+))$/;g.player=function(a,c){if(!g[a]){c=c||{};var f=function(h,p,o){o=o||{};var l=new Date/1E3,i=l,r=0,k=0,j=1,v=false,w={},n=document.getElementById(d.exec(h)&&d.exec(h)[2])||document.getElementById(h)||h,y={};Object.prototype.__defineGetter__||(y=n||document.createElement("div"));for(var C in n)if(!(C in y))if(typeof n[C]==="object")y[C]=n[C];else if(typeof n[C]===
-"function")y[C]=function(m){return"length"in n[m]&&!n[m].call?n[m]:function(){return n[m].apply(n,arguments)}}(C);else g.player.defineProperty(y,C,{get:function(m){return function(){return n[m]}}(C),set:g.nop,configurable:true});var e=function(){l=new Date/1E3;if(!y.paused){y.currentTime+=l-i;y.dispatchEvent("timeupdate");setTimeout(e,10)}i=l};y.play=function(){this.paused=false;if(y.readyState>=4){i=new Date/1E3;y.dispatchEvent("play");e()}};y.pause=function(){this.paused=true;y.dispatchEvent("pause")};
-g.player.defineProperty(y,"currentTime",{get:function(){return r},set:function(m){r=+m;y.dispatchEvent("timeupdate");return r},configurable:true});g.player.defineProperty(y,"volume",{get:function(){return j},set:function(m){j=+m;y.dispatchEvent("volumechange");return j},configurable:true});g.player.defineProperty(y,"muted",{get:function(){return v},set:function(m){v=+m;y.dispatchEvent("volumechange");return v},configurable:true});g.player.defineProperty(y,"readyState",{get:function(){return k},set:function(m){return k=
-m},configurable:true});y.addEventListener=function(m,q){w[m]||(w[m]=[]);w[m].push(q);return q};y.removeEventListener=function(m,q){var s,t=w[m];if(t){for(s=w[m].length-1;s>=0;s--)q===t[s]&&t.splice(s,1);return q}};y.dispatchEvent=function(m){var q,s=m.type;if(!s){s=m;if(m=g.events.getInterface(s)){q=document.createEvent(m);q.initEvent(s,true,true,window,1)}}if(w[s])for(m=w[s].length-1;m>=0;m--)w[s][m].call(this,q,this)};y.src=p||"";y.duration=0;y.paused=true;y.ended=0;o&&o.events&&g.forEach(o.events,
-function(m,q){y.addEventListener(q,m,false)});if(c._canPlayType(n.nodeName,p)!==false)if(c._setup)c._setup.call(y,o);else{y.readyState=4;y.dispatchEvent("loadedmetadata");y.dispatchEvent("loadeddata");y.dispatchEvent("canplaythrough")}else y.dispatchEvent("error");y.addEventListener("loadedmetadata",function(){y.currentTime=r;y.volume=j;y.muted=v});y.addEventListener("loadeddata",function(){!y.paused&&y.play()});h=new g.p.init(y,o);if(c._teardown)h.destroy=b(h.destroy,function(){c._teardown.call(y,
-o)});return h};f.canPlayType=c._canPlayType=c._canPlayType||g.nop;g[a]=g.player.registry[a]=f}};g.player.registry={};g.player.defineProperty=Object.defineProperty||function(a,c,f){a.__defineGetter__(c,f.get||g.nop);a.__defineSetter__(c,f.set||g.nop)};g.smart=function(a,c,f){var h=d.exec(a);h=h&&h.length&&h[2]?document.getElementById(h[2]):a;if(h.nodeType==="VIDEO"&&!c){if(typeof c==="object")f=c;return g(h,f)}for(var p in g.player.registry)if(g.player.registry.hasOwnProperty(p))if(g.player.registry[p].canPlayType(h.nodeName,
-c))return g[p](a,c,f);if(h.nodeType!=="VIDEO"){a=document.createElement("video");h.appendChild(a);h=a}f&&f.events&&f.events.error&&h.addEventListener("error",f.events.error,false);h.src=c;return g(h,f)}})(Popcorn);(function(g){var b=function(d,a){var c=0,f=0,h;g.forEach(a.classes,function(p,o){h=[];if(p==="parent")h[0]=document.querySelectorAll("#"+a.target)[0].parentNode;else h=document.querySelectorAll("#"+a.target+" "+p);c=0;for(f=h.length;c<f;c++)h[c].classList.toggle(o)})};g.compose("applyclass",{manifest:{about:{name:"Popcorn applyclass Effect",version:"0.1",author:"@scottdowne",website:"scottdowne.wordpress.com"},options:{}},_setup:function(d){d.classes={};d.applyclass=d.applyclass||"";for(var a=d.applyclass.replace(/\s/g,
-"").split(","),c=[],f=0,h=a.length;f<h;f++){c=a[f].split(":");if(c[0])d.classes[c[0]]=c[1]||""}},start:b,end:b})})(Popcorn);(function(g){g.plugin("attribution",function(){var b={"cc-by":"data:image/png;base64,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",
-"cc-by-sa":"data:image/png;base64,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",
-"cc-by-nd":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAAAfCAYAAABjyArgAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAEZ0FNQQAAsY58+1GTAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAgrSURBVHja7FpNbBvHFf72R0YdROz6lBZsAQrogczFtB37aFF1AqR1bC1h2Jc0NXUqEKEgmTZqWkimaMupS9ilicJJA7fRojkHWvkH6B/MpRqgNSWLKzgAeSjAPURoe5IipYeKuzs97O5wl1xSFCWljeNnjHa5M/Ptzjdv3nvzxgwhJMAwzKd4KnsuhBCGAUAA4P4f74FlWbAsC47jwLIcOJYFy9lXlgXDsGAZBgzDAAzjoICAgJgEJjFhmlYxDMO6mgYMw4RpGrTOJCZtTwhxPobePwlyfvQCAIABQBxyOY6zCss17znOqmM5m2QGDMO6+bXJsYk1LTINwy7ue8NLsmmalFg30U8SyTwAL7kcD95ztcrd+XsoFosol8vY3Nj0AA0GBnHixAmMfHsEZ86+AsPkwLK6NSEGCwaMPZeu5WMSayXAXkNMd3KXFyuQP5RRrVY9zyORCMRzIo4eP7IrMvYLnwFA/vDg9+B5npLK87xVOB4lZQG5azmsrq72BBgMBjHx0wkMD5+EbhgwDB26bhdDh64bVMP9NLlVi//5j3/hVuEWatUaACAWiyEajQIAVFWFoigAgHAkjPHkOL729ed2RMB+4p8fvWAR/OfSn8BzfJNYfgADPI/M1DTkOZl2EAQBoigiFApheHgYAFAqlaBpGmRZxvr6Om0rxkX8eOJHOPjMQei6joauQ9cb0HXdazIcgk3blruI/mzjMyTHU9jY2IAoisjn8wiFQp5BaJqGdDoNWZYRCARwNXe1ZxL2G58S/OAvDzDgEDvAY4Af8JArCAJSqRSSySQEQegIKEkS0uk0JTocCeM379/GVw4ehK430Gg0qCb7ktxij6feuoRatYZEIoHZ2dnmsrNNi1vTJUnC2NgYwpEwrly73BMBnfA7jW2n+OdHL4AFAM62wTzHgee8mhuNRlGpVJDJZLqSCwCJRAL1ep0usVq1huu5Gx5bztKIhGkW+5+bwOXFCmrVGkRRxMSbb247mEQiAVEUUavWsLxY6cnm7ie+IywAsE5YxnEoKQsecovFYtuy6SaCIKBYLFKS5TkZpdICOI73J5l1wj54SJY/tL4hn88j8vzzrfGlr0PM5/Oevt2kG34n2Qm+h2BLgy0tzl3LUaJmZ2e31dpuJDt9cz/P2bG0TS5jx9SsHWEwaJJsL/9qtYpYLNY2uWNjY1Tzx8bGPHWhUAixWKwtEvATP/xvhYZ8Sz/4Xg22B393/h6NFlKpFNXCfkQQBDrjq6uruHvnHt2wWCR3NhGO+L1fkiTf+259Oklr25deftm39IsPwIqDHW0qFouUnGQySRspioJCoUCdVywWQyaT8a0bHR1FKpWidstxesUHRbxy5rStvbZpMJskOyaC4H+30Xj31+/uOaa10WAYsAyDcrlshViiSJe3oigYGRnxdFIUBYqiIJlMIh6Pt9WtrKxQryyKIiRJQrlctnaArItUNMltRuVNLFVVfZ2No7mJRKKt3q9PJ2lt6zYHbvm7Vu8Ln5oIZ8DODu3w4cO0QTqdpvanXq9Tp3fx4kVks1m6bOr1Oubm5jwxMgB6v7mx2TQH9Orw2m4iIpEIFEWBpmme5+5wqjW00jQNiqIgEolsO3A//FMvvehb+sH3aLDbubTaGWfGEokEQqEQJdpxOI6WOnWiKLY5nmb4Rf9s+2HiORHVmSrS6TTm5uZ6GoyjDOI5sS/8927f3jN8jwb/P8rR40cQjoQhy3JbtNBp8LIsIxwJ95Q32G98L8HEuyty2xlHmyVJwvr6OlRVxdDQELLZbDPWtbfJ7jr3smrGr/RPTx/3k59NIBAIQJIkxONxiuWOgzVNQzwex82bNxEIBDCeHO958J3wW81Ov/jURDgfPBgYxObGJlZWVmiDTCZDX37o0CHPi506VVXb6hxxsAYDgyDEtR0GgTOn9q+2j3s28CwKt27iF2/nIMsyZFlGNBpFNBqFIAhQFIUqQz/JmP3Gp3774aOHOHDgALKXspDnZAiCgLW1tZ7CNFmWUSgUaFt3HQAMDQ1B0zScevEUbuSv4z9bW2g0ttDQG2g0dBhOXsI0YBomTcK37tS+iOlKmuz529JfMTBwAB8tfITkD5N0W+jEs/2KkyABgJm3Z/Dd09/BVmMLW40G9EYDDb2FYJ+Ezxc94c4CoEc6sZFhBINBAEA2m/W1Sb3K+vo69brBYNBOxDupSROmbYsdc/GkCgsAJjFhGNY52pWrlylB8Xjck+PdCbkjIyO078RbE3aC3WiS7EpRUidLnqwjI+rcAZDJzCRZXC4T9XGFvPb91xxXT6LRKKlUKqRXqdfrJBqN0v5iXCTq4wpZXC6Ty1cv0+dfotL8kXojSZYqi0T9WCViXKTPBUEg09PTZG1trSOxa2trZHp6mgiCQPsdP3GcrHyskiV1kUxmJr+M5BKmNSidykxiNC6C53ncyN3AB7/7oO8jo+yVaei6jocPy3j9B6/3v8RcZsN9muHefbb+3im+H5bfe/s2Ee4ylZm0NPlxhbwv/ZYEg8GeZywYDJLCrwpEfVwhS+oieee9d3atBYSQrvfuZ/3ib4fb7zuYTtuq1BtJvPq9V+kphFIs4c78na7H9mfFs4jFhulZ2/z8HcxkZ3bvJLpo0m40109j/a67eQ/Tbd969NgRTGUu4RvfDLpOI9zpRnjiVuc/nqx+8gl+eT2PhdLC3njhLgPdS4Ldk/m5EOzIyeGTOH3mNI69cAxfDQS8OVw7tPp0YwOPlh7h/t37e0bs563B+2GDeyL4qfQvDCHkGYZh/v2Uin3YYBDC/HcArOiX8zGX6zMAAAAASUVORK5CYII=",
-"cc-by-nc":"data:image/png;base64,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",
-"cc-by-nc-sa":"data:image/png;base64,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",
-"cc-by-nc-nd":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAAAfCAYAAABjyArgAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAEZ0FNQQAAsY58+1GTAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAm8SURBVHja7FpdcBvVFf52pXgGplH11mbkDPbQdqy8oIQmMZRiufwMxRivJiHtFChyZwqUlMoiiWlaO5JCfkBNKqvhp30oUsswMCVMlL9CHRqt4xTLkmKtE7D8UMZisIf2pZLltDO1Vnv6sNprrS1bsgNDGjgz17vW3fvt3W/PPfe75y5HRCaO46bxhX3iRkQcB4AA4HT/KfA8D57nYTAYwPMGGHgevKF05HlwHA+e48BxHMBxGgoIBFIICilQFLUUi0X1qBRRLCpQlCKrU0hh1xOR1hl2fi3YAx3bAAAcANLINRgMauENc+cGg1rHG0okc+A4vpzfEjklYhWVzGKxVMrPi3qSFUVhxJYTfS2RbASgJ9dghFF3VMvJ46cQjUYRj8cxk5/RAa02rcamTZvQ+p1WtN9/H4qKATwvqy+kyIMDV3qXZcNHIXUkoDSGOJXckUQKkTcjSKfTuuutViuELQI2bFxf08NdLTgcAPrL2bdhNBoZqUajUS0GIwbEc/A/68fU1FRNHbJYLOje3Y2WltshF4soFmXIcqkUZchykXl4uSd/PPUxjvQ9j/H0OADAbrfDZrMBACRJgiiKAIAmaxO2u7bjq2u+UvH+//j4n3gh+MJVgfNAxzaV4HcGzsBoMM4Ra1yFVUYjPL1eRI5FWAOz2QxBENDQ0ICWlhYAwMDAADKZDCKRCHK5HLtWcAjY2b0D111/HWRZRkGWIcsFyLKsDxmkYDo7jZ8+/iTy+TwEQUAgEEBDQ4Ous5lMBm63G5FIBCaTCfv9+xc81OX8Zbi2d101OFocprODZ2lw6BwNJYYoKSVo9D2JBIdApcFLZrOZvF4vZbNZWspCoRCZzWbWrsnaROeHBikpJSmWHKLBoXMUHTxLZ8R+evuvb9Hp/lN04q3jZLVaCQA5nU4dnoYz/x4a9hvH/6QrTdamijjBQIB+8L3vXzHOYs+8GA4A4gHAUIrBRoMBRoPec202G1KpFDweD8xm85Lhwel0YmJigg2l8fQ4DvkP62I5zxSJqkYSsQTS6TQEQUD3rl1VQ5DT6YQgCBhPj2MkkdLFyvH0ODasX49bm29hv/+mrw/P+v04efo0nt65C5OTkzXhXGl/dPPNYGyQYskYjYxeoOCRIPMcm81W1WsrWTabJZvNxnCCzwdp5OIIDV+I0fnYIEXPq1781jt/Jus61XsnJiZqxp+YmCAAZLVambdoo6Dp69+gG29ooJZv3UaP//hRAkBer5cOHjhIAOjoG2/UhHOl/angwaoX+5/1s3gbCoWqem0lM5vNiEajrK3/oL+kpUsezJU0Nc8jPZaG3W5fEOM6OzuZl3d2durqGhoaYLfbdTN7Oq3itLe344Ft2zA5OYkz/f248YYG/GfmMh56+CGMvf8+tmzdWhNOeX++1tBYsSyFoxmvyTSeV6WYpha6urrYUF+Jmc1mBAIBAMDU1BROnjjFFiwqyRyTaZXuEw6HK55rVqmNzWaD//AhHPQ/h1dffw1btm7FBx9m4D98CGvXrkX45RDSY2M14ZTbXffcU7FUwwGg6mDNm6LRKCPH5XKxi0RRRDAYZCrBbrfD4/FUrOvo6EBXVxeLT263G7lcDtGzUdzX3lbyXg4cz4FTuE9N5G9ubsbm5mY82eXCkb4gzvT3482jR/Hm0aPY3NwM5486cdfdd9eE9dJvX1pxP9SFBseB5zjE43FVYgkCG96iKKK1tVXXSBRFiKIIl8sFh8OxoG50dBShUIhhhcNhxONxdQXIc2zoa4sPSZIqTh6a5zqdzgX1ldrM/y2fz+NMfz+eO/QrOMc60X5vGwBgOBbDcCyG+vp6cKuMVXHKw0G5/T0zsWR/yjxYfWBthXbTTTexC9xuN4sz0WgUmUwGnZ2deOSRR+Dz+djwOHbsGCRJgtvtZhoZAFpaWhAOhzGTn1HvA67sCKxbtw6iKCKTyejiXigUYgRrL6tcg4qiCKvVqltZzcf5yaOPYTgWw5G+IADggw8z6N6xE5uaN+OiNIo/hMP4cGqyKs4dd925pJdW6o9ORSSlBF0au8hm/Wg0ukCLer3eBbPnUnWaRaNRdt2lsYuUlJL0bvxdGvibSO8MnCGPbw8BIEEQFsWfb4KgavTdPbvZjL27Z/cCnI8++oj2+fbSmjVraPWXVlMwEKDp6ell41SzSjg6FfFZ2i233QLrOisikcgCtVDJtNVTk7VJlwfYsHE9mqxNOpz6+nr8ck8vdrifQntbG37W1QWTybRsnJX0R6ciQPosVnk80WbHcDiMXC4HSZLQ2NgIn8/H6rRlcnld+fCZy4+yP7pO9Hp7YTKZEA6H4XA4WJvyLFsmk4HD4UBfXx9MJhO2u7YveJinf9FdEWfHrp149fXXrhhnfliohsOSPYmROOrq6nDbrd/GTH4GTqeTxb1IJLJgItMmno6OjkXrtPZutxt9fX1YbVqN8+8OYnZ2FrOFWRTkAgoFWU0GFWVk/5XDAd8BpiVtNhtsNhvMZjNEUWQvvVqS5nL+Mp474GdJms8ShyV7hi8Mo66uDr49PkSORWA2m5HNZmuSaZFIBMFgkF1bXgcAjY2NyGQyuOPOO3A4cAj/nZ1FYR7BWt5YKSpIDCdw7Oi1ka5kBMeSQ1i1qg7nz52H60lV/wYCAaZnV2rhcJjFsX0H9uHetu9itjCL2UIBcqGAgjyP4AoJ+P/3hDsPgG3p2FtbYLFYAAA+n69i7KnVcrkck3gWi6WUiC/tYigKlFIsptKW07VqPAAopKBYVPfRntm/lxHkcDh0Od7lkNva2sradv+8u5RgL86RXLZlxCZZura2jNjkDoB6PD2UGImTdClFD//wYV1GLZVKLSuzVJ5JExwCSZdSlBiJ0979e9nvn6My90/XUy5KphIkrSDhns1myev16hLuGzdtpNH3JEpKCerx9HweySVuvijt9fSgwyHAaDTisP8wXvnjKyveMvI944UsyxgejuOJx56o5TuCOf1YyrQRlW2OVvh/MZzF2mj3qIaxFE6lflYNEeWl19OjevKlFL0c/j1ZLJaa35jFYqHgkSBJl1KUlBL04u9erLnt/OXx/PPy36rhVGtfC9YngbPAgzXresqFBx96kG31iNEBnDh+Yslt+/uF+2G3t7ANzePHT2Cfb99yvoRZ1DNq8dxKnlbpuJz+VMOphrkowQCw4eb16PXsQf1aS9luRHm6ETrdqn14MjU5iV8fCuDcwLnlfmp0RaGhWkhYDjGfFM6SBGt2e8vtaGtvw83fvBlfNplKn07NBRgiwnQ+jwvJCzh98vSyif20PPhqiME1EfyFrdw4Irqe47h/f0HFp7DAIOL+NwDFrtvhh4x87AAAAABJRU5ErkJggg=="},
-d;return{_setup:function(a){var c="",f=a.license&&b[a.license.toLowerCase()];a._container=document.createElement("div");a._container.style.display="none";d=document.getElementById(a.target);if(a.nameofworkurl)c+="<a href='"+a.nameofworkurl+"' target=_blank>";if(a.nameofwork)c+=a.nameofwork;if(a.nameofworkurl)c+="</a>";if(a.copyrightholderurl)c+="<a href='"+a.copyrightholderurl+"' target=_blank>";if(a.copyrightholder)c+=", "+a.copyrightholder;if(a.copyrightholderurl)c+="</a>";if(c==="")c=a.text;if(a.license)if(f)c=
-a.licenseurl?"<a href='"+a.licenseurl+"' target=_blank><img src='"+f+"' border='0'/></a> "+c:"<img src='"+f+"' />"+c;else{c+=", license: ";c+=a.licenseurl?"<a href='"+a.licenseurl+"' target=_blank>"+a.license+"</a> ":a.license}else if(a.licenseurl)c+=", <a href='"+a.licenseurl+"' target=_blank>license</a> ";a._container.innerHTML=c;if(!d&&g.plugin.debug)throw Error("target container doesn't exist");d&&d.appendChild(a._container)},start:function(a,c){c._container.style.display="inline"},end:function(a,
-c){c._container.style.display="none"},_teardown:function(a){(d=document.getElementById(a.target))&&d.removeChild(a._container)}}}(),{about:{name:"Popcorn Attribution Plugin",version:"0.2",author:"@rwaldron",website:"github.com/rwldrn"},options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},nameofwork:{elem:"input",type:"text",label:"Name of Work"},nameofworkurl:{elem:"input",type:"url",label:"Url of Work",optional:true},copyrightholder:{elem:"input",type:"text",
-label:"Copyright Holder"},copyrightholderurl:{elem:"input",type:"url",label:"Copyright Holder Url",optional:true},license:{elem:"input",type:"text",label:"License type"},licenseurl:{elem:"input",type:"url",label:"License URL",optional:true},target:"attribution-container"}})})(Popcorn);(function(g){g.plugin("code",function(b){var d=false,a=function(){var c=function(f){return function(h){var p=function(){d&&h();d&&f(p)};p()}};return window.webkitRequestAnimationFrame?c(window.webkitRequestAnimationFrame):window.mozRequestAnimationFrame?c(window.mozRequestAnimationFrame):c(function(f){window.setTimeout(f,16)})}();if(!b.onStart||typeof b.onStart!=="function"){if(g.plugin.debug)throw Error("Popcorn Code Plugin Error: onStart must be a function.");b.onStart=g.nop}if(b.onEnd&&typeof b.onEnd!==
-"function"){if(g.plugin.debug)throw Error("Popcorn Code Plugin Error: onEnd  must be a function.");b.onEnd=undefined}if(b.onFrame&&typeof b.onFrame!=="function"){if(g.plugin.debug)throw Error("Popcorn Code Plugin Error: onFrame  must be a function.");b.onFrame=undefined}return{start:function(c,f){f.onStart(f);if(f.onFrame){d=true;a(f.onFrame,f)}},end:function(c,f){if(f.onFrame)d=false;f.onEnd&&f.onEnd(f)}}},{about:{name:"Popcorn Code Plugin",version:"0.1",author:"David Humphrey (@humphd)",website:"http://vocamus.net/dave"},
-options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},onStart:{elem:"input",type:"function",label:"onStart"},onFrame:{elem:"input",type:"function",label:"onFrame",optional:true},onEnd:{elem:"input",type:"function",label:"onEnd"}}})})(Popcorn);(function(g){var b=0;g.plugin("flickr",function(d){var a,c=document.getElementById(d.target),f,h,p,o,l=d.numberofimages||4,i=d.height||"50px",r=d.width||"50px",k=d.padding||"5px",j=d.border||"0px";a=document.createElement("div");a.id="flickr"+b;a.style.width="100%";a.style.height="100%";a.style.display="none";b++;if(!c&&g.plugin.debug)throw Error("flickr target container doesn't exist");c&&c.appendChild(a);var v=function(){if(f)setTimeout(function(){v()},5);else{h="http://api.flickr.com/services/rest/?method=flickr.people.findByUsername&";
-h+="username="+d.username+"&api_key="+d.apikey+"&format=json&jsoncallback=flickr";g.getJSONP(h,function(n){f=n.user.nsid;w()})}},w=function(){h="http://api.flickr.com/services/feeds/photos_public.gne?";if(f)h+="id="+f+"&";if(d.tags)h+="tags="+d.tags+"&";h+="lang=en-us&format=json&jsoncallback=flickr";g.xhr.getJSONP(h,function(n){var y=document.createElement("div");y.innerHTML="<p style='padding:"+k+";'>"+n.title+"<p/>";g.forEach(n.items,function(C,e){if(e<l){p=document.createElement("a");p.setAttribute("href",
-C.link);p.setAttribute("target","_blank");o=document.createElement("img");o.setAttribute("src",C.media.m);o.setAttribute("height",i);o.setAttribute("width",r);o.setAttribute("style","border:"+j+";padding:"+k);p.appendChild(o);y.appendChild(p)}else return false});a.appendChild(y)})};if(d.username&&d.apikey)v();else{f=d.userid;w()}return{start:function(){a.style.display="inline"},end:function(){a.style.display="none"},_teardown:function(n){document.getElementById(n.target)&&document.getElementById(n.target).removeChild(a)}}},
-{about:{name:"Popcorn Flickr Plugin",version:"0.2",author:"Scott Downe, Steven Weerdenburg, Annasob",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"number",label:"In"},end:{elem:"input",type:"number",label:"Out"},userid:{elem:"input",type:"text",label:"UserID",optional:true},tags:{elem:"input",type:"text",label:"Tags"},username:{elem:"input",type:"text",label:"Username",optional:true},apikey:{elem:"input",type:"text",label:"Api_key",optional:true},target:"flickr-container",
-height:{elem:"input",type:"text",label:"Height",optional:true},width:{elem:"input",type:"text",label:"Width",optional:true},padding:{elem:"input",type:"text",label:"Padding",optional:true},border:{elem:"input",type:"text",label:"Border",optional:true},numberofimages:{elem:"input",type:"text",label:"Number of Images"}}})})(Popcorn);(function(g){g.forEach(["footnote","text"],function(b){g.plugin(b,{manifest:{about:{name:"Popcorn "+b+" Plugin",version:"0.2",author:"@annasob, @rwaldron",website:"annasob.wordpress.com"},options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},text:{elem:"input",type:"text",label:"Text"},target:b+"-container"}},_setup:function(d){var a=document.getElementById(d.target);d._container=document.createElement("div");d._container.style.display="none";d._container.innerHTML=
-d.text;if(!a&&g.plugin.debug)throw Error("target container doesn't exist");a&&a.appendChild(d._container)},start:function(d,a){a._container.style.display="inline"},end:function(d,a){a._container.style.display="none"},_teardown:function(d){document.getElementById(d.target)&&document.getElementById(d.target).removeChild(d._container)}})})})(Popcorn);(function(g,b){var d=false;g.plugin("facebook",{manifest:{about:{name:"Popcorn Facebook Plugin",version:"0.1",author:"Dan Ventura, Matthew Schranz: @mjschranz",website:"dsventura.blogspot.com, mschranz.wordpress.com"},options:{type:{elem:"select",options:["LIKE","LIKE-BOX","ACTIVITY","FACEPILE","LIVE-STREAM","SEND","COMMENTS"],label:"Type"},target:"facebook-container",start:{elem:"input",type:"number",label:"In"},end:{elem:"input",type:"number",label:"Out"},font:{elem:"input",type:"text",label:"font",
-optional:true},xid:{elem:"input",type:"text",label:"Xid",optional:true},href:{elem:"input",type:"url",label:"Href",optional:true},site:{elem:"input",type:"url",label:"Site",optional:true},height:{elem:"input",type:"text",label:"Height",optional:true},width:{elem:"input",type:"text",label:"Width",optional:true},action:{elem:"select",options:["like","recommend"],label:"Action",optional:true},stream:{elem:"select",options:["false","true"],label:"Stream",optional:true},header:{elem:"select",options:["false",
-"true"],label:"Header",optional:true},layout:{elem:"select",options:["standard","button_count","box_count"],label:"Layout",optional:true},max_rows:{elem:"input",type:"text",label:"Max_rows",optional:true},border_color:{elem:"input",type:"text",label:"Border_color",optional:true},event_app_id:{elem:"input",type:"text",label:"Event_app_id",optional:true},colorscheme:{elem:"select",options:["light","dark"],label:"Colorscheme",optional:true},show_faces:{elem:"select",options:["false","true"],label:"Showfaces",
-optional:true},recommendations:{elem:"select",options:["false","true"],label:"Recommendations",optional:true},always_post_to_friends:{elem:"input",options:["false","true"],label:"Always_post_to_friends",optional:true},num_posts:{elem:"input",type:"text",label:"Number_of_Comments",optional:true}}},_setup:function(a){var c=document.getElementById(a.target),f=a.type;if(!document.getElementById("fb-root")){var h=document.createElement("div");h.setAttribute("id","fb-root");document.body.appendChild(h)}if(!d||
-a.event_app_id){d=true;g.getScript("//connect.facebook.net/en_US/all.js");b.fbAsyncInit=function(){FB.init({appId:a.event_app_id||"",status:true,cookie:true,xfbml:true})}}f=f.toLowerCase();if(!(["like","like-box","activity","facepile","live-stream","send","comments"].indexOf(f)>-1))throw Error("Facebook plugin type was invalid.");a._container=document.createElement("div");a._container.id="facebookdiv-"+g.guid();a._facebookdiv=document.createElement("fb:"+f);a._container.appendChild(a._facebookdiv);
-a._container.style.display="none";f=f==="activity"?"site":"href";a._facebookdiv.setAttribute(f,a[f]||document.URL);f="width height layout show_faces stream header colorscheme maxrows border_color recommendations font always_post_to_friends xid num_posts".split(" ");g.forEach(f,function(p){a[p]!=null&&a._facebookdiv.setAttribute(p,a[p])});if(!c&&g.plugin.debug)throw Error("Facebook target container doesn't exist");c&&c.appendChild(a._container)},start:function(a,c){c._container.style.display=""},end:function(a,
-c){c._container.style.display="none"},_teardown:function(a){var c=document.getElementById(a.target);c&&c.removeChild(a._container)}})})(Popcorn,this);var googleCallback;
-(function(g){var b=1,d=false,a=false,c,f;googleCallback=function(h){if(typeof google!=="undefined"&&google.maps&&google.maps.Geocoder&&google.maps.LatLng){c=new google.maps.Geocoder;a=true}else setTimeout(function(){googleCallback(h)},1)};f=function(){if(document.body){d=true;g.getScript("//maps.google.com/maps/api/js?sensor=false&callback=googleCallback")}else setTimeout(function(){f()},1)};g.plugin("googlemap",function(h){var p,o,l,i=document.getElementById(h.target);d||f();p=document.createElement("div");
-p.id="actualmap"+b;p.style.width="100%";p.style.height="100%";b++;if(!i&&g.plugin.debug)throw Error("target container doesn't exist");i&&i.appendChild(p);var r=function(){if(a)if(h.location)c.geocode({address:h.location},function(k,j){if(j===google.maps.GeocoderStatus.OK){h.lat=k[0].geometry.location.lat();h.lng=k[0].geometry.location.lng();l=new google.maps.LatLng(h.lat,h.lng);o=new google.maps.Map(p,{mapTypeId:google.maps.MapTypeId[h.type]||google.maps.MapTypeId.HYBRID});o.getDiv().style.display=
-"none"}});else{l=new google.maps.LatLng(h.lat,h.lng);o=new google.maps.Map(p,{mapTypeId:google.maps.MapTypeId[h.type]||google.maps.MapTypeId.HYBRID});o.getDiv().style.display="none"}else setTimeout(function(){r()},5)};r();return{start:function(k,j){var v=this,w,n=function(){if(o){o.getDiv().style.display="block";google.maps.event.trigger(o,"resize");o.setCenter(l);if(j.zoom&&typeof j.zoom!=="number")j.zoom=+j.zoom;j.zoom=j.zoom||8;o.setZoom(j.zoom);if(j.heading&&typeof j.heading!=="number")j.heading=
-+j.heading;if(j.pitch&&typeof j.pitch!=="number")j.pitch=+j.pitch;if(j.type==="STREETVIEW"){o.setStreetView(w=new google.maps.StreetViewPanorama(p,{position:l,pov:{heading:j.heading=j.heading||0,pitch:j.pitch=j.pitch||0,zoom:j.zoom}}));var y=function(u,x){var A=google.maps.geometry.spherical.computeHeading;setTimeout(function(){var B=v.media.currentTime;if(typeof j.tween==="object"){for(var D=0,E=u.length;D<E;D++){var z=u[D];if(B>=z.interval*(D+1)/1E3&&(B<=z.interval*(D+2)/1E3||B>=z.interval*E/1E3)){s.setPosition(new google.maps.LatLng(z.position.lat,
-z.position.lng));s.setPov({heading:z.pov.heading||A(z,u[D+1])||0,zoom:z.pov.zoom||0,pitch:z.pov.pitch||0})}}y(u,u[0].interval)}else{D=0;for(E=u.length;D<E;D++){z=j.interval;if(B>=z*(D+1)/1E3&&(B<=z*(D+2)/1E3||B>=z*E/1E3)){C.setPov({heading:A(u[D],u[D+1])||0,zoom:j.zoom,pitch:j.pitch||0});C.setPosition(e[D])}}y(e,j.interval)}},x)};if(j.location&&typeof j.tween==="string"){var C=w,e=[],m=new google.maps.DirectionsService,q=new google.maps.DirectionsRenderer(C);m.route({origin:j.location,destination:j.tween,
-travelMode:google.maps.TravelMode.DRIVING},function(u,x){if(x==google.maps.DirectionsStatus.OK){q.setDirections(u);for(var A=u.routes[0].overview_path,B=0,D=A.length;B<D;B++)e.push(new google.maps.LatLng(A[B].lat(),A[B].lng()));j.interval=j.interval||1E3;y(e,10)}})}else if(typeof j.tween==="object"){var s=w;m=0;for(var t=j.tween.length;m<t;m++){j.tween[m].interval=j.tween[m].interval||1E3;y(j.tween,10)}}}}else setTimeout(function(){n()},13)};n()},end:function(){if(o)o.getDiv().style.display="none"},
-_teardown:function(k){(k=document.getElementById(k.target))&&k.removeChild(p);p=o=l=null}}},{about:{name:"Popcorn Google Map Plugin",version:"0.1",author:"@annasob",website:"annasob.wordpress.com"},options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},target:"map-container",type:{elem:"select",options:["ROADMAP","SATELLITE","STREETVIEW","HYBRID","TERRAIN"],label:"Type",optional:true},zoom:{elem:"input",type:"text",label:"Zoom",optional:true},lat:{elem:"input",
-type:"text",label:"Lat",optional:true},lng:{elem:"input",type:"text",label:"Lng",optional:true},location:{elem:"input",type:"text",label:"Location"},heading:{elem:"input",type:"text",label:"Heading",optional:true},pitch:{elem:"input",type:"text",label:"Pitch",optional:true}}})})(Popcorn);(function(g){g.plugin("image",{manifest:{about:{name:"Popcorn image Plugin",version:"0.1",author:"Scott Downe",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"number",label:"In"},end:{elem:"input",type:"number",label:"Out"},href:{elem:"input",type:"url",label:"anchor URL",optional:true},target:"image-container",src:{elem:"input",type:"url",label:"Source URL"},text:{elem:"input",type:"text",label:"TEXT",optional:true}}},_setup:function(b){var d=document.createElement("img"),
-a=document.getElementById(b.target);b.anchor=document.createElement("a");b.anchor.style.position="relative";b.anchor.style.textDecoration="none";b.anchor.style.display="none";if(!a&&g.plugin.debug)throw Error("target container doesn't exist");a&&a.appendChild(b.anchor);d.addEventListener("load",function(){d.style.borderStyle="none";b.anchor.href=b.href||b.src||"#";b.anchor.target="_blank";var c,f;if(b.text){c=d.height/12+"px";f=document.createElement("div");g.extend(f.style,{color:"black",fontSize:c,
-fontWeight:"bold",position:"relative",textAlign:"center",width:d.width+"px",zIndex:"10"});f.innerHTML=b.text||"";f.style.top=d.height/2-f.offsetHeight/2+"px";b.anchor.appendChild(f)}b.anchor.appendChild(d)},false);d.src=b.src},start:function(b,d){d.anchor.style.display="inline"},end:function(b,d){d.anchor.style.display="none"},_teardown:function(b){document.getElementById(b.target)&&document.getElementById(b.target).removeChild(b.anchor)}})})(Popcorn);(function(g){var b=function(d){var a=0,c=0,f=0,h=null,p=null,o=false,l=0,i=function(){},r=function(){d.background(0);c=f=0;h=p=null};d.draw=function(){i()};d.setup=function(){};d.construct=function(k,j,v){var w=function(){if(j){l=j.gml.tag.drawing.stroke;var n=(v.end-v.start)/(l.pt||function(C){for(var e=[],m=0,q=C.length;m<q;m++)e=e.concat(C[m].pt);return e}(l)).length,y=j.gml.tag;y=y.header&&y.header.client&&y.header.client.name;o=y==="Graffiti Analysis 2.0: DustTag"||y==="DustTag: Graffiti Analysis 2.0"||
-y==="Fat Tag - Katsu Edition";i=function(){if(k.currentTime<v.endDrawing){var C=(k.currentTime-v.start)/n;for(C<c&&r();c<=C;){if(!l)break;a=l[f]||l;var e=a.pt[c],m=c;if(h!=null){var q=e.x,s=e.y,t=void 0,u=void 0,x=void 0,A=void 0;if(o){t=p*d.height;u=d.width-h*d.width;x=s*d.height;A=d.width-q*d.width}else{t=h*d.width;u=p*d.height;x=q*d.width;A=s*d.height}d.stroke(0);d.strokeWeight(13);d.strokeCap(d.SQUARE);d.line(t,u,x,A);d.stroke(255);d.strokeWeight(12);d.strokeCap(d.ROUND);d.line(t,u,x,A)}h=e.x;
-p=e.y;c===m&&c++}}}}else setTimeout(w,5)};d.size(640,640);d.frameRate(60);d.smooth();r();d.noLoop();w()}};g.plugin("gml",{_setup:function(d){var a=this,c=document.getElementById(d.target);d.endDrawing=d.endDrawing||d.end;d.container=document.createElement("canvas");d.container.style.display="none";d.container.setAttribute("id","canvas"+d.gmltag);if(!c&&g.plugin.debug)throw Error("target container doesn't exist");c&&c.appendChild(d.container);c=function(){g.getJSONP("//000000book.com/data/"+d.gmltag+
-".json?callback=",function(f){d.pjsInstance=new Processing(d.container,b);d.pjsInstance.construct(a.media,f,d);d._running&&d.pjsInstance.loop()},false)};window.Processing?c():g.getScript("//cloud.github.com/downloads/processing-js/processing-js/processing-1.3.6.min.js",c)},start:function(d,a){a.pjsInstance&&a.pjsInstance.loop();a.container.style.display="block"},end:function(d,a){a.pjsInstance&&a.pjsInstance.noLoop();a.container.style.display="none"},_teardown:function(d){d.pjsInstance&&d.pjsInstance.exit();
-document.getElementById(d.target)&&document.getElementById(d.target).removeChild(d.container)}})})(Popcorn);(function(g){var b={},d=function(a){if(a.artist){var c="";c="<h3>"+a.artist.name+"</h3>";c+="<a href='"+a.artist.url+"' target='_blank' style='float:left;margin:0 10px 0 0;'><img src='"+a.artist.image[2]["#text"]+"' alt=''></a>";c+="<p>"+a.artist.bio.summary+"</p>";c+="<hr /><p><h4>Tags</h4><ul>";g.forEach(a.artist.tags.tag,function(f){c+="<li><a href='"+f.url+"'>"+f.name+"</a></li>"});c+="</ul></p>";c+="<hr /><p><h4>Similar</h4><ul>";g.forEach(a.artist.similar.artist,function(f){c+="<li><a href='"+
-f.url+"'>"+f.name+"</a></li>"});c+="</ul></p>";b[a.artist.name.toLowerCase()].htmlString=c}};g.plugin("lastfm",function(){return{_setup:function(a){a._container=document.createElement("div");a._container.style.display="none";a._container.innerHTML="";a.artist=a.artist&&a.artist.toLowerCase()||"";var c=document.getElementById(a.target);if(!c&&g.plugin.debug)throw Error("target container doesn't exist");c&&c.appendChild(a._container);if(!b[a.artist]){b[a.artist]={count:0,htmlString:"Unknown Artist"};
-g.getJSONP("//ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist="+a.artist+"&api_key="+a.apikey+"&format=json&callback=lastFMcallback",d,false)}b[a.artist].count++},start:function(a,c){c._container.innerHTML=b[c.artist].htmlString;c._container.style.display="inline"},end:function(a,c){c._container.style.display="none";c._container.innerHTML=""},_teardown:function(a){--b[a.artist].count||delete b[a.artist];document.getElementById(a.target)&&document.getElementById(a.target).removeChild(a._container)}}}(),
-{about:{name:"Popcorn LastFM Plugin",version:"0.1",author:"Steven Weerdenburg",website:"http://sweerdenburg.wordpress.com/"},options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},target:"lastfm-container",artist:{elem:"input",type:"text",label:"Artist"}}})})(Popcorn);(function(g){g.plugin("lowerthird",{manifest:{about:{name:"Popcorn lowerthird Plugin",version:"0.1",author:"Scott Downe",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},target:"lowerthird-container",salutation:{elem:"input",type:"text",label:"Text",optional:true},name:{elem:"input",type:"text",label:"Text"},role:{elem:"input",type:"text",label:"Text",optional:true}}},_setup:function(b){var d=document.getElementById(b.target);
-if(!this.container){this.container=document.createElement("div");this.container.style.position="absolute";this.container.style.color="white";this.container.style.textShadow="black 2px 2px 6px";this.container.style.fontSize="24px";this.container.style.fontWeight="bold";this.container.style.paddingLeft="40px";this.container.style.width=this.video.offsetWidth+"px";this.container.style.left=this.position().left+"px";this.video.parentNode.appendChild(this.container)}if(b.target&&b.target!=="lowerthird-container"){b.container=
-document.createElement("div");if(!d&&g.plugin.debug)throw Error("target container doesn't exist");d&&d.appendChild(b.container)}else b.container=this.container},start:function(b,d){d.container.innerHTML=(d.salutation?d.salutation+" ":"")+d.name+(d.role?"<br />"+d.role:"");this.container.style.top=this.position().top+this.video.offsetHeight-(40+this.container.offsetHeight)+"px"},end:function(b,d){for(;d.container.firstChild;)d.container.removeChild(d.container.firstChild)}})})(Popcorn);(function(g){var b=1,d=false;g.plugin("googlefeed",function(a){var c=function(){var o=false,l=0,i=document.getElementsByTagName("link"),r=i.length,k=document.head||document.getElementsByTagName("head")[0],j=document.createElement("link");if(window.GFdynamicFeedControl)d=true;else g.getScript("//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.js",function(){d=true});for(;l<r;l++)if(i[l].href==="//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.css")o=true;if(!o){j.type=
-"text/css";j.rel="stylesheet";j.href="//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.css";k.insertBefore(j,k.firstChild)}};window.google?c():g.getScript("//www.google.com/jsapi",function(){google.load("feeds","1",{callback:function(){c()}})});var f=document.createElement("div"),h=document.getElementById(a.target),p=function(){if(d)a.feed=new GFdynamicFeedControl(a.url,f,{vertical:a.orientation.toLowerCase()==="vertical"?true:false,horizontal:a.orientation.toLowerCase()==="horizontal"?
-true:false,title:a.title=a.title||"Blog"});else setTimeout(function(){p()},5)};if(!a.orientation||a.orientation.toLowerCase()!=="vertical"&&a.orientation.toLowerCase()!=="horizontal")a.orientation="vertical";f.style.display="none";f.id="_feed"+b;f.style.width="100%";f.style.height="100%";b++;if(!h&&g.plugin.debug)throw Error("target container doesn't exist");h&&h.appendChild(f);p();return{start:function(){f.setAttribute("style","display:inline")},end:function(){f.setAttribute("style","display:none")},
-_teardown:function(o){document.getElementById(o.target)&&document.getElementById(o.target).removeChild(f);delete o.feed}}},{about:{name:"Popcorn Google Feed Plugin",version:"0.1",author:"David Seifried",website:"dseifried.wordpress.com"},options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},target:"feed-container",url:{elem:"input",type:"url",label:"url"},title:{elem:"input",type:"text",label:"title",optional:true},orientation:{elem:"select",options:["Vertical",
-"Horizontal"],label:"orientation",optional:true}}})})(Popcorn);(function(g){var b={},d={},a={};g.plugin("rdio",function(){var c=function(f){var h=function(p){return"http://www.rdio.com/api/oembed/?format=json&url=http://www.rdio.com/%23"+{playlist:function(){return"/people/"+f.person+"/playlists/"+f.id+"/"},album:function(){return"/artist/"+f.artist+"/album/"}}[p]()+f[p]+"/&callback=_loadResults"}(f.type);g.getJSONP(h,function(p){var o=p.title,l=p.html;if(p&&o&&l)b[f.containerid].htmlString="<div>"+l+"</div>";else if(g.plugin.debug)throw Error("Did not receive data from server.");
-},false)};return{_setup:function(f){var h=f.containerid=g.guid(),p=d[h]=document.createElement("div"),o=a[h]=document.getElementById(f.target);if(!o&&g.plugin.debug)throw Error("Target container could not be found.");p.style.display="none";p.innerHTML="";o.appendChild(p);b[h]={htmlString:f.playlist||"Unknown Source"||f.album||"Unknown Source"};c(f)},start:function(f,h){var p=h.containerid,o=d[p];o.innerHTML=b[p].htmlString;o.style.display="inline"},end:function(f,h){container=d[h.containerid];container.style.display=
-"none";container.innerHTML=""},_teardown:function(f){f=f.containerid;var h=a[f];b[f]&&delete b[f];h&&h.removeChild(d[f]);delete a[f];delete d[f]}}}(),{manifest:{about:{name:"Popcorn Rdio Plugin",version:"0.1",author:"Denise Rigato"},options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},target:"rdio",artist:{elem:"input",type:"text",label:"Artist"},album:{elem:"input",type:"text",label:"Album"},person:{elem:"input",type:"text",label:"Person"},id:{elem:"input",
-type:"text",label:"Id"},playlist:{elem:"input",type:"text",label:"Playlist"}}}})})(Popcorn);(function(g){var b=0,d=function(a,c){var f=a.container=document.createElement("div"),h=f.style,p=a.media,o=function(){var l=a.position();h.fontSize="18px";h.width=p.offsetWidth+"px";h.top=l.top+p.offsetHeight-f.offsetHeight-40+"px";h.left=l.left+"px";setTimeout(o,10)};f.id=c||g.guid();h.position="absolute";h.color="white";h.textShadow="black 2px 2px 6px";h.fontWeight="bold";h.textAlign="center";o();a.media.parentNode.appendChild(f);return f};g.plugin("subtitle",{manifest:{about:{name:"Popcorn Subtitle Plugin",
-version:"0.1",author:"Scott Downe",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},target:"subtitle-container",text:{elem:"input",type:"text",label:"Text"}}},_setup:function(a){var c=document.createElement("div");c.id="subtitle-"+b++;c.style.display="none";!this.container&&(!a.target||a.target==="subtitle-container")&&d(this);a.container=a.target&&a.target!=="subtitle-container"?document.getElementById(a.target)||
-d(this,a.target):this.container;document.getElementById(a.container.id)&&document.getElementById(a.container.id).appendChild(c);a.innerContainer=c;a.showSubtitle=function(){a.innerContainer.innerHTML=a.text||""}},start:function(a,c){c.innerContainer.style.display="inline";c.showSubtitle(c,c.text)},end:function(a,c){c.innerContainer.style.display="none";c.innerContainer.innerHTML=""},_teardown:function(a){a.container.removeChild(a.innerContainer)}})})(Popcorn);(function(g){var b=[],d=function(){this.name="";this.contains={};this.toString=function(){var a=[],c;for(c in this.contains)this.contains.hasOwnProperty(c)&&a.push(" "+this.contains[c]);return a.toString()}};g.plugin("tagthisperson",function(){return{_setup:function(a){var c=false;if(!document.getElementById(a.target)&&g.plugin.debug)throw Error("target container doesn't exist");for(var f=0;f<b.length;f++)if(b[f].name===a.target){a._p=b[f];c=true;break}if(!c){a._p=new d;a._p.name=a.target;b.push(a._p)}},
-start:function(a,c){c._p.contains[c.person]=c.image?"<img src='"+c.image+"'/> ":"";c._p.contains[c.person]+=c.href?"<a href='"+c.href+"' target='_blank'> "+c.person+"</a>":c.person;document.getElementById(c.target).innerHTML=c._p.toString()},end:function(a,c){delete c._p.contains[c.person];document.getElementById(c.target).innerHTML=c._p.toString()}}}(),{about:{name:"Popcorn tagthisperson Plugin",version:"0.1",author:"@annasob",website:"annasob.wordpress.com"},options:{start:{elem:"input",type:"text",
-label:"In"},end:{elem:"input",type:"text",label:"Out"},target:"tagthisperson-container",person:{elem:"input",type:"text",label:"Name"},image:{elem:"input",type:"url",label:"Image Src",optional:true},href:{elem:"input",type:"url",label:"URL",optional:true}}})})(Popcorn);(function(g){var b=false;g.plugin("twitter",{manifest:{about:{name:"Popcorn Twitter Plugin",version:"0.1",author:"Scott Downe",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"number",label:"In"},end:{elem:"input",type:"number",label:"Out"},src:{elem:"input",type:"text",label:"Source"},target:"twitter-container",height:{elem:"input",type:"number",label:"Height",optional:true},width:{elem:"input",type:"number",label:"Width",optional:true}}},_setup:function(d){if(!window.TWTR&&
-!b){b=true;g.getScript("//widgets.twimg.com/j/2/widget.js")}var a=document.getElementById(d.target);d.container=document.createElement("div");d.container.setAttribute("id",g.guid());d.container.style.display="none";if(!a&&g.plugin.debug)throw Error("target container doesn't exist");a&&a.appendChild(d.container);var c=d.src||"";a=d.width||250;var f=d.height||200,h=/^@/.test(c),p={version:2,id:d.container.getAttribute("id"),rpp:30,width:a,height:f,interval:6E3,theme:{shell:{background:"#ffffff",color:"#000000"},
-tweets:{background:"#ffffff",color:"#444444",links:"#1985b5"}},features:{loop:true,timestamp:true,avatars:true,hashtags:true,toptweets:true,live:true,scrollbar:false,behavior:"default"}},o=function(l){if(window.TWTR)if(h){p.type="profile";(new TWTR.Widget(p)).render().setUser(c).start()}else{p.type="search";p.search=c;p.subject=c;(new TWTR.Widget(p)).render().start()}else setTimeout(function(){o(l)},1)};o(this)},start:function(d,a){a.container.style.display="inline"},end:function(d,a){a.container.style.display=
-"none"},_teardown:function(d){document.getElementById(d.target)&&document.getElementById(d.target).removeChild(d.container)}})})(Popcorn);(function(g){g.plugin("webpage",{manifest:{about:{name:"Popcorn Webpage Plugin",version:"0.1",author:"@annasob",website:"annasob.wordpress.com"},options:{id:{elem:"input",type:"text",label:"Id",optional:true},start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},src:{elem:"input",type:"url",label:"Src"},target:"iframe-container"}},_setup:function(b){var d=document.getElementById(b.target);b.src=b.src.replace(/^(https?:)?(\/\/)?/,"//");b._iframe=document.createElement("iframe");
-b._iframe.setAttribute("width","100%");b._iframe.setAttribute("height","100%");b._iframe.id=b.id;b._iframe.src=b.src;b._iframe.style.display="none";if(!d&&g.plugin.debug)throw Error("target container doesn't exist");d&&d.appendChild(b._iframe)},start:function(b,d){d._iframe.src=d.src;d._iframe.style.display="inline"},end:function(b,d){d._iframe.style.display="none"},_teardown:function(b){document.getElementById(b.target)&&document.getElementById(b.target).removeChild(b._iframe)}})})(Popcorn);var wikiCallback;
-(function(g){g.plugin("wikipedia",{manifest:{about:{name:"Popcorn Wikipedia Plugin",version:"0.1",author:"@annasob",website:"annasob.wordpress.com"},options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},lang:{elem:"input",type:"text",label:"Language",optional:true},src:{elem:"input",type:"url",label:"Src"},title:{elem:"input",type:"text",label:"Title",optional:true},numberofwords:{elem:"input",type:"text",label:"Num Of Words",optional:true},target:"wikipedia-container"}},
-_setup:function(b){var d,a=g.guid();if(!b.lang)b.lang="en";b.numberofwords=b.numberofwords||200;window["wikiCallback"+a]=function(c){b._link=document.createElement("a");b._link.setAttribute("href",b.src);b._link.setAttribute("target","_blank");b._link.innerHTML=b.title||c.parse.displaytitle;b._desc=document.createElement("p");d=c.parse.text["*"].substr(c.parse.text["*"].indexOf("<p>"));d=d.replace(/((<(.|\n)+?>)|(\((.*?)\) )|(\[(.*?)\]))/g,"");d=d.split(" ");b._desc.innerHTML=d.slice(0,d.length>=
-b.numberofwords?b.numberofwords:d.length).join(" ")+" ...";b._fired=true};if(b.src)g.getScript("//"+b.lang+".wikipedia.org/w/api.php?action=parse&props=text&page="+b.src.slice(b.src.lastIndexOf("/")+1)+"&format=json&callback=wikiCallback"+a);else if(g.plugin.debug)throw Error("Wikipedia plugin needs a 'src'");},start:function(b,d){var a=function(){if(d._fired){if(d._link&&d._desc)if(document.getElementById(d.target)){document.getElementById(d.target).appendChild(d._link);document.getElementById(d.target).appendChild(d._desc);
-d._added=true}}else setTimeout(function(){a()},13)};a()},end:function(b,d){if(d._added){document.getElementById(d.target).removeChild(d._link);document.getElementById(d.target).removeChild(d._desc)}},_teardown:function(b){if(b._added){b._link.parentNode&&document.getElementById(b.target).removeChild(b._link);b._desc.parentNode&&document.getElementById(b.target).removeChild(b._desc);delete b.target}}})})(Popcorn);(function(g){var b={text:function(d){var a=d.post,c=document.createElement("a"),f=document.createTextNode(a.title),h=document.createElement("div");c.setAttribute("href",a.post_url);c.appendChild(f);h.appendChild(c);h.innerHTML+=a.body;d._container.appendChild(h)},photo:function(d){for(var a=d.width||250,c=-1,f=[d.post.photos.length],h=[d.post.photos.length],p=document.createElement("div"),o=document.createElement("img"),l=d.post,i=0,r=l.photos.length;i<r;i++){for(var k=l.photos[i],j=k.alt_sizes,v=
-0,w=j.length;v<w;v++){var n=j[v];if(n.width===a){h[i]=n.url;f[i]=k.caption;c=0;break}else if(n.width===250)c=v}c===-1&&g.error("Clearly your blog has a picture that is so tiny it isn't even 250px wide. Consider  using a bigger picture or try a smaller size.");if(v===j.length)h[i]=j[c].url}a=0;for(c=h.length;a<c;a++){p.innerHTML+=f[a]+"<br/>";o.setAttribute("src",h[a]);o.setAttribute("alt","Pic"+a);p.appendChild(o);p.innerHTML+="<br/>"}p.innerHTML+="<br/>"+l.caption;d._container.appendChild(p)},audio:function(d){var a=
-document.createElement("div"),c=document.createElement("a"),f=d.post;if(f.artist){var h=document.createElement("img");a.innerHTML+="Artist: "+f.artist+"<br/>";c.setAttribute("href",f.source_url);h.setAttribute("src",f.album_art);h.setAttribute("alt",f.album);c.appendChild(h);a.appendChild(c);a.innerHTML+="<hr/>"+f.track_number+" - "+f.track_name+"<br/>"}else{h=document.createTextNode(f.source_title);c.setAttribute("href",f.source_url);c.appendChild(h);a.appendChild(c);a.innerHTML+="<br/>"}a.innerHTML+=
-f.player+"   "+f.plays+"plays<br/>"+f.caption;d._container.appendChild(a)},video:function(d){for(var a=d.width||400,c=-1,f=d.post,h=document.createElement("div"),p,o=0,l=f.player.length;o<l;o++){var i=f.player[o];if(i.width===a){p=i.embed_code;c=0;break}else if(i.width===400)c=o}if(o===d.post.player.length)p=f.player[c].embed_code;c===-1&&g.error("Specified video size was not found and default was never found. Please try another width.");h.innerHTML+=p+"<br/>"+f.caption;d._container.appendChild(h)},
-chat:function(d){var a=d.post,c,f=document.createElement("div");f.innerHTML+="<strong><u>"+a.title+"</u></strong><br/><br/>";for(var h=0,p=a.dialogue.length;h<p;h++){c=a.dialogue[h];f.innerHTML+=c.label+" "+c.phrase+"<br/>"}d._container.appendChild(f)},quote:function(d){var a=document.createElement("div"),c=document.createElement("a"),f=d.post,h=document.createTextNode(f.text);c.setAttribute("href",f.post_url);c.appendChild(h);a.appendChild(c);a.innerHTML+="<br/><br/>Source: <b>"+f.source+"</b>";
-d._container.appendChild(a)},link:function(d){var a=document.createElement("div"),c=document.createElement("a"),f=d.post,h=document.createTextNode(f.title);c.setAttribute("href",f.post_url);c.appendChild(h);a.appendChild(c);a.innerHTML+="<br/>"+f.description;d._container.appendChild(a)},answer:function(d){var a=document.createElement("div"),c=document.createElement("a"),f=d.post,h=document.createTextNode(f.asking_name);a.innerHTML="Inquirer: ";c.setAttribute("href",f.asking_url);c.appendChild(h);
-a.appendChild(c);a.innerHTML+="<br/><br/>Question: "+f.question+"<br/>Answer: "+f.answer;d._container.appendChild(a)}};g.plugin("tumblr",{manifest:{about:{name:"Popcorn Tumblr Plugin",version:"0.1",author:"Matthew Schranz, @mjschranz",website:"mschranz.wordpress.com"},options:{requestType:{elem:"select",options:["INFO","AVATAR","BLOGPOST"],label:"Type_Of_Plugin"},target:"tumblr-container",start:{elem:"input",type:"number",label:"Start_Time"},end:{elem:"input",type:"number",label:"End_Time"},base_hostname:{elem:"input",
-type:"text",label:"User_Name"},api_key:{elem:"input",type:"text",label:"Application_Key",optional:true},size:{elem:"select",options:[16,24,30,40,48,64,96,128,512],label:"avatarSize",optional:true},blogId:{elem:"input",type:"number",label:"Blog_ID",optional:true},width:{elem:"input",type:"number",label:"Photo_Width",optional:true}}},_setup:function(d){var a=document.getElementById(d.target),c,f,h=this;d.requestType=d.requestType.toLowerCase();(!d.base_hostname||!d.api_key&&(d.requestType==="info"||
-d.requestType==="blogpost"))&&g.error("Must provide a blog URL to the plugin and an api_key for Blog Info and Blog Post requests.");!(["info","avatar","blogpost"].indexOf(d.requestType)>-1)&&g.error("Invalid tumblr plugin type.");d.requestType==="blogpost"&&d.blogId===undefined&&g.error("Error. BlogId required for blogpost requests");!a&&g.plugin.debug&&g.error("Target Tumblr container doesn't exist.");c=d.base_hostname.slice(d.base_hostname.indexOf("/")+2,d.base_hostname.length);f=d.base_hostname.slice(0,
-d.base_hostname.indexOf("/")+2);c=f==="http://"||f==="https://"?c:d.base_hostname;if(c.indexOf("/")>-1)c=c.slice(0,c.indexOf("/"));d.base_hostname=c;d._container=document.createElement("div");d._container.id="tumblrdiv-"+g.guid();if(d.requestType==="avatar")d._container.innerHTML="<img src=http://api.tumblr.com/v2/blog/"+d.base_hostname+"/avatar/"+d.size+" alt='BlogAvatar' />";else{c=d.requestType==="blogpost"?"posts":"info";c="http://api.tumblr.com/v2/blog/"+d.base_hostname+"/"+c+"?api_key="+d.api_key+
-"&id="+d.blogId+"&jsonp=tumblrCallBack";this.listen("tumblrError",function(p){g.error(p)});g.getJSONP(c,function(p){if(p.meta.msg==="OK"){var o=document.createElement("div");if(d.requestType==="blogpost"){d.post=p.response.posts[0];var l=d.post.type;p=d.post.tags;o.innerHTML="Date Published: "+d.post.date.slice(0,d.post.date.indexOf(" "))+"<br/>";if(p.length!==0){o.innerHTML+="Tags: "+p[0];for(var i=1,r=p.length;i<r;i++)o.innerHTML+=", "+p[i]}else o.innerHTML+="Tags: No Tags Used";d._container.appendChild(o);
-b[l](d)}else{l=document.createElement("a");p=p.response.blog;i=document.createTextNode(p.title);l.setAttribute("href",p.url);l.appendChild(i);o.appendChild(l);o.innerHTML+=p.description;d._container.appendChild(o)}}else h.trigger("tumblrError","Error. Request failed. Status code: "+p.meta.status+" - Message: "+p.meta.msg)},false)}d._container.style.display="none";a&&a.appendChild(d._container)},start:function(d,a){if(a._container)a._container.style.display=""},end:function(d,a){if(a._container)a._container.style.display=
-"none"},_teardown:function(d){document.getElementById(d.target)&&document.getElementById(d.target).removeChild(d._container)}})})(Popcorn,this);(function(g){g.plugin("linkedin",{manifest:{about:{name:"Popcorn LinkedIn Plugin",version:"0.1",author:"Dan Ventura",website:"dsventura.blogspot.com"},options:{type:{elem:"input",type:"text",label:"Type"},url:{elem:"input",type:"text",label:"URL"},apikey:{elem:"input",type:"text",label:"API Key"},counter:{elem:"input",type:"text",label:"Counter"},memberid:{elem:"input",type:"text",label:"Member ID",optional:true},format:{elem:"input",type:"text",label:"Format",optional:true},companyid:{elem:"input",
-type:"text",label:"Company ID",optional:true},modules:{elem:"input",type:"text",label:"Modules",optional:true},productid:{elem:"input",type:"text",label:"productid",optional:true},related:{elem:"input",type:"text",label:"related",optional:true},start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},target:"linkedin-container"}},_setup:function(b){var d=b.apikey,a=document.getElementById(b.target),c=document.createElement("script");g.getScript("//platform.linkedin.com/in.js");
-b._container=document.createElement("div");b._container.appendChild(c);if(d)c.innerHTML="api_key: "+d;b.type=b.type&&b.type.toLowerCase()||"";var f=function(h){return{share:function(){c.setAttribute("type","IN/Share");h.counter&&c.setAttribute("data-counter",h.counter);h.url&&c.setAttribute("data-url",h.url)},memberprofile:function(){c.setAttribute("type","IN/MemberProfile");c.setAttribute("data-id",h.memberid);c.setAttribute("data-format",h.format||"inline");h.text&&h.format.toLowerCase()!=="inline"&&
-c.setAttribute("data-text",h.text)},companyinsider:function(){c.setAttribute("type","IN/CompanyInsider");c.setAttribute("data-id",h.companyid);h.modules&&h._container.setAttribute("data-modules",h.modules)},companyprofile:function(){c.setAttribute("type","IN/CompanyProfile");c.setAttribute("data-id",h.companyid);c.setAttribute("data-format",h.format||"inline");h.text&&h.format.toLowerCase()!=="inline"&&c.setAttribute("data-text",h.text);h.related!==undefined&&c.setAttribute("data-related",h.related)},
-recommendproduct:function(){c.setAttribute("type","IN/RecommendProduct");c.setAttribute("data-company",h.companyid||"LinkedIn");c.setAttribute("data-product",h.productid||"201714");h.counter&&c.setAttribute("data-counter",h.counter)}}}(b);if(d)f[b.type]&&f[b.type]();else{b._container=document.createElement("p");b._container.innerHTML="Plugin requires a valid <a href='https://www.linkedin.com/secure/developer'>apikey</a>";if(!a&&g.plugin.debug)throw"target container doesn't exist";a&&a.appendChild(b._container)}if(!a&&
-g.plugin.debug)throw Error("target container doesn't exist");a&&a.appendChild(b._container);b._container.style.display="none"},start:function(b,d){d._container.style.display="block"},end:function(b,d){d._container.style.display="none"},_teardown:function(b){var d=document.getElementById(b.target);d&&d.removeChild(b._container)}})})(Popcorn);(function(g){g.plugin("mustache",function(b){var d,a,c,f;g.getScript("http://mustache.github.com/extras/mustache.js");var h=!!b.dynamic,p=typeof b.template,o=typeof b.data,l=document.getElementById(b.target);if(!l&&g.plugin.debug)throw Error("target container doesn't exist");b.container=l||document.createElement("div");if(p==="function")if(h)c=b.template;else f=b.template(b);else if(p==="string")f=b.template;else if(g.plugin.debug)throw Error("Mustache Plugin Error: options.template must be a String or a Function.");
-else f="";if(o==="function")if(h)d=b.data;else a=b.data(b);else if(o==="string")a=JSON.parse(b.data);else if(o==="object")a=b.data;else if(g.plugin.debug)throw Error("Mustache Plugin Error: options.data must be a String, Object, or Function.");else a="";return{start:function(i,r){var k=function(){if(window.Mustache){if(d)a=d(r);if(c)f=c(r);var j=Mustache.to_html(f,a).replace(/^\s*/mg,"");r.container.innerHTML=j}else setTimeout(function(){k()},10)};k()},end:function(i,r){r.container.innerHTML=""},
-_teardown:function(){d=a=c=f=null}}},{about:{name:"Popcorn Mustache Plugin",version:"0.1",author:"David Humphrey (@humphd)",website:"http://vocamus.net/dave"},options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},target:"mustache-container",template:{elem:"input",type:"text",label:"Template"},data:{elem:"input",type:"text",label:"Data"},dynamic:{elem:"input",type:"text",label:"Dynamic",optional:true}}})})(Popcorn);(function(g){function b(a,c){if(a.map)a.map.div.style.display=c;else setTimeout(function(){b(a,c)},10)}var d=1;g.plugin("openmap",function(a){var c,f,h,p,o,l,i,r,k=document.getElementById(a.target);c=document.createElement("div");c.id="openmapdiv"+d;c.style.width="100%";c.style.height="100%";d++;if(!k&&g.plugin.debug)throw Error("target container doesn't exist");k&&k.appendChild(c);r=function(){if(window.OpenLayers){if(a.location){location=new OpenLayers.LonLat(0,0);g.getJSONP("//tinygeocoder.com/create-api.php?q="+
-a.location+"&callback=jsonp",function(v){f=new OpenLayers.LonLat(v[1],v[0]);a.map.setCenter(f)})}else f=new OpenLayers.LonLat(a.lng,a.lat);a.type=a.type||"ROADMAP";if(a.type==="SATELLITE"){a.map=new OpenLayers.Map({div:c,maxResolution:0.28125,tileSize:new OpenLayers.Size(512,512)});var j=new OpenLayers.Layer.WorldWind("LANDSAT","//worldwind25.arc.nasa.gov/tile/tile.aspx",2.25,4,{T:"105"});a.map.addLayer(j);p=new OpenLayers.Projection("EPSG:4326");h=new OpenLayers.Projection("EPSG:4326")}else if(a.type===
-"TERRAIN"){p=new OpenLayers.Projection("EPSG:4326");h=new OpenLayers.Projection("EPSG:4326");a.map=new OpenLayers.Map({div:c,projection:h});j=new OpenLayers.Layer.WMS("USGS Terraserver","//terraserver-usa.org/ogcmap.ashx?",{layers:"DRG"});a.map.addLayer(j)}else{h=new OpenLayers.Projection("EPSG:900913");p=new OpenLayers.Projection("EPSG:4326");f=f.transform(p,h);a.map=new OpenLayers.Map({div:c,projection:h,displayProjection:p});j=new OpenLayers.Layer.OSM;a.map.addLayer(j)}if(a.map)a.map.div.style.display=
-"none"}else setTimeout(function(){r()},50)};r();return{_setup:function(j){window.OpenLayers||g.getScript("//openlayers.org/api/OpenLayers.js");var v=function(){if(j.map){j.zoom=j.zoom||2;if(j.zoom&&typeof j.zoom!=="number")j.zoom=+j.zoom;j.map.setCenter(f,j.zoom);if(j.markers){var w=OpenLayers.Util.extend({},OpenLayers.Feature.Vector.style["default"]),n=function(u){clickedFeature=u.feature;if(clickedFeature.attributes.text){i=new OpenLayers.Popup.FramedCloud("featurePopup",clickedFeature.geometry.getBounds().getCenterLonLat(),
-new OpenLayers.Size(120,250),clickedFeature.attributes.text,null,true,function(){l.unselect(this.feature)});clickedFeature.popup=i;i.feature=clickedFeature;j.map.addPopup(i)}},y=function(u){feature=u.feature;if(feature.popup){i.feature=null;j.map.removePopup(feature.popup);feature.popup.destroy();feature.popup=null}},C=function(u){g.getJSONP("//tinygeocoder.com/create-api.php?q="+u.location+"&callback=jsonp",function(x){x=(new OpenLayers.Geometry.Point(x[1],x[0])).transform(p,h);var A=OpenLayers.Util.extend({},
-w);if(!u.size||isNaN(u.size))u.size=14;A.pointRadius=u.size;A.graphicOpacity=1;A.externalGraphic=u.icon;x=new OpenLayers.Feature.Vector(x,null,A);if(u.text)x.attributes={text:u.text};o.addFeatures([x])})};o=new OpenLayers.Layer.Vector("Point Layer",{style:w});j.map.addLayer(o);for(var e=0,m=j.markers.length;e<m;e++){var q=j.markers[e];if(q.text)if(!l){l=new OpenLayers.Control.SelectFeature(o);j.map.addControl(l);l.activate();o.events.on({featureselected:n,featureunselected:y})}if(q.location)C(q);
-else{var s=(new OpenLayers.Geometry.Point(q.lng,q.lat)).transform(p,h),t=OpenLayers.Util.extend({},w);if(!q.size||isNaN(q.size))q.size=14;t.pointRadius=q.size;t.graphicOpacity=1;t.externalGraphic=q.icon;s=new OpenLayers.Feature.Vector(s,null,t);if(q.text)s.attributes={text:q.text};o.addFeatures([s])}}}}else setTimeout(function(){v()},13)};v()},start:function(j,v){b(v,"block")},end:function(j,v){b(v,"none")},_teardown:function(){k&&k.removeChild(c);c=map=f=h=p=o=l=i=null}}},{about:{name:"Popcorn OpenMap Plugin",
-version:"0.3",author:"@mapmeld",website:"mapadelsur.blogspot.com"},options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},target:"map-container",type:{elem:"select",options:["ROADMAP","SATELLITE","TERRAIN"],label:"Type",optional:true},zoom:{elem:"input",type:"text",label:"Zoom",optional:true},lat:{elem:"input",type:"text",label:"Lat",optional:true},lng:{elem:"input",type:"text",label:"Lng",optional:true},location:{elem:"input",type:"text",label:"Location"},
-markers:{elem:"input",type:"text",label:"List Markers",optional:true}}})})(Popcorn);document.addEventListener("click",function(g){g=g.target;if(g.nodeName==="A"||g.parentNode&&g.parentNode.nodeName==="A")Popcorn.instances.forEach(function(b){b.options.pauseOnLinkClicked&&b.pause()})},false);(function(g){var b={},d=0,a=document.createElement("span"),c=["webkit","Moz","ms","O",""],f=["Transform","TransitionDuration","TransitionTimingFunction"],h={},p;document.getElementsByTagName("head")[0].appendChild(a);for(var o=0,l=f.length;o<l;o++)for(var i=0,r=c.length;i<r;i++){p=c[i]+f[o];if(p in a.style){h[f[o].toLowerCase()]=p;break}}document.getElementsByTagName("head")[0].appendChild(a);g.plugin("wordriver",{manifest:{about:{name:"Popcorn WordRiver Plugin"},options:{start:{elem:"input",type:"text",
-label:"In"},end:{elem:"input",type:"text",label:"Out"},target:"wordriver-container",text:{elem:"input",type:"text",label:"Text"},color:{elem:"input",type:"text",label:"Color",optional:true}}},_setup:function(k){if(!document.getElementById(k.target)&&g.plugin.debug)throw Error("target container doesn't exist");k._duration=k.end-k.start;var j;if(!(j=b[k.target])){j=k.target;b[j]=document.createElement("div");var v=document.getElementById(j);v&&v.appendChild(b[j]);b[j].style.height="100%";b[j].style.position=
-"relative";j=b[j]}k._container=j;k.word=document.createElement("span");k.word.style.position="absolute";k.word.style.whiteSpace="nowrap";k.word.style.opacity=0;k.word.style.MozTransitionProperty="opacity, -moz-transform";k.word.style.webkitTransitionProperty="opacity, -webkit-transform";k.word.style.OTransitionProperty="opacity, -o-transform";k.word.style.transitionProperty="opacity, transform";k.word.style[h.transitionduration]="1s, "+k._duration+"s";k.word.style[h.transitiontimingfunction]="linear";
-k.word.innerHTML=k.text;k.word.style.color=k.color||"black"},start:function(k,j){j._container.appendChild(j.word);j.word.style[h.transform]="";j.word.style.fontSize=~~(30+20*Math.random())+"px";d%=j._container.offsetWidth-j.word.offsetWidth;j.word.style.left=d+"px";d+=j.word.offsetWidth+10;j.word.style[h.transform]="translateY("+(j._container.offsetHeight-j.word.offsetHeight)+"px)";j.word.style.opacity=1;setTimeout(function(){j.word.style.opacity=0},(j.end-j.start-1||1)*1E3)},end:function(k,j){j.word.style.opacity=
-0},_teardown:function(k){var j=document.getElementById(k.target);k.word.parentNode&&k._container.removeChild(k.word);b[k.target]&&!b[k.target].childElementCount&&j&&j.removeChild(b[k.target])&&delete b[k.target]}})})(Popcorn);(function(g){g.plugin("processing",function(b){var d=function(a){function c(f){var h=function(){a.listen("pause",function(){f.canvas.style.display==="inline"&&f.pjsInstance.noLoop()});a.listen("play",function(){f.canvas.style.display==="inline"&&f.pjsInstance.loop()})};if(f.sketch)g.xhr({url:f.sketch,dataType:"text",success:function(p){f.codeReady=false;p=Processing.compile(p);f.pjsInstance=new Processing(f.canvas,p);f.seeking=false;f._running&&!a.media.paused&&f.pjsInstance.loop()||f.pjsInstance.noLoop();
-a.listen("seeking",function(){f._running&&f.canvas.style.display==="inline"&&f.noPause&&f.pjsInstance.loop()});f.noPause=f.noPause||false;!f.noPause&&h();f.codeReady=true}});else if(g.plugin.debug)throw Error("Popcorn.Processing: options.sketch is undefined");}window.Processing?c(b):g.getScript("//cloud.github.com/downloads/processing-js/processing-js/processing-1.3.6.min.js",function(){c(b)})};return{_setup:function(a){a.codeReady=false;a.parentTarget=document.getElementById(a.target);if(!a.parentTarget&&
-g.plugin.debug)throw Error("target container doesn't exist");var c=document.createElement("canvas");c.id=g.guid(a.target+"-sketch");c.style.display="none";a.canvas=c;a.parentTarget&&a.parentTarget.appendChild(a.canvas);d(this)},start:function(a,c){c.codeReady&&!this.media.paused&&c.pjsInstance.loop();c.canvas.style.display="inline"},end:function(a,c){c.pjsInstance&&c.pjsInstance.noLoop();c.canvas.style.display="none"},_teardown:function(a){a.pjsInstance&&a.pjsInstance.exit();a.parentTarget&&a.parentTarget.removeChild(a.canvas)}}},
-{about:{name:"Popcorn Processing Plugin",version:"0.1",author:"Christopher De Cairos, Benjamin Chalovich",website:"cadecairos.blogspot.com, ben1amin.wordpress.org"},options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},target:{elem:"input",type:"text",label:"Target"},sketch:{elem:"input",type:"url",label:"Sketch"},noPause:{elem:"select",options:["TRUE","FALSE"],label:"No Loop",optional:true}}})})(Popcorn);(function(g){var b=1;g.plugin("timeline",function(d){var a=document.getElementById(d.target),c=document.createElement("div"),f,h=true;if(a&&!a.firstChild){a.appendChild(f=document.createElement("div"));f.style.width="380px";f.style.height="600px";f.style.overflow="auto"}else f=a.firstChild;c.style.display="none";c.id="timelineDiv"+b;d.direction=d.direction||"up";if(d.direction.toLowerCase()==="down")h=false;if(a&&f)h?f.insertBefore(c,f.firstChild):f.appendChild(c);else if(g.plugin.debug)throw Error("target container doesn't exist");
-b++;c.innerHTML="<p><span id='big' style='font-size:24px; line-height: 130%;' >"+d.title+"</span><br /><span id='mid' style='font-size: 16px;'>"+d.text+"</span><br />"+d.innerHTML;return{start:function(p,o){c.style.display="block";if(o.direction==="down")f.scrollTop=f.scrollHeight},end:function(){c.style.display="none"},_teardown:function(){f&&c&&f.removeChild(c)&&!f.firstChild&&a.removeChild(f)}}},{about:{name:"Popcorn Timeline Plugin",version:"0.1",author:"David Seifried @dcseifried",website:"dseifried.wordpress.com"},
-options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},target:"feed-container",title:{elem:"input",type:"text",label:"title"},text:{elem:"input",type:"text",label:"text"},innerHTML:{elem:"input",type:"text",label:"innerHTML",optional:true},direction:{elem:"input",type:"text",label:"direction",optional:true}}})})(Popcorn);(function(g,b){var d={};g.plugin("documentcloud",{manifest:{about:{name:"Popcorn Document Cloud Plugin",version:"0.1",author:"@humphd, @ChrisDeCairos",website:"http://vocamus.net/dave"},options:{start:{elem:"input",type:"text",label:"In"},end:{elem:"input",type:"text",label:"Out"},target:"documentcloud-container",width:{elem:"input",type:"text",label:"Width",optional:true},height:{elem:"input",type:"text",label:"Height",optional:true},src:{elem:"input",type:"text",label:"PDF URL"},preload:{elem:"input",
-type:"boolean",label:"Preload",optional:true},page:{elem:"input",type:"number",label:"Page Number",optional:true},aid:{elem:"input",type:"number",label:"Annotation Id",optional:true}}},_setup:function(a){function c(){function i(u){a._key=u.api.getId();a._changeView=function(x){a.aid?x.pageSet.showAnnotation(x.api.getAnnotation(a.aid)):x.api.setCurrentPage(a.page)}}function r(){d[a._key]={num:1,id:a._containerId};h.loaded=true}h.loaded=false;var k=a.url.replace(/\.html$/,".js"),j=a.target,v=b.getElementById(j),
-w=b.createElement("div"),n=g.position(v),y=a.width||n.width;n=a.height||n.height;var C=a.sidebar||true,e=a.text||true,m=a.pdf||true,q=a.showAnnotations||true,s=a.zoom||700,t=a.search||true;if(!function(u){var x=false;g.forEach(h.viewers,function(A){if(A.api.getSchema().canonicalURL===u){i(A);A=d[a._key];a._containerId=A.id;A.num+=1;x=true;h.loaded=true}});return x}(a.url)){w.id=a._containerId=g.guid(j);j="#"+w.id;v.appendChild(w);p.trigger("documentready");h.load(k,{width:y,height:n,sidebar:C,text:e,
-pdf:m,showAnnotations:q,zoom:s,search:t,container:j,afterLoad:a.page||a.aid?function(u){i(u);a._changeView(u);w.style.visibility="hidden";u.elements.pages.hide();r()}:function(u){i(u);r();w.style.visibility="hidden";u.elements.pages.hide()}})}}function f(){window.DV.loaded?c():setTimeout(f,25)}var h=window.DV=window.DV||{},p=this;if(h.loading)f();else{h.loading=true;h.recordHit="//www.documentcloud.org/pixel.gif";var o=b.createElement("link"),l=b.getElementsByTagName("head")[0];o.rel="stylesheet";
-o.type="text/css";o.media="screen";o.href="//s3.documentcloud.org/viewer/viewer-datauri.css";l.appendChild(o);h.loaded=false;g.getScript("http://s3.documentcloud.org/viewer/viewer.js",function(){h.loading=false;c()})}},start:function(a,c){var f=b.getElementById(c._containerId),h=DV.viewers[c._key];(c.page||c.aid)&&h&&c._changeView(h);if(f&&h){f.style.visibility="visible";h.elements.pages.show()}},end:function(a,c){var f=b.getElementById(c._containerId);if(f&&DV.viewers[c._key]){f.style.visibility=
-"hidden";DV.viewers[c._key].elements.pages.hide()}},_teardown:function(a){var c=b.getElementById(a._containerId);if((a=a._key)&&DV.viewers[a]&&--d[a].num===0){for(DV.viewers[a].api.unload();c.hasChildNodes();)c.removeChild(c.lastChild);c.parentNode.removeChild(c)}}})})(Popcorn,window.document);(function(g){g.parser("parseJSON","JSON",function(b){var d={title:"",remote:"",data:[]};g.forEach(b.data,function(a){d.data.push(a)});return d})})(Popcorn);(function(g){g.parser("parseSBV",function(b){var d={title:"",remote:"",data:[]},a=[],c=0,f=0,h=function(k){k=k.split(":");var j=k.length-1,v;try{v=parseInt(k[j-1],10)*60+parseFloat(k[j],10);if(j===2)v+=parseInt(k[0],10)*3600}catch(w){throw"Bad cue";}return v},p=function(k,j){var v={};v[k]=j;return v};b=b.text.split(/(?:\r\n|\r|\n)/gm);for(f=b.length;c<f;){var o={},l=[],i=b[c++].split(",");try{o.start=h(i[0]);for(o.end=h(i[1]);c<f&&b[c];)l.push(b[c++]);o.text=l.join("<br />");a.push(p("subtitle",o))}catch(r){for(;c<
-f&&b[c];)c++}for(;c<f&&!b[c];)c++}d.data=a;return d})})(Popcorn);(function(g){g.parser("parseSRT",function(b){var d={title:"",remote:"",data:[]},a=[],c=0,f=0,h=0,p,o,l,i=function(k){k=k.split(":");try{var j=k[2].split(",");if(j.length===1)j=k[2].split(".");return parseFloat(k[0],10)*3600+parseFloat(k[1],10)*60+parseFloat(j[0],10)+parseFloat(j[1],10)/1E3}catch(v){return 0}},r=function(k,j){var v={};v[k]=j;return v};b=b.text.split(/(?:\r\n|\r|\n)/gm);f=b.length;for(c=0;c<f;c++){l={};o=[];l.id=parseInt(b[c++],10);p=b[c++].split(/[\t ]*--\>[\t ]*/);l.start=i(p[0]);
-h=p[1].indexOf(" ");if(h!==-1)p[1]=p[1].substr(0,h);for(l.end=i(p[1]);c<f&&b[c];)o.push(b[c++]);l.text=o.join("\\N").replace(/\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}/gi,"");l.text=l.text.replace(/</g,"&lt;").replace(/>/g,"&gt;");l.text=l.text.replace(/&lt;(\/?(font|b|u|i|s))((\s+(\w|\w[\w\-]*\w)(\s*=\s*(?:\".*?\"|'.*?'|[^'\">\s]+))?)+\s*|\s*)(\/?)&gt;/gi,"<$1$3$7>");l.text=l.text.replace(/\\N/gi,"<br />");a.push(r("subtitle",l))}d.data=a;return d})})(Popcorn);(function(g){function b(c,f){var h=c.substr(10).split(","),p;p={start:d(h[f.start]),end:d(h[f.end])};if(p.start===-1||p.end===-1)throw"Invalid time";var o=k.call(i,/\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}/gi,""),l=o.replace,i;i=h.length;k=[];for(var r=f.text;r<i;r++)k.push(h[r]);i=k.join(",");var k=i.replace;p.text=l.call(o,/\\N/gi,"<br />");return p}function d(c){var f=c.split(":");if(c.length!==10||f.length<3)return-1;return parseInt(f[0],10)*3600+parseInt(f[1],10)*60+parseFloat(f[2],10)}function a(c,
-f){var h={};h[c]=f;return h}g.parser("parseSSA",function(c){var f={title:"",remote:"",data:[]},h=[],p=0,o;c=c.text.split(/(?:\r\n|\r|\n)/gm);for(o=c.length;p<o&&c[p]!=="[Events]";)p++;var l=c[++p].substr(8).split(", "),i={},r,k;k=0;for(r=l.length;k<r;k++)if(l[k]==="Start")i.start=k;else if(l[k]==="End")i.end=k;else if(l[k]==="Text")i.text=k;for(;++p<o&&c[p]&&c[p][0]!=="[";)try{h.push(a("subtitle",b(c[p],i)))}catch(j){}f.data=h;return f})})(Popcorn);(function(g){g.parser("parseTTML",function(b){var d={title:"",remote:"",data:[]},a,c=0,f,h=function(l,i){if(!l)return-1;var r=l.split(":"),k=r.length-1;if(k>=2)return parseInt(r[0],10)*3600+parseInt(r[k-1],10)*60+parseFloat(r[k],10);for(r=l.length-1;r>=0;r--)if(l[r]<="9"&&l[r]>="0")break;r++;k=l.substr(r);i=i||0;if(k==="h")k=3600;else if(k==="m")k=60;else if(k==="s")k=1;else if(k==="ms")k=0.0010;else return-1;return parseFloat(l.substr(0,r))*k+i},p=function(l,i){var r={};r[l]=i;return r},o=function(l,
-i){for(var r=l.firstChild,k;r;){if(r.nodeType===1)if(r.nodeName==="p"){k=r;var j=i,v={};v.text=k.textContent.replace(/^[\s]+|[\s]+$/gm,"").replace(/(?:\r\n|\r|\n)/gm,"<br />");v.id=k.getAttribute("xml:id")||k.getAttribute("id");v.start=h(k.getAttribute("begin"),j);v.end=h(k.getAttribute("end"),j);v.target=f;if(v.end<0){v.end=h(k.getAttribute("duration"),0);if(v.end>=0)v.end+=v.start;else v.end=Number.MAX_VALUE}k=v;d.data.push(p("subtitle",k));c++}else if(r.nodeName==="div"){k=h(r.getAttribute("begin"));
-if(k<0)k=i;o(r,k)}r=r.nextSibling}};if(!b.xml||!b.xml.documentElement||!(a=b.xml.documentElement.firstChild))return d;for(;a.nodeName!=="body";)a=a.nextSibling;f="";o(a,0);return d})})(Popcorn);(function(g){g.parser("parseTTXT",function(b){var d={title:"",remote:"",data:[]},a=function(o){o=o.split(":");var l=0;try{return parseFloat(o[0],10)*60*60+parseFloat(o[1],10)*60+parseFloat(o[2],10)}catch(i){l=0}return l},c=function(o,l){var i={};i[o]=l;return i};b=b.xml.lastChild.lastChild;for(var f=Number.MAX_VALUE,h=[];b;){if(b.nodeType===1&&b.nodeName==="TextSample"){var p={};p.start=a(b.getAttribute("sampleTime"));p.text=b.getAttribute("text");if(p.text){p.end=f-0.0010;h.push(c("subtitle",p))}f=
-p.start}b=b.previousSibling}d.data=h.reverse();return d})})(Popcorn);(function(g){function b(a){var c=a.split(":");a=a.length;var f;if(a!==12&&a!==9)throw"Bad cue";a=c.length-1;try{f=parseInt(c[a-1],10)*60+parseFloat(c[a],10);if(a===2)f+=parseInt(c[0],10)*3600}catch(h){throw"Bad cue";}return f}function d(a,c){var f={};f[a]=c;return f}g.parser("parseVTT",function(a){var c={title:"",remote:"",data:[]},f=[],h=0,p=0,o,l;a=a.text.split(/(?:\r\n|\r|\n)/gm);p=a.length;if(p===0||a[0]!=="WEBVTT")return c;for(h++;h<p;){o=[];try{for(var i=h;i<p&&!a[i];)i++;h=i;var r=a[h++];i=
-void 0;var k={};if(!r||r.indexOf("--\>")===-1)throw"Bad cue";i=r.replace(/--\>/," --\> ").split(/[\t ]+/);if(i.length<2)throw"Bad cue";k.id=r;k.start=b(i[0]);k.end=b(i[2]);for(l=k;h<p&&a[h];)o.push(a[h++]);l.text=o.join("<br />");f.push(d("subtitle",l))}catch(j){for(h=h;h<p&&a[h];)h++;h=h}}c.data=f;return c})})(Popcorn);(function(g){g.parser("parseXML","XML",function(b){var d={title:"",remote:"",data:[]},a={},c=function(i){i=i.split(":");if(i.length===1)return parseFloat(i[0],10);else if(i.length===2)return parseFloat(i[0],10)+parseFloat(i[1]/12,10);else if(i.length===3)return parseInt(i[0]*60,10)+parseFloat(i[1],10)+parseFloat(i[2]/12,10);else if(i.length===4)return parseInt(i[0]*3600,10)+parseInt(i[1]*60,10)+parseFloat(i[2],10)+parseFloat(i[3]/12,10)},f=function(i){for(var r={},k=0,j=i.length;k<j;k++){var v=i.item(k).nodeName,
-w=i.item(k).nodeValue;if(v==="in")r.start=c(w);else if(v==="out")r.end=c(w);else if(v==="resourceid")g.extend(r,a[w]);else r[v]=w}return r},h=function(i,r){var k={};k[i]=r;return k},p=function(i,r,k){var j={};g.extend(j,r,f(i.attributes),{text:i.textContent});r=i.childNodes;if(r.length<1||r.length===1&&r[0].nodeType===3)if(k)a[j.id]=j;else d.data.push(h(i.nodeName,j));else for(i=0;i<r.length;i++)r[i].nodeType===1&&p(r[i],j,k)};b=b.documentElement.childNodes;for(var o=0,l=b.length;o<l;o++)if(b[o].nodeType===
-1)b[o].nodeName==="manifest"?p(b[o],{},true):p(b[o],{},false);return d})})(Popcorn);(function(g,b){function d(l,i){if(l.currentStyle)return l.currentStyle[i];else if(b.getComputedStyle)return document.defaultView.getComputedStyle(l,null).getPropertyValue(i)}function a(l){return'<div><a href="'+l.user.profile+'"><img width="16px height="16px" src="'+l.user.avatar+'"></img>'+l.user.name+"</a> at "+function(i){var r=h(i/60);i=p(i%60);return r+"."+(i<10?"0":"")+i}(l.start)+" "+function(i){function r(k,j){return k+" "+j+(k>1?"s":"")+" ago"}i=((new Date).getTime()-i.getTime())/1E3;if(i<
-60)return r(p(i),"second");i/=60;if(i<60)return r(p(i),"minute");i/=60;if(i<24)return r(p(i),"hour");i/=24;if(i<30)return r(p(i),"day");if(i<365)return r(p(i/30),"month");return r(p(i/365),"year")}(l.date)+"<br />"+l.text+"</span>"}function c(l){if(b.swfobject&&b.soundcloud){var i={enable_api:true,object_id:l._playerId,url:l.src,show_comments:!l._options.api.key&&!l._options.api.commentdiv},r={id:l._playerId,name:l._playerId},k=document.createElement("div");k.setAttribute("id",l._playerId);l._container.appendChild(k);
-swfobject.embedSWF("http://player.soundcloud.com/player.swf",l._playerId,l.offsetWidth,l.height,"9.0.0","expressInstall.swf",i,{allowscriptaccess:"always",wmode:"transparent"},r)}else setTimeout(function(){c(l)},15)}var f=Math.abs,h=Math.floor,p=Math.round,o={};g.soundcloud=function(l,i,r){g.getScript("http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js");g.getScript("http://popcornjs.org/code/players/soundcloud/lib/soundcloud.player.api.js",function(){var k=1;soundcloud.addEventListener("onPlayerReady",
-function(j,v){var w=o[j.api_getFlashId()];w.swfObj=j;w.duration=j.api_getTrackDuration();w.currentTime=j.api_getTrackPosition();w.volume=w.previousVolume=j.api_getVolume()/100;w._mediaId=v.mediaId;w.dispatchEvent("load");w.dispatchEvent("canplay");w.dispatchEvent("durationchange");w.timeupdate()});soundcloud.addEventListener("onMediaStart",function(j){j=o[j.api_getFlashId()];j.played=1;j.dispatchEvent("playing")});soundcloud.addEventListener("onMediaPlay",function(j){if(k)k=0;else o[j.api_getFlashId()].dispatchEvent("play")});
-soundcloud.addEventListener("onMediaPause",function(j){o[j.api_getFlashId()].dispatchEvent("pause")});soundcloud.addEventListener("onMediaBuffering",function(j){j=o[j.api_getFlashId()];j.dispatchEvent("progress");if(j.readyState===0){j.readyState=3;j.dispatchEvent("readystatechange")}});soundcloud.addEventListener("onMediaDoneBuffering",function(j){o[j.api_getFlashId()].dispatchEvent("canplaythrough")});soundcloud.addEventListener("onMediaEnd",function(j){j=o[j.api_getFlashId()];j.paused=1;j.dispatchEvent("ended")});
-soundcloud.addEventListener("onMediaSeek",function(j){var v=o[j.api_getFlashId()];v.setCurrentTime(j.api_getTrackPosition());v.paused&&v.dispatchEvent("timeupdate")});soundcloud.addEventListener("onPlayerError",function(j){o[j.api_getFlashId()].dispatchEvent("error")})});return new g.soundcloud.init(l,i,r)};g.soundcloud.init=function(){function l(i){var r=i._options,k=i._container,j=k.getBoundingClientRect();i.width=r.width||d(k,"width")||"100%";i.height=r.height||d(k,"height")||"81px";i.src=r.src;
-i.autoplay=r.autoplay;if(parseFloat(i.height,10)!==81)i.height="81px";i.offsetLeft=j.left;i.offsetTop=j.top;i.offsetHeight=parseFloat(i.height,10);i.offsetWidth=parseFloat(i.width,10);if(/[\d]+%/.test(i.width)){r=d(k,"width");i._container.style.width=i.width;i.offsetWidth=i._container.offsetWidth;i._container.style.width=r}if(/[\d]+%/.test(i.height)){r=d(k,"height");i._container.style.height=i.height;i.offsetHeight=i._container.offsetHeight;i._container.style.height=r}}return function(i,r,k){if(i)if(r){if(/file/.test(location.protocol))throw"Must run from a web server!";
-}else throw"Must supply a source!";else throw"Must supply an id!";if(!(this._container=document.getElementById(i)))throw"Could not find that container in the DOM!";k=k||{};k.api=k.api||{};k.target=i;k.src=r;k.api.commentformat=k.api.commentformat||a;this._mediaId=0;this._listeners={};this._playerId=g.guid(k.target);this._containerId=k.target;this._options=k;this._comments=[];this._popcorn=null;l(this);this.duration=0;this.volume=1;this.ended=this.currentTime=0;this.paused=1;this.readyState=0;this.playbackRate=
-1;this.left=this.top=0;this.autoplay=null;this.played=0;this.addEventListener("load",function(){var j=this.getBoundingClientRect();this.top=j.top;this.left=j.left;this.offsetWidth=this.swfObj.offsetWidth;this.offsetHeight=this.swfObj.offsetHeight;this.offsetLeft=this.swfObj.offsetLeft;this.offsetTop=this.swfObj.offsetTop});o[this._playerId]=this;c(this)}}();g.soundcloud.init.prototype=g.soundcloud.prototype;g.extend(g.soundcloud.prototype,{setVolume:function(l){if(!(!l&&l!==0)){if(l<0)l=-l;if(l>1)l%=
-1;this.volume=this.previousVolume=l;this.swfObj.api_setVolume(l*100);this.dispatchEvent("volumechange")}},setCurrentTime:function(l){if(!(!l&&l!==0)){this.currentTime=this.previousCurrentTime=l;this.ended=l>=this.duration;this.dispatchEvent("seeked")}},play:function(){if(this.swfObj){if(this.paused){this.paused=0;this.swfObj.api_play()}}else this.addEventListener("load",this.play)},pause:function(){if(this.swfObj){if(!this.paused){this.paused=1;this.swfObj.api_pause()}}else this.addEventListener("load",
-this.pause)},mute:function(){if(this.swfObj)if(this.muted())if(this.paused)this.setVolume(this.oldVol);else this.volume=this.oldVol;else{this.oldVol=this.volume;if(this.paused)this.setVolume(0);else this.volume=0}else this.addEventListener("load",this.mute)},muted:function(){return this.volume===0},load:function(){if(this.swfObj){this.play();this.pause()}else this.addEventListener("load",this.load)},addEventListener:function(l,i){this._listeners[l]||(this._listeners[l]=[]);this._listeners[l].push(i);
-return i},dispatchEvent:function(l){var i=this;l=l.type||l;l==="play"&&this.paused||l==="pause"&&!this.paused?this[l]():g.forEach(this._listeners[l],function(r){r.call(i)})},timeupdate:function(){var l=this,i=this.swfObj.api_getVolume()/100;if(f(this.currentTime-this.previousCurrentTime)>0.25)this.swfObj.api_seekTo(this.currentTime);else this.previousCurrentTime=this.currentTime=this.swfObj.api_getTrackPosition();if(i!==this.previousVolume)this.setVolume(i);else this.volume!==this.previousVolume&&
-this.setVolume(this.volume);this.paused||this.dispatchEvent("timeupdate");l.ended||setTimeout(function(){l.timeupdate.call(l)},33)},getBoundingClientRect:function(){var l;if(this.swfObj){l=this.swfObj.getBoundingClientRect();return{bottom:l.bottom,left:l.left,right:l.right,top:l.top,width:l.width||l.right-l.left,height:l.height||l.bottom-l.top}}else{tmp=this._container.getBoundingClientRect();return{left:tmp.left,top:tmp.top,width:this.offsetWidth,height:this.offsetHeight,bottom:tmp.top+this.width,
-right:tmp.top+this.height}}},registerPopcornWithPlayer:function(l){if(this.swfObj){this._popcorn=l;var i=this._options.api;if(i.key&&i.commentdiv){var r=this;g.xhr({url:"http://api.soundcloud.com/tracks/"+r._mediaId+"/comments.js?consumer_key="+i.key,success:function(k){g.forEach(k.json,function(j){r.addComment({start:j.timestamp/1E3,date:new Date(j.created_at),text:j.body,user:{name:j.user.username,profile:j.user.permalink_url,avatar:j.user.avatar_url}})})}})}}else this.addEventListener("load",function(){this.registerPopcornWithPlayer(l)})}});
-g.extend(g.soundcloud.prototype,{addComment:function(l,i){var r=this,k={start:l.start||0,date:l.date||new Date,text:l.text||"",user:{name:l.user.name||"",profile:l.user.profile||"",avatar:l.user.avatar||""},display:function(){return(i||r._options.api.commentformat)(k)}};this._comments.push(k);this._popcorn&&this._popcorn.subtitle({start:k.start,target:this._options.api.commentdiv,display:"inline",language:"en",text:k.display()})}})})(Popcorn,window);(function(){vimeo_player_loaded=function(g){vimeo_player_loaded[g]&&vimeo_player_loaded[g]()};vimeo_player_loaded.seek={};vimeo_player_loaded.loadProgress={};vimeo_player_loaded.play={};vimeo_player_loaded.pause={};Popcorn.player("vimeo",{_canPlayType:function(g,b){return/(?:http:\/\/www\.|http:\/\/|www\.|\.|^)(vimeo)/.test(b)&&g.toLowerCase()!=="video"},_setup:function(g){var b=this,d,a=document.createElement("div"),c=0,f=false,h=0,p,o;a.id=b.id+Popcorn.guid();b.appendChild(a);o=b.style.width?""+
-b.offsetWidth:"560";p=b.style.height?""+b.offsetHeight:"315";var l=function(){var i;i=b.src;var r=0,k=false;vimeo_player_loaded[a.id]=function(){d=document.getElementById(a.id);vimeo_player_loaded.seek[a.id]=function(w){if(w!==c){c=w;b.dispatchEvent("seeked");b.dispatchEvent("timeupdate")}};vimeo_player_loaded.play[a.id]=function(){if(b.paused){b.paused=false;b.dispatchEvent("play");b.dispatchEvent("playing");j()}};vimeo_player_loaded.pause[a.id]=function(){if(!b.paused){b.paused=true;b.dispatchEvent("pause")}};
-vimeo_player_loaded.loadProgress[a.id]=function(w){if(!k){k=true;b.dispatchEvent("loadstart")}w.percent===100&&b.dispatchEvent("canplaythrough")};d.api_addEventListener("seek","vimeo_player_loaded.seek."+a.id);d.api_addEventListener("loadProgress","vimeo_player_loaded.loadProgress."+a.id);d.api_addEventListener("play","vimeo_player_loaded.play."+a.id);d.api_addEventListener("pause","vimeo_player_loaded.pause."+a.id);var j=function(){if(!b.paused){c=d.api_getCurrentTime();b.dispatchEvent("timeupdate");
-setTimeout(j,10)}},v=function(){var w=d.api_getVolume()===0,n=d.api_getVolume();if(f!==w){f=w;b.dispatchEvent("volumechange")}if(h!==n){h=n;b.dispatchEvent("volumechange")}setTimeout(v,250)};b.play=function(){b.paused=false;b.dispatchEvent("play");b.dispatchEvent("playing");j();d.api_play()};b.pause=function(){if(!b.paused){b.paused=true;b.dispatchEvent("pause");d.api_pause()}};Popcorn.player.defineProperty(b,"currentTime",{set:function(w){if(!w)return c;c=+w;b.dispatchEvent("seeked");b.dispatchEvent("timeupdate");
-d.api_seekTo(c);return c},get:function(){return c}});Popcorn.player.defineProperty(b,"muted",{set:function(w){if(d.api_getVolume()===0!==w)if(w){r=d.api_getVolume();d.api_setVolume(0)}else d.api_setVolume(r)},get:function(){return d.api_getVolume()===0}});Popcorn.player.defineProperty(b,"volume",{set:function(w){if(!w||typeof w!=="number"||w<0||w>1)return d.api_getVolume()/100;if(d.api_getVolume()!==w){d.api_setVolume(w*100);h=d.api_getVolume();b.dispatchEvent("volumechange")}return d.api_getVolume()/
-100},get:function(){return d.api_getVolume()/100}});b.dispatchEvent("loadedmetadata");b.dispatchEvent("loadeddata");b.duration=d.api_getDuration();b.dispatchEvent("durationchange");v();b.readyState=4;b.dispatchEvent("canplaythrough")};i=/\d+$/.exec(i);i={clip_id:i?i[0]:0,api:1,js_swf_id:a.id};Popcorn.extend(i,g);swfobject.embedSWF("//vimeo.com/moogaloop.swf",a.id,o,p,"9.0.0","expressInstall.swf",i,{allowscriptaccess:"always",allowfullscreen:"true",wmode:"transparent"},{})};window.swfobject?l():Popcorn.getScript("//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js",
-l)}})})();var onYouTubePlayerReady=function(g){onYouTubePlayerReady[g]&&onYouTubePlayerReady[g]()};onYouTubePlayerReady.stateChangeEventHandler={};onYouTubePlayerReady.onErrorEventHandler={};
-Popcorn.player("youtube",{_canPlayType:function(g,b){return/(?:http:\/\/www\.|http:\/\/|www\.|\.|^)(youtu)/.test(b)&&g.toLowerCase()!=="video"},_setup:function(g){var b=this,d=false,a=document.createElement("div"),c=0,f=0,h=true,p=false,o=false,l=100;b.paused=undefined;a.id=b.id+Popcorn.guid();g._container=a;b.appendChild(a);var i=function(){var r,k,j,v,w;onYouTubePlayerReady[a.id]=function(){g.youtubeObject=document.getElementById(a.id);onYouTubePlayerReady.stateChangeEventHandler[a.id]=function(C){if(!g.destroyed)if(C===
-2)if(p&&f===c&&f!==g.youtubeObject.getCurrentTime()){p=false;g.youtubeObject.seekTo(c)}else{c=g.youtubeObject.getCurrentTime();b.dispatchEvent("timeupdate");!b.paused&&b.pause()}else if(C===1&&!h)b.paused&&b.play();else if(C===-1)g.youtubeObject.playVideo();else if(C===1&&h){h=false;if(b.paused===true)b.pause();else if(b.paused===false)b.play();else if(d)b.play();else d||b.pause();b.duration=g.youtubeObject.getDuration();b.dispatchEvent("durationchange");y();b.dispatchEvent("loadedmetadata");b.dispatchEvent("loadeddata");
-b.readyState=4;b.dispatchEvent("canplaythrough")}else C===0&&b.dispatchEvent("ended")};onYouTubePlayerReady.onErrorEventHandler[a.id]=function(C){[2,100,101,150].indexOf(C)!==-1&&b.dispatchEvent("error")};g.youtubeObject.addEventListener("onStateChange","onYouTubePlayerReady.stateChangeEventHandler."+a.id);g.youtubeObject.addEventListener("onError","onYouTubePlayerReady.onErrorEventHandler."+a.id);var n=function(){if(!g.destroyed)if(!b.paused){c=g.youtubeObject.getCurrentTime();b.dispatchEvent("timeupdate");
-setTimeout(n,10)}},y=function(){if(!g.destroyed){if(o!==g.youtubeObject.isMuted()){o=g.youtubeObject.isMuted();b.dispatchEvent("volumechange")}if(l!==g.youtubeObject.getVolume()){l=g.youtubeObject.getVolume();b.dispatchEvent("volumechange")}setTimeout(y,250)}};b.play=function(){if(!g.destroyed){if(b.paused!==false||g.youtubeObject.getPlayerState()!==1){b.paused=false;b.dispatchEvent("play");b.dispatchEvent("playing")}n();g.youtubeObject.playVideo()}};b.pause=function(){if(!g.destroyed)if(b.paused!==
-true||g.youtubeObject.getPlayerState()!==2){b.paused=true;b.dispatchEvent("pause");g.youtubeObject.pauseVideo()}};Popcorn.player.defineProperty(b,"currentTime",{set:function(C){c=f=+C;p=true;if(g.destroyed)return c;b.dispatchEvent("seeked");b.dispatchEvent("timeupdate");g.youtubeObject.seekTo(c);return c},get:function(){return c}});Popcorn.player.defineProperty(b,"muted",{set:function(C){if(g.destroyed)return C;if(g.youtubeObject.isMuted()!==C){C?g.youtubeObject.mute():g.youtubeObject.unMute();o=
-g.youtubeObject.isMuted();b.dispatchEvent("volumechange")}return g.youtubeObject.isMuted()},get:function(){if(g.destroyed)return 0;return g.youtubeObject.isMuted()}});Popcorn.player.defineProperty(b,"volume",{set:function(C){if(g.destroyed)return C;if(g.youtubeObject.getVolume()/100!==C){g.youtubeObject.setVolume(C*100);l=g.youtubeObject.getVolume();b.dispatchEvent("volumechange")}return g.youtubeObject.getVolume()/100},get:function(){if(g.destroyed)return 0;return g.youtubeObject.getVolume()/100}})};
-g.controls=+g.controls===0||+g.controls===1?g.controls:1;g.annotations=+g.annotations===1||+g.annotations===3?g.annotations:1;r={playerapiid:a.id};k=/^.*(?:\/|v=)(.{11})/.exec(b.src)[1];w=(b.src.split("?")[1]||"").replace(/v=.{11}/,"");d=/autoplay=1/.test(w);j=b.style.width?""+b.offsetWidth:"560";v=b.style.height?""+b.offsetHeight:"315";k={id:a.id,"data-youtube-player":"//www.youtube.com/e/"+k+"?"+w+"&enablejsapi=1&playerapiid="+a.id+"&version=3"};swfobject.embedSWF(k["data-youtube-player"],a.id,
-j,v,"8",undefined,r,{wmode:"transparent",allowScriptAccess:"always"},k)};window.swfobject?i():Popcorn.getScript("//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js",i)},_teardown:function(g){g.destroyed=true;g.youtubeObject.stopVideo();g.youtubeObject.clearVideo();this.removeChild(document.getElementById(g._container.id))}});
+(function(r,f){function n(a,g){return function(){if(d.plugin.debug)return a.apply(this,arguments);try{return a.apply(this,arguments)}catch(l){d.plugin.errors.push({plugin:g,thrown:l,source:a.toString()});this.emit("pluginerror",d.plugin.errors)}}}if(f.addEventListener){var c=Array.prototype,b=Object.prototype,e=c.forEach,h=c.slice,i=b.hasOwnProperty,j=b.toString,p=r.Popcorn,m=[],o=false,q={events:{hash:{},apis:{}}},s=function(){return r.requestAnimationFrame||r.webkitRequestAnimationFrame||r.mozRequestAnimationFrame||
+r.oRequestAnimationFrame||r.msRequestAnimationFrame||function(a){r.setTimeout(a,16)}}(),d=function(a,g){return new d.p.init(a,g||null)};d.version="1.3";d.isSupported=true;d.instances=[];d.p=d.prototype={init:function(a,g){var l,k=this;if(typeof a==="function")if(f.readyState==="complete")a(f,d);else{m.push(a);if(!o){o=true;var t=function(){f.removeEventListener("DOMContentLoaded",t,false);for(var z=0,C=m.length;z<C;z++)m[z].call(f,d);m=null};f.addEventListener("DOMContentLoaded",t,false)}}else{if(typeof a===
+"string")try{l=f.querySelector(a)}catch(u){throw Error("Popcorn.js Error: Invalid media element selector: "+a);}this.media=l||a;l=this.media.nodeName&&this.media.nodeName.toLowerCase()||"video";this[l]=this.media;this.options=g||{};this.id=this.options.id||d.guid(l);if(d.byId(this.id))throw Error("Popcorn.js Error: Cannot use duplicate ID ("+this.id+")");this.isDestroyed=false;this.data={running:{cue:[]},timeUpdate:d.nop,disabled:{},events:{},hooks:{},history:[],state:{volume:this.media.volume},trackRefs:{},
+trackEvents:{byStart:[{start:-1,end:-1}],byEnd:[{start:-1,end:-1}],animating:[],startIndex:0,endIndex:0,previousUpdateTime:-1}};d.instances.push(this);var v=function(){if(k.media.currentTime<0)k.media.currentTime=0;k.media.removeEventListener("loadeddata",v,false);var z,C,E,B,w;z=k.media.duration;z=z!=z?Number.MAX_VALUE:z+1;d.addTrackEvent(k,{start:z,end:z});if(k.options.frameAnimation){k.data.timeUpdate=function(){d.timeUpdate(k,{});d.forEach(d.manifest,function(D,F){if(C=k.data.running[F]){B=C.length;
+for(var I=0;I<B;I++){E=C[I];(w=E._natives)&&w.frame&&w.frame.call(k,{},E,k.currentTime())}}});k.emit("timeupdate");!k.isDestroyed&&s(k.data.timeUpdate)};!k.isDestroyed&&s(k.data.timeUpdate)}else{k.data.timeUpdate=function(D){d.timeUpdate(k,D)};k.isDestroyed||k.media.addEventListener("timeupdate",k.data.timeUpdate,false)}};Object.defineProperty(this,"error",{get:function(){return k.media.error}});k.media.readyState>=2?v():k.media.addEventListener("loadeddata",v,false);return this}}};d.p.init.prototype=
+d.p;d.byId=function(a){for(var g=d.instances,l=g.length,k=0;k<l;k++)if(g[k].id===a)return g[k];return null};d.forEach=function(a,g,l){if(!a||!g)return{};l=l||this;var k,t;if(e&&a.forEach===e)return a.forEach(g,l);if(j.call(a)==="[object NodeList]"){k=0;for(t=a.length;k<t;k++)g.call(l,a[k],k,a);return a}for(k in a)i.call(a,k)&&g.call(l,a[k],k,a);return a};d.extend=function(a){var g=h.call(arguments,1);d.forEach(g,function(l){for(var k in l)a[k]=l[k]});return a};d.extend(d,{noConflict:function(a){if(a)r.Popcorn=
+p;return d},error:function(a){throw Error(a);},guid:function(a){d.guid.counter++;return(a?a:"")+(+new Date+d.guid.counter)},sizeOf:function(a){var g=0,l;for(l in a)g++;return g},isArray:Array.isArray||function(a){return j.call(a)==="[object Array]"},nop:function(){},position:function(a){a=a.getBoundingClientRect();var g={},l=f.documentElement,k=f.body,t,u,v;t=l.clientTop||k.clientTop||0;u=l.clientLeft||k.clientLeft||0;v=r.pageYOffset&&l.scrollTop||k.scrollTop;l=r.pageXOffset&&l.scrollLeft||k.scrollLeft;
+t=Math.ceil(a.top+v-t);u=Math.ceil(a.left+l-u);for(var z in a)g[z]=Math.round(a[z]);return d.extend({},g,{top:t,left:u})},disable:function(a,g){if(!a.data.disabled[g]){a.data.disabled[g]=true;for(var l=a.data.running[g].length-1,k;l>=0;l--){k=a.data.running[g][l];k._natives.end.call(a,null,k)}}return a},enable:function(a,g){if(a.data.disabled[g]){a.data.disabled[g]=false;for(var l=a.data.running[g].length-1,k;l>=0;l--){k=a.data.running[g][l];k._natives.start.call(a,null,k)}}return a},destroy:function(a){var g=
+a.data.events,l=a.data.trackEvents,k,t,u,v;for(t in g){k=g[t];for(u in k)delete k[u];g[t]=null}for(v in d.registryByName)d.removePlugin(a,v);l.byStart.length=0;l.byEnd.length=0;if(!a.isDestroyed){a.data.timeUpdate&&a.media.removeEventListener("timeupdate",a.data.timeUpdate,false);a.isDestroyed=true}}});d.guid.counter=1;d.extend(d.p,function(){var a={};d.forEach("load play pause currentTime playbackRate volume duration preload playbackRate autoplay loop controls muted buffered readyState seeking paused played seekable ended".split(/\s+/g),
+function(g){a[g]=function(l){var k;if(typeof this.media[g]==="function"){if(l!=null&&/play|pause/.test(g))this.media.currentTime=d.util.toSeconds(l);this.media[g]();return this}if(l!=null){k=this.media[g];this.media[g]=l;k!==l&&this.emit("attrchange",{attribute:g,previousValue:k,currentValue:l});return this}return this.media[g]}});return a}());d.forEach("enable disable".split(" "),function(a){d.p[a]=function(g){return d[a](this,g)}});d.extend(d.p,{roundTime:function(){return Math.round(this.media.currentTime)},
+exec:function(a,g,l){var k=arguments.length,t,u;try{u=d.util.toSeconds(a)}catch(v){}if(typeof u==="number")a=u;if(typeof a==="number"&&k===2){l=g;g=a;a=d.guid("cue")}else if(k===1)g=-1;else if(t=this.getTrackEvent(a)){if(typeof a==="string"&&k===2){if(typeof g==="number")l=t._natives.start;if(typeof g==="function"){l=g;g=t.start}}}else if(k>=2){if(typeof g==="string"){try{u=d.util.toSeconds(g)}catch(z){}g=u}if(typeof g==="number")l=d.nop();if(typeof g==="function"){l=g;g=-1}}d.addTrackEvent(this,
+{id:a,start:g,end:g+1,_running:false,_natives:{start:l||d.nop,end:d.nop,type:"cue"}});return this},mute:function(a){a=a==null||a===true?"muted":"unmuted";if(a==="unmuted"){this.media.muted=false;this.media.volume=this.data.state.volume}if(a==="muted"){this.data.state.volume=this.media.volume;this.media.muted=true}this.emit(a);return this},unmute:function(a){return this.mute(a==null?false:!a)},position:function(){return d.position(this.media)},toggle:function(a){return d[this.data.disabled[a]?"enable":
+"disable"](this,a)},defaults:function(a,g){if(d.isArray(a)){d.forEach(a,function(l){for(var k in l)this.defaults(k,l[k])},this);return this}if(!this.options.defaults)this.options.defaults={};this.options.defaults[a]||(this.options.defaults[a]={});d.extend(this.options.defaults[a],g);return this}});d.Events={UIEvents:"blur focus focusin focusout load resize scroll unload",MouseEvents:"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave click dblclick",Events:"loadstart progress suspend emptied stalled play pause error loadedmetadata loadeddata waiting playing canplay canplaythrough seeking seeked timeupdate ended ratechange durationchange volumechange"};
+d.Events.Natives=d.Events.UIEvents+" "+d.Events.MouseEvents+" "+d.Events.Events;q.events.apiTypes=["UIEvents","MouseEvents","Events"];(function(a,g){for(var l=q.events.apiTypes,k=a.Natives.split(/\s+/g),t=0,u=k.length;t<u;t++)g.hash[k[t]]=true;l.forEach(function(v){g.apis[v]={};for(var z=a[v].split(/\s+/g),C=z.length,E=0;E<C;E++)g.apis[v][z[E]]=true})})(d.Events,q.events);d.events={isNative:function(a){return!!q.events.hash[a]},getInterface:function(a){if(!d.events.isNative(a))return false;var g=
+q.events,l=g.apiTypes;g=g.apis;for(var k=0,t=l.length,u,v;k<t;k++){v=l[k];if(g[v][a]){u=v;break}}return u},all:d.Events.Natives.split(/\s+/g),fn:{trigger:function(a,g){var l;if(this.data.events[a]&&d.sizeOf(this.data.events[a])){if(l=d.events.getInterface(a)){l=f.createEvent(l);l.initEvent(a,true,true,r,1);this.media.dispatchEvent(l);return this}d.forEach(this.data.events[a],function(k){k.call(this,g)},this)}return this},listen:function(a,g){var l=this,k=true,t=d.events.hooks[a],u;if(!this.data.events[a]){this.data.events[a]=
+{};k=false}if(t){t.add&&t.add.call(this,{},g);if(t.bind)a=t.bind;if(t.handler){u=g;g=function(v){t.handler.call(l,v,u)}}k=true;if(!this.data.events[a]){this.data.events[a]={};k=false}}this.data.events[a][g.name||g.toString()+d.guid()]=g;!k&&d.events.all.indexOf(a)>-1&&this.media.addEventListener(a,function(v){d.forEach(l.data.events[a],function(z){typeof z==="function"&&z.call(l,v)})},false);return this},unlisten:function(a,g){if(this.data.events[a]&&this.data.events[a][g]){delete this.data.events[a][g];
+return this}this.data.events[a]=null;return this}},hooks:{canplayall:{bind:"canplaythrough",add:function(a,g){var l=false;if(this.media.readyState){g.call(this,a);l=true}this.data.hooks.canplayall={fired:l}},handler:function(a,g){if(!this.data.hooks.canplayall.fired){g.call(this,a);this.data.hooks.canplayall.fired=true}}}}};d.forEach([["trigger","emit"],["listen","on"],["unlisten","off"]],function(a){d.p[a[0]]=d.p[a[1]]=d.events.fn[a[0]]});d.addTrackEvent=function(a,g){var l,k;if(g.id)l=a.getTrackEvent(g.id);
+if(l){k=true;g=d.extend({},l,g);a.removeTrackEvent(g.id)}if(g&&g._natives&&g._natives.type&&a.options.defaults&&a.options.defaults[g._natives.type])g=d.extend({},a.options.defaults[g._natives.type],g);if(g._natives){g._id=g.id||g._id||d.guid(g._natives.type);a.data.history.push(g._id)}g.start=d.util.toSeconds(g.start,a.options.framerate);g.end=d.util.toSeconds(g.end,a.options.framerate);var t=a.data.trackEvents.byStart,u=a.data.trackEvents.byEnd,v;for(v=t.length-1;v>=0;v--)if(g.start>=t[v].start){t.splice(v+
+1,0,g);break}for(t=u.length-1;t>=0;t--)if(g.end>u[t].end){u.splice(t+1,0,g);break}if(g.end>a.media.currentTime&&g.start<=a.media.currentTime){g._running=true;a.data.running[g._natives.type].push(g);a.data.disabled[g._natives.type]||g._natives.start.call(a,null,g)}v<=a.data.trackEvents.startIndex&&g.start<=a.data.trackEvents.previousUpdateTime&&a.data.trackEvents.startIndex++;t<=a.data.trackEvents.endIndex&&g.end<a.data.trackEvents.previousUpdateTime&&a.data.trackEvents.endIndex++;this.timeUpdate(a,
+null,true);g._id&&d.addTrackEvent.ref(a,g);if(k){k=g._natives.type==="cue"?"cuechange":"trackchange";a.emit(k,{id:g.id,previousValue:{time:l.start,fn:l._natives.start},currentValue:{time:g.start,fn:g._natives.start}})}};d.addTrackEvent.ref=function(a,g){a.data.trackRefs[g._id]=g;return a};d.removeTrackEvent=function(a,g){for(var l,k,t=a.data.history.length,u=a.data.trackEvents.byStart.length,v=0,z=0,C=[],E=[],B=[],w=[];--u>-1;){l=a.data.trackEvents.byStart[v];k=a.data.trackEvents.byEnd[v];if(!l._id){C.push(l);
+E.push(k)}if(l._id){l._id!==g&&C.push(l);k._id!==g&&E.push(k);if(l._id===g){z=v;l._natives._teardown&&l._natives._teardown.call(a,l)}}v++}u=a.data.trackEvents.animating.length;v=0;if(u)for(;--u>-1;){l=a.data.trackEvents.animating[v];l._id||B.push(l);l._id&&l._id!==g&&B.push(l);v++}z<=a.data.trackEvents.startIndex&&a.data.trackEvents.startIndex--;z<=a.data.trackEvents.endIndex&&a.data.trackEvents.endIndex--;a.data.trackEvents.byStart=C;a.data.trackEvents.byEnd=E;a.data.trackEvents.animating=B;for(u=
+0;u<t;u++)a.data.history[u]!==g&&w.push(a.data.history[u]);a.data.history=w;d.removeTrackEvent.ref(a,g)};d.removeTrackEvent.ref=function(a,g){delete a.data.trackRefs[g];return a};d.getTrackEvents=function(a){var g=[];a=a.data.trackEvents.byStart;for(var l=a.length,k=0,t;k<l;k++){t=a[k];t._id&&g.push(t)}return g};d.getTrackEvents.ref=function(a){return a.data.trackRefs};d.getTrackEvent=function(a,g){return a.data.trackRefs[g]};d.getTrackEvent.ref=function(a,g){return a.data.trackRefs[g]};d.getLastTrackEventId=
+function(a){return a.data.history[a.data.history.length-1]};d.timeUpdate=function(a,g){var l=a.media.currentTime,k=a.data.trackEvents.previousUpdateTime,t=a.data.trackEvents,u=t.endIndex,v=t.startIndex,z=t.byStart.length,C=t.byEnd.length,E=d.registryByName,B,w,D;if(k<=l){for(;t.byEnd[u]&&t.byEnd[u].end<=l;){B=t.byEnd[u];w=(k=B._natives)&&k.type;if(!k||E[w]||a[w]){if(B._running===true){B._running=false;D=a.data.running[w];D.splice(D.indexOf(B),1);if(!a.data.disabled[w]){k.end.call(a,g,B);a.emit("trackend",
+d.extend({},B,{plugin:w,type:"trackend"}))}}u++}else{d.removeTrackEvent(a,B._id);return}}for(;t.byStart[v]&&t.byStart[v].start<=l;){B=t.byStart[v];w=(k=B._natives)&&k.type;if(!k||E[w]||a[w]){if(B.end>l&&B._running===false){B._running=true;a.data.running[w].push(B);if(!a.data.disabled[w]){k.start.call(a,g,B);a.emit("trackstart",d.extend({},B,{plugin:w,type:"trackstart"}))}}v++}else{d.removeTrackEvent(a,B._id);return}}}else if(k>l){for(;t.byStart[v]&&t.byStart[v].start>l;){B=t.byStart[v];w=(k=B._natives)&&
+k.type;if(!k||E[w]||a[w]){if(B._running===true){B._running=false;D=a.data.running[w];D.splice(D.indexOf(B),1);if(!a.data.disabled[w]){k.end.call(a,g,B);a.emit("trackend",d.extend({},B,{plugin:w,type:"trackend"}))}}v--}else{d.removeTrackEvent(a,B._id);return}}for(;t.byEnd[u]&&t.byEnd[u].end>l;){B=t.byEnd[u];w=(k=B._natives)&&k.type;if(!k||E[w]||a[w]){if(B.start<=l&&B._running===false){B._running=true;a.data.running[w].push(B);if(!a.data.disabled[w]){k.start.call(a,g,B);a.emit("trackstart",d.extend({},
+B,{plugin:w,type:"trackstart"}))}}u--}else{d.removeTrackEvent(a,B._id);return}}}t.endIndex=u;t.startIndex=v;t.previousUpdateTime=l;t.byStart.length<z&&t.startIndex--;t.byEnd.length<C&&t.endIndex--};d.extend(d.p,{getTrackEvents:function(){return d.getTrackEvents.call(null,this)},getTrackEvent:function(a){return d.getTrackEvent.call(null,this,a)},getLastTrackEventId:function(){return d.getLastTrackEventId.call(null,this)},removeTrackEvent:function(a){d.removeTrackEvent.call(null,this,a);return this},
+removePlugin:function(a){d.removePlugin.call(null,this,a);return this},timeUpdate:function(a){d.timeUpdate.call(null,this,a);return this},destroy:function(){d.destroy.call(null,this);return this}});d.manifest={};d.registry=[];d.registryByName={};d.plugin=function(a,g,l){if(d.protect.natives.indexOf(a.toLowerCase())>=0)d.error("'"+a+"' is a protected function name");else{var k=["start","end"],t={},u=typeof g==="function",v=["_setup","_teardown","start","end","frame"],z=function(B,w){B=B||d.nop;w=w||
+d.nop;return function(){B.apply(this,arguments);w.apply(this,arguments)}};d.manifest[a]=l=l||g.manifest||{};v.forEach(function(B){g[B]=n(g[B]||d.nop,a)});var C=function(B,w){if(!w)return this;if(w.ranges&&d.isArray(w.ranges)){d.forEach(w.ranges,function(G){G=d.extend({},w,G);delete G.ranges;this[a](G)},this);return this}var D=w._natives={},F="",I;d.extend(D,B);w._natives.type=a;w._running=false;D.start=D.start||D["in"];D.end=D.end||D.out;if(w.once)D.end=z(D.end,function(){this.removeTrackEvent(w._id)});
+D._teardown=z(function(){var G=h.call(arguments),H=this.data.running[D.type];G.unshift(null);G[1]._running&&H.splice(H.indexOf(w),1)&&D.end.apply(this,G)},D._teardown);w.compose=w.compose&&w.compose.split(" ")||[];w.effect=w.effect&&w.effect.split(" ")||[];w.compose=w.compose.concat(w.effect);w.compose.forEach(function(G){F=d.compositions[G]||{};v.forEach(function(H){D[H]=z(D[H],F[H])})});w._natives.manifest=l;if(!("start"in w))w.start=w["in"]||0;if(!w.end&&w.end!==0)w.end=w.out||Number.MAX_VALUE;
+if(!i.call(w,"toString"))w.toString=function(){var G=["start: "+w.start,"end: "+w.end,"id: "+(w.id||w._id)];w.target!=null&&G.push("target: "+w.target);return a+" ( "+G.join(", ")+" )"};if(!w.target){I="options"in l&&l.options;w.target=I&&"target"in I&&I.target}if(w._natives)w._id=d.guid(w._natives.type);w._natives._setup&&w._natives._setup.call(this,w);d.addTrackEvent(this,w);d.forEach(B,function(G,H){H!=="type"&&k.indexOf(H)===-1&&this.on(H,G)},this);return this};d.p[a]=t[a]=function(B,w){var D;
+if(B&&!w)w=B;else if(D=this.getTrackEvent(B)){w=d.extend({},D,w);d.addTrackEvent(this,w);return this}else w.id=B;this.data.running[a]=this.data.running[a]||[];D=d.extend({},this.options.defaults&&this.options.defaults[a]||{},w);return C.call(this,u?g.call(this,D):g,D)};l&&d.extend(g,{manifest:l});var E={fn:t[a],definition:g,base:g,parents:[],name:a};d.registry.push(d.extend(t,E,{type:a}));d.registryByName[a]=E;return t}};d.plugin.errors=[];d.plugin.debug=d.version==="1.3";d.removePlugin=function(a,
+g){if(!g){g=a;a=d.p;if(d.protect.natives.indexOf(g.toLowerCase())>=0){d.error("'"+g+"' is a protected function name");return}var l=d.registry.length,k;for(k=0;k<l;k++)if(d.registry[k].name===g){d.registry.splice(k,1);delete d.registryByName[g];delete d.manifest[g];delete a[g];return}}l=a.data.trackEvents.byStart;k=a.data.trackEvents.byEnd;var t=a.data.trackEvents.animating,u,v;u=0;for(v=l.length;u<v;u++){if(l[u]&&l[u]._natives&&l[u]._natives.type===g){l[u]._natives._teardown&&l[u]._natives._teardown.call(a,
+l[u]);l.splice(u,1);u--;v--;if(a.data.trackEvents.startIndex<=u){a.data.trackEvents.startIndex--;a.data.trackEvents.endIndex--}}k[u]&&k[u]._natives&&k[u]._natives.type===g&&k.splice(u,1)}u=0;for(v=t.length;u<v;u++)if(t[u]&&t[u]._natives&&t[u]._natives.type===g){t.splice(u,1);u--;v--}};d.compositions={};d.compose=function(a,g,l){d.manifest[a]=l||g.manifest||{};d.compositions[a]=g};d.plugin.effect=d.effect=d.compose;var A=/^(?:\.|#|\[)/;d.dom={debug:false,find:function(a,g){var l=null;a=a.trim();g=
+g||f;if(a){if(!A.test(a)){l=f.getElementById(a);if(l!==null)return l}try{l=g.querySelector(a)}catch(k){if(d.dom.debug)throw Error(k);}}return l}};var y=/\?/,x={url:"",data:"",dataType:"",success:d.nop,type:"GET",async:true,xhr:function(){return new r.XMLHttpRequest}};d.xhr=function(a){a.dataType=a.dataType&&a.dataType.toLowerCase()||null;if(a.dataType&&(a.dataType==="jsonp"||a.dataType==="script"))d.xhr.getJSONP(a.url,a.success,a.dataType==="script");else{a=d.extend({},x,a);a.ajax=a.xhr();if(a.ajax){if(a.type===
+"GET"&&a.data){a.url+=(y.test(a.url)?"&":"?")+a.data;a.data=null}a.ajax.open(a.type,a.url,a.async);a.ajax.send(a.data||null);return d.xhr.httpData(a)}}};d.xhr.httpData=function(a){var g,l=null,k,t=null;a.ajax.onreadystatechange=function(){if(a.ajax.readyState===4){try{l=JSON.parse(a.ajax.responseText)}catch(u){}g={xml:a.ajax.responseXML,text:a.ajax.responseText,json:l};if(!g.xml||!g.xml.documentElement){g.xml=null;try{k=new DOMParser;t=k.parseFromString(a.ajax.responseText,"text/xml");if(!t.getElementsByTagName("parsererror").length)g.xml=
+t}catch(v){}}if(a.dataType)g=g[a.dataType];a.success.call(a.ajax,g)}};return g};d.xhr.getJSONP=function(a,g,l){var k=f.head||f.getElementsByTagName("head")[0]||f.documentElement,t=f.createElement("script"),u=false,v=[];v=/(=)\?(?=&|$)|\?\?/;var z,C;if(!l){C=a.match(/(callback=[^&]*)/);if(C!==null&&C.length){v=C[1].split("=")[1];if(v==="?")v="jsonp";z=d.guid(v);a=a.replace(/(callback=[^&]*)/,"callback="+z)}else{z=d.guid("jsonp");if(v.test(a))a=a.replace(v,"$1"+z);v=a.split(/\?(.+)?/);a=v[0]+"?";if(v[1])a+=
+v[1]+"&";a+="callback="+z}window[z]=function(E){g&&g(E);u=true}}t.addEventListener("load",function(){l&&g&&g();u&&delete window[z];k.removeChild(t)},false);t.src=a;k.insertBefore(t,k.firstChild)};d.getJSONP=d.xhr.getJSONP;d.getScript=d.xhr.getScript=function(a,g){return d.xhr.getJSONP(a,g,true)};d.util={toSeconds:function(a,g){var l=/^([0-9]+:){0,2}[0-9]+([.;][0-9]+)?$/,k,t,u;if(typeof a==="number")return a;typeof a==="string"&&!l.test(a)&&d.error("Invalid time format");l=a.split(":");k=l.length-
+1;t=l[k];if(t.indexOf(";")>-1){t=t.split(";");u=0;if(g&&typeof g==="number")u=parseFloat(t[1],10)/g;l[k]=parseInt(t[0],10)+u}k=l[0];return{1:parseFloat(k,10),2:parseInt(k,10)*60+parseFloat(l[1],10),3:parseInt(k,10)*3600+parseInt(l[1],10)*60+parseFloat(l[2],10)}[l.length||1]}};d.p.cue=d.p.exec;d.protect={natives:function(a){return Object.keys?Object.keys(a):function(g){var l,k=[];for(l in g)i.call(g,l)&&k.push(l);return k}(a)}(d.p).map(function(a){return a.toLowerCase()})};d.forEach({listen:"on",unlisten:"off",
+trigger:"emit",exec:"cue"},function(a,g){var l=d.p[g];d.p[g]=function(){if(typeof console!=="undefined"&&console.warn){console.warn("Deprecated method '"+g+"', "+(a==null?"do not use.":"use '"+a+"' instead."));d.p[g]=l}return d.p[a].apply(this,[].slice.call(arguments))}});r.Popcorn=d}else{r.Popcorn={isSupported:false};for(c="byId forEach extend effects error guid sizeOf isArray nop position disable enable destroyaddTrackEvent removeTrackEvent getTrackEvents getTrackEvent getLastTrackEventId timeUpdate plugin removePlugin compose effect xhr getJSONP getScript".split(/\s+/);c.length;)r.Popcorn[c.shift()]=
+function(){}}})(window,window.document);(function(r,f){var n=r.document,c=r.location,b=/:\/\//,e=c.href.replace(c.href.split("/").slice(-1)[0],""),h=function(j,p,m){j=j||0;p=(p||j||0)+1;m=m||1;p=Math.ceil((p-j)/m)||0;var o=0,q=[];for(q.length=p;o<p;){q[o++]=j;j+=m}return q};f.sequence=function(j,p){return new f.sequence.init(j,p)};f.sequence.init=function(j,p){this.parent=n.getElementById(j);this.seqId=f.guid("__sequenced");this.queue=[];this.playlist=[];this.inOuts={ofVideos:[],ofClips:[]};this.dims={width:0,height:0};this.active=0;this.playing=
+this.cycling=false;this.times={last:0};this.events={};var m=this,o=0;f.forEach(p,function(q,s){var d=n.createElement("video");d.preload="auto";d.controls=true;d.style.display=s&&"none"||"";d.id=m.seqId+"-"+s;m.queue.push(d);var A=q["in"],y=q.out;m.inOuts.ofVideos.push({"in":A!==undefined&&A||1,out:y!==undefined&&y||0});m.inOuts.ofVideos[s].out=m.inOuts.ofVideos[s].out||m.inOuts.ofVideos[s]["in"]+2;d.src=!b.test(q.src)?e+q.src:q.src;d.setAttribute("data-sequence-owner",j);d.setAttribute("data-sequence-guid",
+m.seqId);d.setAttribute("data-sequence-id",s);d.setAttribute("data-sequence-clip",[m.inOuts.ofVideos[s]["in"],m.inOuts.ofVideos[s].out].join(":"));m.parent.appendChild(d);m.playlist.push(f("#"+d.id))});m.inOuts.ofVideos.forEach(function(q){q={"in":o,out:o+(q.out-q["in"])};m.inOuts.ofClips.push(q);o=q.out+1});f.forEach(this.queue,function(q,s){function d(){if(!s){m.dims.width=q.videoWidth;m.dims.height=q.videoHeight}q.currentTime=m.inOuts.ofVideos[s]["in"]-0.5;q.removeEventListener("canplaythrough",
+d,false);return true}q.addEventListener("canplaythrough",d,false);q.addEventListener("play",function(){m.playing=true},false);q.addEventListener("pause",function(){m.playing=false},false);q.addEventListener("timeupdate",function(A){A=A.srcElement||A.target;A=+(A.dataset&&A.dataset.sequenceId||A.getAttribute("data-sequence-id"));var y=Math.floor(q.currentTime);if(m.times.last!==y&&A===m.active){m.times.last=y;y===m.inOuts.ofVideos[A].out&&f.sequence.cycle.call(m,A)}},false)});return this};f.sequence.init.prototype=
+f.sequence.prototype;f.sequence.cycle=function(j){this.queue||f.error("Popcorn.sequence.cycle is not a public method");var p=this.queue,m=this.inOuts.ofVideos,o=p[j],q=0,s;if(p[j+1])q=j+1;if(p[j+1]){p=p[q];m=m[q];f.extend(p,{width:this.dims.width,height:this.dims.height});s=this.playlist[q];o.pause();this.active=q;this.times.last=m["in"]-1;s.currentTime(m["in"]);s[q?"play":"pause"]();this.trigger("cycle",{position:{previous:j,current:q}});if(q){o.style.display="none";p.style.display=""}this.cycling=
+false}else this.playlist[j].pause();return this};var i=["timeupdate","play","pause"];f.extend(f.sequence.prototype,{eq:function(j){return this.playlist[j]},remove:function(){this.parent.innerHTML=null},clip:function(j){return this.inOuts.ofVideos[j]},duration:function(){for(var j=0,p=this.inOuts.ofClips,m=0;m<p.length;m++)j+=p[m].out-p[m]["in"]+1;return j-1},play:function(){this.playlist[this.active].play();return this},exec:function(j,p){var m=this.active;this.inOuts.ofClips.forEach(function(o,q){if(j>=
+o["in"]&&j<=o.out)m=q});j+=this.inOuts.ofVideos[m]["in"]-this.inOuts.ofClips[m]["in"];f.addTrackEvent(this.playlist[m],{start:j-1,end:j,_running:false,_natives:{start:p||f.nop,end:f.nop,type:"exec"}});return this},listen:function(j,p){var m=this,o=this.playlist,q=o.length,s=0;if(!p)p=f.nop;if(f.Events.Natives.indexOf(j)>-1)f.forEach(o,function(d){d.listen(j,function(A){A.active=m;if(i.indexOf(j)>-1)p.call(d,A);else++s===q&&p.call(d,A)})});else{this.events[j]||(this.events[j]={});o=p.name||f.guid("__"+
+j);this.events[j][o]=p}return this},unlisten:function(){},trigger:function(j,p){var m=this;if(!(f.Events.Natives.indexOf(j)>-1)){this.events[j]&&f.forEach(this.events[j],function(o){o.call(m,{type:j},p)});return this}}});f.forEach(f.manifest,function(j,p){f.sequence.prototype[p]=function(m){var o={},q=[],s,d,A,y,x;for(s=0;s<this.inOuts.ofClips.length;s++){q=this.inOuts.ofClips[s];d=h(q["in"],q.out);A=d.indexOf(m.start);y=d.indexOf(m.end);if(A>-1)o[s]=f.extend({},q,{start:d[A],clipIdx:A});if(y>-1)o[s]=
+f.extend({},q,{end:d[y],clipIdx:y})}s=Object.keys(o).map(function(g){return+g});q=h(s[0],s[1]);for(s=0;s<q.length;s++){A={};y=q[s];var a=o[y];if(a){x=this.inOuts.ofVideos[y];d=a.clipIdx;x=h(x["in"],x.out);if(a.start){A.start=x[d];A.end=x[x.length-1]}if(a.end){A.start=x[0];A.end=x[d]}}else{A.start=this.inOuts.ofVideos[y]["in"];A.end=this.inOuts.ofVideos[y].out}this.playlist[y][p](f.extend({},m,A))}return this}})})(this,Popcorn);(function(r){document.addEventListener("DOMContentLoaded",function(){var f=document.querySelectorAll("[data-timeline-sources]");r.forEach(f,function(n,c){var b=f[c],e,h,i;if(!b.id)b.id=r.guid("__popcorn");if(b.nodeType&&b.nodeType===1){i=r("#"+b.id);e=(b.getAttribute("data-timeline-sources")||"").split(",");e[0]&&r.forEach(e,function(j){h=j.split("!");if(h.length===1){h=j.match(/(.*)[\/\\]([^\/\\]+\.\w+)$/)[2].split(".");h[0]="parse"+h[1].toUpperCase();h[1]=j}e[0]&&i[h[0]]&&i[h[0]](h[1])});i.autoplay()&&
+i.play()}})},false)})(Popcorn);(function(r,f){function n(e){e=typeof e==="string"?e:[e.language,e.region].join("-");var h=e.split("-");return{iso6391:e,language:h[0]||"",region:h[1]||""}}var c=r.navigator,b=n(c.userLanguage||c.language);f.locale={get:function(){return b},set:function(e){b=n(e);f.locale.broadcast();return b},broadcast:function(e){var h=f.instances,i=h.length,j=0,p;for(e=e||"locale:changed";j<i;j++){p=h[j];e in p.data.events&&p.trigger(e)}}}})(this,this.Popcorn);(function(r){var f=Object.prototype.hasOwnProperty;r.parsers={};r.parser=function(n,c,b){if(r.protect.natives.indexOf(n.toLowerCase())>=0)r.error("'"+n+"' is a protected function name");else{if(typeof c==="function"&&!b){b=c;c=""}if(!(typeof b!=="function"||typeof c!=="string")){var e={};e[n]=function(h,i){if(!h)return this;var j=this;r.xhr({url:h,dataType:c,success:function(p){var m,o,q=0;p=b(p).data||[];if(m=p.length){for(;q<m;q++){o=p[q];for(var s in o)f.call(o,s)&&j[s]&&j[s](o[s])}i&&i()}}});
+return this};r.extend(r.p,e);return e}}}})(Popcorn);(function(r){var f=function(b,e){b=b||r.nop;e=e||r.nop;return function(){b.apply(this,arguments);e.apply(this,arguments)}},n=/^.*\.(ogg|oga|aac|mp3|wav)($|\?)/,c=/^.*\.(ogg|oga|aac|mp3|wav|ogg|ogv|mp4|webm)($|\?)/;r.player=function(b,e){if(!r[b]){e=e||{};var h=function(i,j,p){p=p||{};var m=new Date/1E3,o=m,q=0,s=0,d=1,A=false,y={},x=typeof i==="string"?r.dom.find(i):i,a={};Object.prototype.__defineGetter__||(a=x||document.createElement("div"));for(var g in x)if(!(g in a))if(typeof x[g]==="object")a[g]=
+x[g];else if(typeof x[g]==="function")a[g]=function(k){return"length"in x[k]&&!x[k].call?x[k]:function(){return x[k].apply(x,arguments)}}(g);else r.player.defineProperty(a,g,{get:function(k){return function(){return x[k]}}(g),set:r.nop,configurable:true});var l=function(){m=new Date/1E3;if(!a.paused){a.currentTime+=m-o;a.dispatchEvent("timeupdate");setTimeout(l,10)}o=m};a.play=function(){this.paused=false;if(a.readyState>=4){o=new Date/1E3;a.dispatchEvent("play");l()}};a.pause=function(){this.paused=
+true;a.dispatchEvent("pause")};r.player.defineProperty(a,"currentTime",{get:function(){return q},set:function(k){q=+k;a.dispatchEvent("timeupdate");return q},configurable:true});r.player.defineProperty(a,"volume",{get:function(){return d},set:function(k){d=+k;a.dispatchEvent("volumechange");return d},configurable:true});r.player.defineProperty(a,"muted",{get:function(){return A},set:function(k){A=+k;a.dispatchEvent("volumechange");return A},configurable:true});r.player.defineProperty(a,"readyState",
+{get:function(){return s},set:function(k){return s=k},configurable:true});a.addEventListener=function(k,t){y[k]||(y[k]=[]);y[k].push(t);return t};a.removeEventListener=function(k,t){var u,v=y[k];if(v){for(u=y[k].length-1;u>=0;u--)t===v[u]&&v.splice(u,1);return t}};a.dispatchEvent=function(k){var t,u=k.type;if(!u){u=k;if(k=r.events.getInterface(u)){t=document.createEvent(k);t.initEvent(u,true,true,window,1)}}if(y[u])for(k=y[u].length-1;k>=0;k--)y[u][k].call(this,t,this)};a.src=j||"";a.duration=0;a.paused=
+true;a.ended=0;p&&p.events&&r.forEach(p.events,function(k,t){a.addEventListener(t,k,false)});if(e._canPlayType(x.nodeName,j)!==false)if(e._setup)e._setup.call(a,p);else{a.readyState=4;a.dispatchEvent("loadedmetadata");a.dispatchEvent("loadeddata");a.dispatchEvent("canplaythrough")}else setTimeout(function(){a.dispatchEvent("error")},0);i=new r.p.init(a,p);if(e._teardown)i.destroy=f(i.destroy,function(){e._teardown.call(a,p)});return i};h.canPlayType=e._canPlayType=e._canPlayType||r.nop;r[b]=r.player.registry[b]=
+h}};r.player.registry={};r.player.defineProperty=Object.defineProperty||function(b,e,h){b.__defineGetter__(e,h.get||r.nop);b.__defineSetter__(e,h.set||r.nop)};r.player.playerQueue=function(){var b=[],e=false;return{next:function(){e=false;b.shift();b[0]&&b[0]()},add:function(h){b.push(function(){e=true;h&&h()});!e&&b[0]()}}};r.smart=function(b,e,h){var i=["AUDIO","VIDEO"],j,p=r.dom.find(b),m;j=document.createElement("video");var o={ogg:"video/ogg",ogv:"video/ogg",oga:"audio/ogg",webm:"video/webm",
+mp4:"video/mp4",mp3:"audio/mp3"};if(p){if(i.indexOf(p.nodeName)>-1&&!e){if(typeof e==="object")h=e;return r(p,h)}if(typeof e==="string")e=[e];b=0;for(srcLength=e.length;b<srcLength;b++){m=c.exec(e[b]);m=!m||!m[1]?false:j.canPlayType(o[m[1]]);if(m){e=e[b];break}for(var q in r.player.registry)if(r.player.registry.hasOwnProperty(q))if(r.player.registry[q].canPlayType(p.nodeName,e[b]))return r[q](p,e[b],h)}if(i.indexOf(p.nodeName)===-1){j=typeof e==="string"?e:e.length?e[0]:e;b=document.createElement(n.exec(j)?
+i[0]:i[1]);b.controls=true;p.appendChild(b);p=b}h&&h.events&&h.events.error&&p.addEventListener("error",h.events.error,false);p.src=e;return r(p,h)}else r.error("Specified target "+b+" was not found.")}})(Popcorn);(function(r){var f=function(n,c){var b=0,e=0,h;r.forEach(c.classes,function(i,j){h=[];if(i==="parent")h[0]=document.querySelectorAll("#"+c.target)[0].parentNode;else h=document.querySelectorAll("#"+c.target+" "+i);b=0;for(e=h.length;b<e;b++)h[b].classList.toggle(j)})};r.compose("applyclass",{manifest:{about:{name:"Popcorn applyclass Effect",version:"0.1",author:"@scottdowne",website:"scottdowne.wordpress.com"},options:{}},_setup:function(n){n.classes={};n.applyclass=n.applyclass||"";for(var c=n.applyclass.replace(/\s/g,
+"").split(","),b=[],e=0,h=c.length;e<h;e++){b=c[e].split(":");if(b[0])n.classes[b[0]]=b[1]||""}},start:f,end:f})})(Popcorn);(function(r){var f=/(?:http:\/\/www\.|http:\/\/|www\.|\.|^)(youtu|vimeo|soundcloud|baseplayer)/,n={},c={vimeo:false,youtube:false,soundcloud:false,module:false};Object.defineProperty(n,void 0,{get:function(){return c[void 0]},set:function(b){c[void 0]=b}});r.plugin("mediaspawner",{manifest:{about:{name:"Popcorn Media Spawner Plugin",version:"0.1",author:"Matthew Schranz, @mjschranz",website:"mschranz.wordpress.com"},options:{source:{elem:"input",type:"text",label:"Media Source","default":"http://www.youtube.com/watch?v=CXDstfD9eJ0"},
+caption:{elem:"input",type:"text",label:"Media Caption","default":"Popcorn Popping",optional:true},target:"mediaspawner-container",start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},autoplay:{elem:"input",type:"checkbox",label:"Autoplay Video",optional:true},width:{elem:"input",type:"number",label:"Media Width","default":400,units:"px",optional:true},height:{elem:"input",type:"number",label:"Media Height","default":200,units:"px",optional:true}}},_setup:function(b){function e(){function o(){if(j!==
+"HTML5"&&!window.Popcorn[j])setTimeout(function(){o()},300);else{b.id=b._container.id;b._container.style.width=b.width+"px";b._container.style.height=b.height+"px";b.popcorn=r.smart("#"+b.id,b.source);j==="HTML5"&&b.popcorn.controls(true);b._container.style.width="0px";b._container.style.height="0px";b._container.style.visibility="hidden";b._container.style.overflow="hidden"}}if(j!=="HTML5"&&!window.Popcorn[j]&&!n[j]){n[j]=true;r.getScript("http://popcornjs.org/code/players/"+j+"/popcorn."+j+".js",
+function(){o()})}else o()}function h(){window.Popcorn.player?e():setTimeout(function(){h()},300)}var i=document.getElementById(b.target)||{},j,p,m;if(p=f.exec(b.source)){j=p[1];if(j==="youtu")j="youtube"}else j="HTML5";b._type=j;b._container=document.createElement("div");p=b._container;p.id="mediaSpawnerdiv-"+r.guid();b.width=b.width||400;b.height=b.height||200;if(b.caption){m=document.createElement("div");m.innerHTML=b.caption;m.style.display="none";b._capCont=m;p.appendChild(m)}i&&i.appendChild(p);
+if(!window.Popcorn.player&&!n.module){n.module=true;r.getScript("http://popcornjs.org/code/modules/player/popcorn.player.js",h)}else h()},start:function(b,e){if(e._capCont)e._capCont.style.display="";e._container.style.width=e.width+"px";e._container.style.height=e.height+"px";e._container.style.visibility="visible";e._container.style.overflow="visible";e.autoplay&&e.popcorn.play()},end:function(b,e){if(e._capCont)e._capCont.style.display="none";e._container.style.width="0px";e._container.style.height=
+"0px";e._container.style.visibility="hidden";e._container.style.overflow="hidden";e.popcorn.pause()},_teardown:function(b){b.popcorn&&b.popcorn.destory&&b.popcorn.destroy();document.getElementById(b.target)&&document.getElementById(b.target).removeChild(b._container)}})})(Popcorn,this);(function(r){r.plugin("code",function(f){var n=false,c=this,b=function(){var e=function(h){return function(i,j){var p=function(){n&&i.call(c,j);n&&h(p)};p()}};return window.webkitRequestAnimationFrame?e(window.webkitRequestAnimationFrame):window.mozRequestAnimationFrame?e(window.mozRequestAnimationFrame):e(function(h){window.setTimeout(h,16)})}();if(!f.onStart||typeof f.onStart!=="function")f.onStart=r.nop;if(f.onEnd&&typeof f.onEnd!=="function")f.onEnd=undefined;if(f.onFrame&&typeof f.onFrame!==
+"function")f.onFrame=undefined;return{start:function(e,h){h.onStart.call(c,h);if(h.onFrame){n=true;b(h.onFrame,h)}},end:function(e,h){if(h.onFrame)n=false;h.onEnd&&h.onEnd.call(c,h)}}},{about:{name:"Popcorn Code Plugin",version:"0.1",author:"David Humphrey (@humphd)",website:"http://vocamus.net/dave"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},onStart:{elem:"input",type:"function",label:"onStart"},onFrame:{elem:"input",type:"function",label:"onFrame",
+optional:true},onEnd:{elem:"input",type:"function",label:"onEnd"}}})})(Popcorn);(function(r){var f=0;r.plugin("flickr",function(n){var c,b=document.getElementById(n.target),e,h,i,j,p=n.numberofimages||4,m=n.height||"50px",o=n.width||"50px",q=n.padding||"5px",s=n.border||"0px";c=document.createElement("div");c.id="flickr"+f;c.style.width="100%";c.style.height="100%";c.style.display="none";f++;b&&b.appendChild(c);var d=function(){if(e)setTimeout(function(){d()},5);else{h="http://api.flickr.com/services/rest/?method=flickr.people.findByUsername&";h+="username="+n.username+"&api_key="+
+n.apikey+"&format=json&jsoncallback=flickr";r.getJSONP(h,function(y){e=y.user.nsid;A()})}},A=function(){h="http://api.flickr.com/services/feeds/photos_public.gne?";if(e)h+="id="+e+"&";if(n.tags)h+="tags="+n.tags+"&";h+="lang=en-us&format=json&jsoncallback=flickr";r.xhr.getJSONP(h,function(y){var x=document.createElement("div");x.innerHTML="<p style='padding:"+q+";'>"+y.title+"<p/>";r.forEach(y.items,function(a,g){if(g<p){i=document.createElement("a");i.setAttribute("href",a.link);i.setAttribute("target",
+"_blank");j=document.createElement("img");j.setAttribute("src",a.media.m);j.setAttribute("height",m);j.setAttribute("width",o);j.setAttribute("style","border:"+s+";padding:"+q);i.appendChild(j);x.appendChild(i)}else return false});c.appendChild(x)})};if(n.username&&n.apikey)d();else{e=n.userid;A()}return{start:function(){c.style.display="inline"},end:function(){c.style.display="none"},_teardown:function(y){document.getElementById(y.target)&&document.getElementById(y.target).removeChild(c)}}},{about:{name:"Popcorn Flickr Plugin",
+version:"0.2",author:"Scott Downe, Steven Weerdenburg, Annasob",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},userid:{elem:"input",type:"text",label:"User ID",optional:true},tags:{elem:"input",type:"text",label:"Tags"},username:{elem:"input",type:"text",label:"Username",optional:true},apikey:{elem:"input",type:"text",label:"API Key",optional:true},target:"flickr-container",height:{elem:"input",type:"text",
+label:"Height","default":"50px",optional:true},width:{elem:"input",type:"text",label:"Width","default":"50px",optional:true},padding:{elem:"input",type:"text",label:"Padding",optional:true},border:{elem:"input",type:"text",label:"Border","default":"5px",optional:true},numberofimages:{elem:"input",type:"number","default":4,label:"Number of Images"}}})})(Popcorn);(function(r){r.plugin("footnote",{manifest:{about:{name:"Popcorn Footnote Plugin",version:"0.2",author:"@annasob, @rwaldron",website:"annasob.wordpress.com"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},text:{elem:"input",type:"text",label:"Text"},target:"footnote-container"}},_setup:function(f){var n=r.dom.find(f.target);f._container=document.createElement("div");f._container.style.display="none";f._container.innerHTML=f.text;n.appendChild(f._container)},
+start:function(f,n){n._container.style.display="inline"},end:function(f,n){n._container.style.display="none"},_teardown:function(f){var n=r.dom.find(f.target);n&&n.removeChild(f._container)}})})(Popcorn);(function(r){function f(b){return String(b).replace(/&(?!\w+;)|[<>"']/g,function(e){return c[e]||e})}function n(b,e){var h=b.container=document.createElement("div"),i=h.style,j=b.media,p=function(){var m=b.position();i.fontSize="18px";i.width=j.offsetWidth+"px";i.top=m.top+j.offsetHeight-h.offsetHeight-40+"px";i.left=m.left+"px";setTimeout(p,10)};h.id=e||"";i.position="absolute";i.color="white";i.textShadow="black 2px 2px 6px";i.fontWeight="bold";i.textAlign="center";p();b.media.parentNode.appendChild(h);
+return h}var c={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};r.plugin("text",{manifest:{about:{name:"Popcorn Text Plugin",version:"0.1",author:"@humphd"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},text:{elem:"input",type:"text",label:"Text","default":"Popcorn.js"},escape:{elem:"input",type:"checkbox",label:"Escape"},multiline:{elem:"input",type:"checkbox",label:"Multiline"}}},_setup:function(b){var e,h,i=b._container=document.createElement("div");
+i.style.display="none";if(b.target)if(e=r.dom.find(b.target)){if(["VIDEO","AUDIO"].indexOf(e.nodeName)>-1)e=n(this,b.target+"-overlay")}else e=n(this,b.target);else e=this.container?this.container:n(this);b._target=e;h=b.escape?f(b.text):b.text;h=b.multiline?h.replace(/\r?\n/gm,"<br>"):h;i.innerHTML=h||"";e.appendChild(i)},start:function(b,e){e._container.style.display="inline"},end:function(b,e){e._container.style.display="none"},_teardown:function(b){var e=b._target;e&&e.removeChild(b._container)}})})(Popcorn);var googleCallback;
+(function(r){function f(i,j,p){i=i.type?i.type.toUpperCase():"HYBRID";var m;if(i==="STAMEN-WATERCOLOR"||i==="STAMEN-TERRAIN"||i==="STAMEN-TONER")m=i.replace("STAMEN-","").toLowerCase();p=new google.maps.Map(p,{mapTypeId:m?m:google.maps.MapTypeId[i],mapTypeControlOptions:{mapTypeIds:[]}});m&&p.mapTypes.set(m,new google.maps.StamenMapType(m));p.getDiv().style.display="none";return p}var n=1,c=false,b=false,e,h;googleCallback=function(i){if(typeof google!=="undefined"&&google.maps&&google.maps.Geocoder&&
+google.maps.LatLng){e=new google.maps.Geocoder;r.getScript("//maps.stamen.com/js/tile.stamen.js",function(){b=true})}else setTimeout(function(){googleCallback(i)},1)};h=function(){if(document.body){c=true;r.getScript("//maps.google.com/maps/api/js?sensor=false&callback=googleCallback")}else setTimeout(function(){h()},1)};r.plugin("googlemap",function(i){var j,p,m,o=document.getElementById(i.target);i.type=i.type||"ROADMAP";i.zoom=i.zoom||1;i.lat=i.lat||0;i.lng=i.lng||0;c||h();j=document.createElement("div");
+j.id="actualmap"+n;j.style.width=i.width||"100%";j.style.height=i.height?i.height:o&&o.clientHeight?o.clientHeight+"px":"100%";n++;o&&o.appendChild(j);var q=function(){if(b){if(j)if(i.location)e.geocode({address:i.location},function(s,d){if(j&&d===google.maps.GeocoderStatus.OK){i.lat=s[0].geometry.location.lat();i.lng=s[0].geometry.location.lng();m=new google.maps.LatLng(i.lat,i.lng);p=f(i,m,j)}});else{m=new google.maps.LatLng(i.lat,i.lng);p=f(i,m,j)}}else setTimeout(function(){q()},5)};q();return{start:function(s,
+d){var A=this,y,x=function(){if(p){d._map=p;p.getDiv().style.display="block";google.maps.event.trigger(p,"resize");p.setCenter(m);if(d.zoom&&typeof d.zoom!=="number")d.zoom=+d.zoom;p.setZoom(d.zoom);if(d.heading&&typeof d.heading!=="number")d.heading=+d.heading;if(d.pitch&&typeof d.pitch!=="number")d.pitch=+d.pitch;if(d.type==="STREETVIEW"){p.setStreetView(y=new google.maps.StreetViewPanorama(j,{position:m,pov:{heading:d.heading=d.heading||0,pitch:d.pitch=d.pitch||0,zoom:d.zoom}}));var a=function(z,
+C){var E=google.maps.geometry.spherical.computeHeading;setTimeout(function(){var B=A.media.currentTime;if(typeof d.tween==="object"){for(var w=0,D=z.length;w<D;w++){var F=z[w];if(B>=F.interval*(w+1)/1E3&&(B<=F.interval*(w+2)/1E3||B>=F.interval*D/1E3)){u.setPosition(new google.maps.LatLng(F.position.lat,F.position.lng));u.setPov({heading:F.pov.heading||E(F,z[w+1])||0,zoom:F.pov.zoom||0,pitch:F.pov.pitch||0})}}a(z,z[0].interval)}else{w=0;for(D=z.length;w<D;w++){F=d.interval;if(B>=F*(w+1)/1E3&&(B<=F*
+(w+2)/1E3||B>=F*D/1E3)){g.setPov({heading:E(z[w],z[w+1])||0,zoom:d.zoom,pitch:d.pitch||0});g.setPosition(l[w])}}a(l,d.interval)}},C)};if(d.location&&typeof d.tween==="string"){var g=y,l=[],k=new google.maps.DirectionsService,t=new google.maps.DirectionsRenderer(g);k.route({origin:d.location,destination:d.tween,travelMode:google.maps.TravelMode.DRIVING},function(z,C){if(C==google.maps.DirectionsStatus.OK){t.setDirections(z);for(var E=z.routes[0].overview_path,B=0,w=E.length;B<w;B++)l.push(new google.maps.LatLng(E[B].lat(),
+E[B].lng()));d.interval=d.interval||1E3;a(l,10)}})}else if(typeof d.tween==="object"){var u=y;k=0;for(var v=d.tween.length;k<v;k++){d.tween[k].interval=d.tween[k].interval||1E3;a(d.tween,10)}}}d.onmaploaded&&d.onmaploaded(d,p)}else setTimeout(function(){x()},13)};x()},end:function(){if(p)p.getDiv().style.display="none"},_teardown:function(s){var d=document.getElementById(s.target);d&&d.removeChild(j);j=p=m=null;s._map=null}}},{about:{name:"Popcorn Google Map Plugin",version:"0.1",author:"@annasob",
+website:"annasob.wordpress.com"},options:{start:{elem:"input",type:"start",label:"Start"},end:{elem:"input",type:"start",label:"End"},target:"map-container",type:{elem:"select",options:["ROADMAP","SATELLITE","STREETVIEW","HYBRID","TERRAIN","STAMEN-WATERCOLOR","STAMEN-TERRAIN","STAMEN-TONER"],label:"Map Type",optional:true},zoom:{elem:"input",type:"text",label:"Zoom","default":0,optional:true},lat:{elem:"input",type:"text",label:"Lat",optional:true},lng:{elem:"input",type:"text",label:"Lng",optional:true},
+location:{elem:"input",type:"text",label:"Location","default":"Toronto, Ontario, Canada"},heading:{elem:"input",type:"text",label:"Heading","default":0,optional:true},pitch:{elem:"input",type:"text",label:"Pitch","default":1,optional:true}}})})(Popcorn);(function(r){function f(b){function e(){var p=b.getBoundingClientRect(),m=i.getBoundingClientRect();if(m.left!==p.left)i.style.left=p.left+"px";if(m.top!==p.top)i.style.top=p.top+"px"}var h=-1,i=document.createElement("div"),j=getComputedStyle(b).zIndex;i.setAttribute("data-popcorn-helper-container",true);i.style.position="absolute";i.style.zIndex=isNaN(j)?n:j+1;document.body.appendChild(i);return{element:i,start:function(){h=setInterval(e,c)},stop:function(){clearInterval(h);h=-1},destroy:function(){document.body.removeChild(i);
+h!==-1&&clearInterval(h)}}}var n=2E3,c=10;r.plugin("image",{manifest:{about:{name:"Popcorn image Plugin",version:"0.1",author:"Scott Downe",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},src:{elem:"input",type:"url",label:"Image URL","default":"http://mozillapopcorn.org/wp-content/themes/popcorn/images/for_developers.png"},href:{elem:"input",type:"url",label:"Link","default":"http://mozillapopcorn.org/wp-content/themes/popcorn/images/for_developers.png",
+optional:true},target:"image-container",text:{elem:"input",type:"text",label:"Caption","default":"Popcorn.js",optional:true}}},_setup:function(b){var e=document.createElement("img"),h=document.getElementById(b.target);b.anchor=document.createElement("a");b.anchor.style.position="relative";b.anchor.style.textDecoration="none";b.anchor.style.display="none";if(h)if(["VIDEO","AUDIO"].indexOf(h.nodeName)>-1){b.trackedContainer=f(h);b.trackedContainer.element.appendChild(b.anchor)}else h&&h.appendChild(b.anchor);
+e.addEventListener("load",function(){e.style.borderStyle="none";b.anchor.href=b.href||b.src||"#";b.anchor.target="_blank";var i,j;e.style.height=h.style.height;e.style.width=h.style.width;b.anchor.appendChild(e);if(b.text){i=e.height/12+"px";j=document.createElement("div");r.extend(j.style,{color:"black",fontSize:i,fontWeight:"bold",position:"relative",textAlign:"center",width:e.style.width||e.width+"px",zIndex:"10"});j.innerHTML=b.text||"";j.style.top=(e.style.height.replace("px","")||e.height)/
+2-j.offsetHeight/2+"px";b.anchor.insertBefore(j,e)}},false);e.src=b.src},start:function(b,e){e.anchor.style.display="inline";e.trackedContainer&&e.trackedContainer.start()},end:function(b,e){e.anchor.style.display="none";e.trackedContainer&&e.trackedContainer.stop()},_teardown:function(b){if(b.trackedContainer)b.trackedContainer.destroy();else b.anchor.parentNode&&b.anchor.parentNode.removeChild(b.anchor)}})})(Popcorn);(function(r){var f=1,n=false;r.plugin("googlefeed",function(c){var b=function(){var j=false,p=0,m=document.getElementsByTagName("link"),o=m.length,q=document.head||document.getElementsByTagName("head")[0],s=document.createElement("link");if(window.GFdynamicFeedControl)n=true;else r.getScript("//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.js",function(){n=true});for(;p<o;p++)if(m[p].href==="//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.css")j=true;if(!j){s.type=
+"text/css";s.rel="stylesheet";s.href="//www.google.com/uds/solutions/dynamicfeed/gfdynamicfeedcontrol.css";q.insertBefore(s,q.firstChild)}};window.google?b():r.getScript("//www.google.com/jsapi",function(){google.load("feeds","1",{callback:function(){b()}})});var e=document.createElement("div"),h=document.getElementById(c.target),i=function(){if(n)c.feed=new GFdynamicFeedControl(c.url,e,{vertical:c.orientation.toLowerCase()==="vertical"?true:false,horizontal:c.orientation.toLowerCase()==="horizontal"?
+true:false,title:c.title=c.title||"Blog"});else setTimeout(function(){i()},5)};if(!c.orientation||c.orientation.toLowerCase()!=="vertical"&&c.orientation.toLowerCase()!=="horizontal")c.orientation="vertical";e.style.display="none";e.id="_feed"+f;e.style.width="100%";e.style.height="100%";f++;h&&h.appendChild(e);i();return{start:function(){e.setAttribute("style","display:inline")},end:function(){e.setAttribute("style","display:none")},_teardown:function(j){document.getElementById(j.target)&&document.getElementById(j.target).removeChild(e);
+delete j.feed}}},{about:{name:"Popcorn Google Feed Plugin",version:"0.1",author:"David Seifried",website:"dseifried.wordpress.com"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"feed-container",url:{elem:"input",type:"url",label:"Feed URL","default":"http://planet.mozilla.org/rss20.xml"},title:{elem:"input",type:"text",label:"Title","default":"Planet Mozilla",optional:true},orientation:{elem:"select",options:["Vertical","Horizontal"],
+label:"Orientation","default":"Vertical",optional:true}}})})(Popcorn);(function(r){var f=0,n=function(c,b){var e=c.container=document.createElement("div"),h=e.style,i=c.media,j=function(){var p=c.position();h.fontSize="18px";h.width=i.offsetWidth+"px";h.top=p.top+i.offsetHeight-e.offsetHeight-40+"px";h.left=p.left+"px";setTimeout(j,10)};e.id=b||r.guid();h.position="absolute";h.color="white";h.textShadow="black 2px 2px 6px";h.fontWeight="bold";h.textAlign="center";j();c.media.parentNode.appendChild(e);return e};r.plugin("subtitle",{manifest:{about:{name:"Popcorn Subtitle Plugin",
+version:"0.1",author:"Scott Downe",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"text",label:"Start"},end:{elem:"input",type:"text",label:"End"},target:"subtitle-container",text:{elem:"input",type:"text",label:"Text"}}},_setup:function(c){var b=document.createElement("div");b.id="subtitle-"+f++;b.style.display="none";!this.container&&(!c.target||c.target==="subtitle-container")&&n(this);c.container=c.target&&c.target!=="subtitle-container"?document.getElementById(c.target)||
+n(this,c.target):this.container;document.getElementById(c.container.id)&&document.getElementById(c.container.id).appendChild(b);c.innerContainer=b;c.showSubtitle=function(){c.innerContainer.innerHTML=c.text||""}},start:function(c,b){b.innerContainer.style.display="inline";b.showSubtitle(b,b.text)},end:function(c,b){b.innerContainer.style.display="none";b.innerContainer.innerHTML=""},_teardown:function(c){c.container.removeChild(c.innerContainer)}})})(Popcorn);(function(r){var f=false;r.plugin("twitter",{manifest:{about:{name:"Popcorn Twitter Plugin",version:"0.1",author:"Scott Downe",website:"http://scottdowne.wordpress.com/"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},src:{elem:"input",type:"text",label:"Tweet Source (# or @)","default":"@popcornjs"},target:"twitter-container",height:{elem:"input",type:"number",label:"Height","default":"200",optional:true},width:{elem:"input",type:"number",label:"Width",
+"default":"250",optional:true}}},_setup:function(n){if(!window.TWTR&&!f){f=true;r.getScript("//widgets.twimg.com/j/2/widget.js")}var c=document.getElementById(n.target);n.container=document.createElement("div");n.container.setAttribute("id",r.guid());n.container.style.display="none";c&&c.appendChild(n.container);var b=n.src||"";c=n.width||250;var e=n.height||200,h=/^@/.test(b),i={version:2,id:n.container.getAttribute("id"),rpp:30,width:c,height:e,interval:6E3,theme:{shell:{background:"#ffffff",color:"#000000"},
+tweets:{background:"#ffffff",color:"#444444",links:"#1985b5"}},features:{loop:true,timestamp:true,avatars:true,hashtags:true,toptweets:true,live:true,scrollbar:false,behavior:"default"}},j=function(p){if(window.TWTR)if(h){i.type="profile";(new TWTR.Widget(i)).render().setUser(b).start()}else{i.type="search";i.search=b;i.subject=b;(new TWTR.Widget(i)).render().start()}else setTimeout(function(){j(p)},1)};j(this)},start:function(n,c){c.container.style.display="inline"},end:function(n,c){c.container.style.display=
+"none"},_teardown:function(n){document.getElementById(n.target)&&document.getElementById(n.target).removeChild(n.container)}})})(Popcorn);(function(r){r.plugin("webpage",{manifest:{about:{name:"Popcorn Webpage Plugin",version:"0.1",author:"@annasob",website:"annasob.wordpress.com"},options:{id:{elem:"input",type:"text",label:"Id",optional:true},start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},src:{elem:"input",type:"url",label:"Webpage URL","default":"http://mozillapopcorn.org"},target:"iframe-container"}},_setup:function(f){var n=document.getElementById(f.target);f.src=f.src.replace(/^(https?:)?(\/\/)?/,
+"//");f._iframe=document.createElement("iframe");f._iframe.setAttribute("width","100%");f._iframe.setAttribute("height","100%");f._iframe.id=f.id;f._iframe.src=f.src;f._iframe.style.display="none";n&&n.appendChild(f._iframe)},start:function(f,n){n._iframe.src=n.src;n._iframe.style.display="inline"},end:function(f,n){n._iframe.style.display="none"},_teardown:function(f){document.getElementById(f.target)&&document.getElementById(f.target).removeChild(f._iframe)}})})(Popcorn);var wikiCallback;
+(function(r){r.plugin("wikipedia",{manifest:{about:{name:"Popcorn Wikipedia Plugin",version:"0.1",author:"@annasob",website:"annasob.wordpress.com"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},lang:{elem:"input",type:"text",label:"Language","default":"english",optional:true},src:{elem:"input",type:"url",label:"Wikipedia URL","default":"http://en.wikipedia.org/wiki/Cat"},title:{elem:"input",type:"text",label:"Title","default":"Cats",optional:true},
+numberofwords:{elem:"input",type:"number",label:"Number of Words","default":"200",optional:true},target:"wikipedia-container"}},_setup:function(f){var n,c=r.guid();if(!f.lang)f.lang="en";f.numberofwords=f.numberofwords||200;window["wikiCallback"+c]=function(b){f._link=document.createElement("a");f._link.setAttribute("href",f.src);f._link.setAttribute("target","_blank");f._link.innerHTML=f.title||b.parse.displaytitle;f._desc=document.createElement("p");n=b.parse.text["*"].substr(b.parse.text["*"].indexOf("<p>"));
+n=n.replace(/((<(.|\n)+?>)|(\((.*?)\) )|(\[(.*?)\]))/g,"");n=n.split(" ");f._desc.innerHTML=n.slice(0,n.length>=f.numberofwords?f.numberofwords:n.length).join(" ")+" ...";f._fired=true};f.src&&r.getScript("//"+f.lang+".wikipedia.org/w/api.php?action=parse&props=text&redirects&page="+f.src.slice(f.src.lastIndexOf("/")+1)+"&format=json&callback=wikiCallback"+c)},start:function(f,n){var c=function(){if(n._fired){if(n._link&&n._desc)if(document.getElementById(n.target)){document.getElementById(n.target).appendChild(n._link);
+document.getElementById(n.target).appendChild(n._desc);n._added=true}}else setTimeout(function(){c()},13)};c()},end:function(f,n){if(n._added){document.getElementById(n.target).removeChild(n._link);document.getElementById(n.target).removeChild(n._desc)}},_teardown:function(f){if(f._added){f._link.parentNode&&document.getElementById(f.target).removeChild(f._link);f._desc.parentNode&&document.getElementById(f.target).removeChild(f._desc);delete f.target}}})})(Popcorn);(function(r){r.plugin("mustache",function(f){var n,c,b,e;r.getScript("http://mustache.github.com/extras/mustache.js");var h=!!f.dynamic,i=typeof f.template,j=typeof f.data,p=document.getElementById(f.target);f.container=p||document.createElement("div");if(i==="function")if(h)b=f.template;else e=f.template(f);else e=i==="string"?f.template:"";if(j==="function")if(h)n=f.data;else c=f.data(f);else c=j==="string"?JSON.parse(f.data):j==="object"?f.data:"";return{start:function(m,o){var q=function(){if(window.Mustache){if(n)c=
+n(o);if(b)e=b(o);var s=Mustache.to_html(e,c).replace(/^\s*/mg,"");o.container.innerHTML=s}else setTimeout(function(){q()},10)};q()},end:function(m,o){o.container.innerHTML=""},_teardown:function(){n=c=b=e=null}}},{about:{name:"Popcorn Mustache Plugin",version:"0.1",author:"David Humphrey (@humphd)",website:"http://vocamus.net/dave"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"mustache-container",template:{elem:"input",type:"text",
+label:"Template"},data:{elem:"input",type:"text",label:"Data"},dynamic:{elem:"input",type:"checkbox",label:"Dynamic","default":true}}})})(Popcorn);(function(r){function f(c,b){if(c.map)c.map.div.style.display=b;else setTimeout(function(){f(c,b)},10)}var n=1;r.plugin("openmap",function(c){var b,e,h,i,j,p,m,o,q=document.getElementById(c.target);b=document.createElement("div");b.id="openmapdiv"+n;b.style.width="100%";b.style.height="100%";n++;q&&q.appendChild(b);o=function(){if(window.OpenLayers&&window.OpenLayers.Layer.Stamen){if(c.location){location=new OpenLayers.LonLat(0,0);r.getJSONP("//tinygeocoder.com/create-api.php?q="+c.location+"&callback=jsonp",
+function(d){e=new OpenLayers.LonLat(d[1],d[0])})}else e=new OpenLayers.LonLat(c.lng,c.lat);c.type=c.type||"ROADMAP";switch(c.type){case "SATELLITE":c.map=new OpenLayers.Map({div:b,maxResolution:0.28125,tileSize:new OpenLayers.Size(512,512)});var s=new OpenLayers.Layer.WorldWind("LANDSAT","//worldwind25.arc.nasa.gov/tile/tile.aspx",2.25,4,{T:"105"});c.map.addLayer(s);i=new OpenLayers.Projection("EPSG:4326");h=new OpenLayers.Projection("EPSG:4326");break;case "TERRAIN":i=new OpenLayers.Projection("EPSG:4326");
+h=new OpenLayers.Projection("EPSG:4326");c.map=new OpenLayers.Map({div:b,projection:h});s=new OpenLayers.Layer.WMS("USGS Terraserver","//terraserver-usa.org/ogcmap.ashx?",{layers:"DRG"});c.map.addLayer(s);break;case "STAMEN-TONER":case "STAMEN-WATERCOLOR":case "STAMEN-TERRAIN":s=c.type.replace("STAMEN-","").toLowerCase();s=new OpenLayers.Layer.Stamen(s);i=new OpenLayers.Projection("EPSG:4326");h=new OpenLayers.Projection("EPSG:900913");e=e.transform(i,h);c.map=new OpenLayers.Map({div:b,projection:h,
+displayProjection:i,controls:[new OpenLayers.Control.Navigation,new OpenLayers.Control.PanPanel,new OpenLayers.Control.ZoomPanel]});c.map.addLayer(s);break;default:h=new OpenLayers.Projection("EPSG:900913");i=new OpenLayers.Projection("EPSG:4326");e=e.transform(i,h);c.map=new OpenLayers.Map({div:b,projection:h,displayProjection:i});s=new OpenLayers.Layer.OSM;c.map.addLayer(s)}if(c.map){c.map.setCenter(e,c.zoom||10);c.map.div.style.display="none"}}else setTimeout(function(){o()},50)};o();return{_setup:function(s){window.OpenLayers||
+r.getScript("//openlayers.org/api/OpenLayers.js",function(){r.getScript("//maps.stamen.com/js/tile.stamen.js")});var d=function(){if(s.map){s.zoom=s.zoom||2;if(s.zoom&&typeof s.zoom!=="number")s.zoom=+s.zoom;s.map.setCenter(e,s.zoom);if(s.markers){var A=OpenLayers.Util.extend({},OpenLayers.Feature.Vector.style["default"]),y=function(v){clickedFeature=v.feature;if(clickedFeature.attributes.text){m=new OpenLayers.Popup.FramedCloud("featurePopup",clickedFeature.geometry.getBounds().getCenterLonLat(),
+new OpenLayers.Size(120,250),clickedFeature.attributes.text,null,true,function(){p.unselect(this.feature)});clickedFeature.popup=m;m.feature=clickedFeature;s.map.addPopup(m)}},x=function(v){feature=v.feature;if(feature.popup){m.feature=null;s.map.removePopup(feature.popup);feature.popup.destroy();feature.popup=null}},a=function(v){r.getJSONP("//tinygeocoder.com/create-api.php?q="+v.location+"&callback=jsonp",function(z){z=(new OpenLayers.Geometry.Point(z[1],z[0])).transform(i,h);var C=OpenLayers.Util.extend({},
+A);if(!v.size||isNaN(v.size))v.size=14;C.pointRadius=v.size;C.graphicOpacity=1;C.externalGraphic=v.icon;z=new OpenLayers.Feature.Vector(z,null,C);if(v.text)z.attributes={text:v.text};j.addFeatures([z])})};j=new OpenLayers.Layer.Vector("Point Layer",{style:A});s.map.addLayer(j);for(var g=0,l=s.markers.length;g<l;g++){var k=s.markers[g];if(k.text)if(!p){p=new OpenLayers.Control.SelectFeature(j);s.map.addControl(p);p.activate();j.events.on({featureselected:y,featureunselected:x})}if(k.location)a(k);
+else{var t=(new OpenLayers.Geometry.Point(k.lng,k.lat)).transform(i,h),u=OpenLayers.Util.extend({},A);if(!k.size||isNaN(k.size))k.size=14;u.pointRadius=k.size;u.graphicOpacity=1;u.externalGraphic=k.icon;t=new OpenLayers.Feature.Vector(t,null,u);if(k.text)t.attributes={text:k.text};j.addFeatures([t])}}}}else setTimeout(function(){d()},13)};d()},start:function(s,d){f(d,"block")},end:function(s,d){f(d,"none")},_teardown:function(){q&&q.removeChild(b);b=map=e=h=i=j=p=m=null}}},{about:{name:"Popcorn OpenMap Plugin",
+version:"0.3",author:"@mapmeld",website:"mapadelsur.blogspot.com"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"map-container",type:{elem:"select",options:["ROADMAP","SATELLITE","TERRAIN"],label:"Map Type",optional:true},zoom:{elem:"input",type:"number",label:"Zoom","default":2},lat:{elem:"input",type:"text",label:"Lat",optional:true},lng:{elem:"input",type:"text",label:"Lng",optional:true},location:{elem:"input",type:"text",label:"Location",
+"default":"Toronto, Ontario, Canada"},markers:{elem:"input",type:"text",label:"List Markers",optional:true}}})})(Popcorn);document.addEventListener("click",function(r){r=r.target;if(r.nodeName==="A"||r.parentNode&&r.parentNode.nodeName==="A")Popcorn.instances.forEach(function(f){f.options.pauseOnLinkClicked&&f.pause()})},false);(function(r){var f={},n=0,c=document.createElement("span"),b=["webkit","Moz","ms","O",""],e=["Transform","TransitionDuration","TransitionTimingFunction"],h={},i;document.getElementsByTagName("head")[0].appendChild(c);for(var j=0,p=e.length;j<p;j++)for(var m=0,o=b.length;m<o;m++){i=b[m]+e[j];if(i in c.style){h[e[j].toLowerCase()]=i;break}}document.getElementsByTagName("head")[0].appendChild(c);r.plugin("wordriver",{manifest:{about:{name:"Popcorn WordRiver Plugin"},options:{start:{elem:"input",type:"number",
+label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"wordriver-container",text:{elem:"input",type:"text",label:"Text","default":"Popcorn.js"},color:{elem:"input",type:"text",label:"Color","default":"Green",optional:true}}},_setup:function(q){q._duration=q.end-q.start;var s;if(!(s=f[q.target])){s=q.target;f[s]=document.createElement("div");var d=document.getElementById(s);d&&d.appendChild(f[s]);f[s].style.height="100%";f[s].style.position="relative";s=f[s]}q._container=s;q.word=document.createElement("span");
+q.word.style.position="absolute";q.word.style.whiteSpace="nowrap";q.word.style.opacity=0;q.word.style.MozTransitionProperty="opacity, -moz-transform";q.word.style.webkitTransitionProperty="opacity, -webkit-transform";q.word.style.OTransitionProperty="opacity, -o-transform";q.word.style.transitionProperty="opacity, transform";q.word.style[h.transitionduration]="1s, "+q._duration+"s";q.word.style[h.transitiontimingfunction]="linear";q.word.innerHTML=q.text;q.word.style.color=q.color||"black"},start:function(q,
+s){s._container.appendChild(s.word);s.word.style[h.transform]="";s.word.style.fontSize=~~(30+20*Math.random())+"px";n%=s._container.offsetWidth-s.word.offsetWidth;s.word.style.left=n+"px";n+=s.word.offsetWidth+10;s.word.style[h.transform]="translateY("+(s._container.offsetHeight-s.word.offsetHeight)+"px)";s.word.style.opacity=1;setTimeout(function(){s.word.style.opacity=0},(s.end-s.start-1||1)*1E3)},end:function(q,s){s.word.style.opacity=0},_teardown:function(q){var s=document.getElementById(q.target);
+q.word.parentNode&&q._container.removeChild(q.word);f[q.target]&&!f[q.target].childElementCount&&s&&s.removeChild(f[q.target])&&delete f[q.target]}})})(Popcorn);(function(r){var f=1;r.plugin("timeline",function(n){var c=document.getElementById(n.target),b=document.createElement("div"),e,h=true;if(c&&!c.firstChild){c.appendChild(e=document.createElement("div"));e.style.width="inherit";e.style.height="inherit";e.style.overflow="auto"}else e=c.firstChild;b.style.display="none";b.id="timelineDiv"+f;n.direction=n.direction||"up";if(n.direction.toLowerCase()==="down")h=false;if(c&&e)h?e.insertBefore(b,e.firstChild):e.appendChild(b);f++;b.innerHTML="<p><span id='big' style='font-size:24px; line-height: 130%;' >"+
+n.title+"</span><br /><span id='mid' style='font-size: 16px;'>"+n.text+"</span><br />"+n.innerHTML;return{start:function(i,j){b.style.display="block";if(j.direction==="down")e.scrollTop=e.scrollHeight},end:function(){b.style.display="none"},_teardown:function(){e&&b&&e.removeChild(b)&&!e.firstChild&&c.removeChild(e)}}},{about:{name:"Popcorn Timeline Plugin",version:"0.1",author:"David Seifried @dcseifried",website:"dseifried.wordpress.com"},options:{start:{elem:"input",type:"number",label:"Start"},
+end:{elem:"input",type:"number",label:"End"},target:"feed-container",title:{elem:"input",type:"text",label:"Title"},text:{elem:"input",type:"text",label:"Text"},innerHTML:{elem:"input",type:"text",label:"HTML Code",optional:true},direction:{elem:"select",options:["DOWN","UP"],label:"Direction",optional:true}}})})(Popcorn);(function(r,f){var n={};r.plugin("documentcloud",{manifest:{about:{name:"Popcorn Document Cloud Plugin",version:"0.1",author:"@humphd, @ChrisDeCairos",website:"http://vocamus.net/dave"},options:{start:{elem:"input",type:"number",label:"Start"},end:{elem:"input",type:"number",label:"End"},target:"documentcloud-container",width:{elem:"input",type:"text",label:"Width",optional:true},height:{elem:"input",type:"text",label:"Height",optional:true},src:{elem:"input",type:"url",label:"PDF URL","default":"http://www.documentcloud.org/documents/70050-urbina-day-1-in-progress.html"},
+preload:{elem:"input",type:"checkbox",label:"Preload","default":true},page:{elem:"input",type:"number",label:"Page Number",optional:true},aid:{elem:"input",type:"number",label:"Annotation Id",optional:true}}},_setup:function(c){function b(){function m(v){c._key=v.api.getId();c._changeView=function(z){c.aid?z.pageSet.showAnnotation(z.api.getAnnotation(c.aid)):z.api.setCurrentPage(c.page)}}function o(){n[c._key]={num:1,id:c._containerId};h.loaded=true}h.loaded=false;var q=c.url.replace(/\.html$/,".js"),
+s=c.target,d=f.getElementById(s),A=f.createElement("div"),y=r.position(d),x=c.width||y.width;y=c.height||y.height;var a=c.sidebar||true,g=c.text||true,l=c.pdf||true,k=c.showAnnotations||true,t=c.zoom||700,u=c.search||true;if(!function(v){var z=false;r.forEach(h.viewers,function(C){if(C.api.getSchema().canonicalURL===v){m(C);C=n[c._key];c._containerId=C.id;C.num+=1;z=true;h.loaded=true}});return z}(c.url)){A.id=c._containerId=r.guid(s);s="#"+A.id;d.appendChild(A);i.trigger("documentready");h.load(q,
+{width:x,height:y,sidebar:a,text:g,pdf:l,showAnnotations:k,zoom:t,search:u,container:s,afterLoad:c.page||c.aid?function(v){m(v);c._changeView(v);A.style.visibility="hidden";v.elements.pages.hide();o()}:function(v){m(v);o();A.style.visibility="hidden";v.elements.pages.hide()}})}}function e(){window.DV.loaded?b():setTimeout(e,25)}var h=window.DV=window.DV||{},i=this;if(h.loading)e();else{h.loading=true;h.recordHit="//www.documentcloud.org/pixel.gif";var j=f.createElement("link"),p=f.getElementsByTagName("head")[0];
+j.rel="stylesheet";j.type="text/css";j.media="screen";j.href="//s3.documentcloud.org/viewer/viewer-datauri.css";p.appendChild(j);h.loaded=false;r.getScript("http://s3.documentcloud.org/viewer/viewer.js",function(){h.loading=false;b()})}},start:function(c,b){var e=f.getElementById(b._containerId),h=DV.viewers[b._key];(b.page||b.aid)&&h&&b._changeView(h);if(e&&h){e.style.visibility="visible";h.elements.pages.show()}},end:function(c,b){var e=f.getElementById(b._containerId);if(e&&DV.viewers[b._key]){e.style.visibility=
+"hidden";DV.viewers[b._key].elements.pages.hide()}},_teardown:function(c){var b=f.getElementById(c._containerId);if((c=c._key)&&DV.viewers[c]&&--n[c].num===0){for(DV.viewers[c].api.unload();b.hasChildNodes();)b.removeChild(b.lastChild);b.parentNode.removeChild(b)}}})})(Popcorn,window.document);(function(r){r.parser("parseJSON","JSON",function(f){var n={title:"",remote:"",data:[]};r.forEach(f.data,function(c){n.data.push(c)});return n})})(Popcorn);(function(r){r.parser("parseSBV",function(f){var n={title:"",remote:"",data:[]},c=[],b=0,e=0,h=function(q){q=q.split(":");var s=q.length-1,d;try{d=parseInt(q[s-1],10)*60+parseFloat(q[s],10);if(s===2)d+=parseInt(q[0],10)*3600}catch(A){throw"Bad cue";}return d},i=function(q,s){var d={};d[q]=s;return d};f=f.text.split(/(?:\r\n|\r|\n)/gm);for(e=f.length;b<e;){var j={},p=[],m=f[b++].split(",");try{j.start=h(m[0]);for(j.end=h(m[1]);b<e&&f[b];)p.push(f[b++]);j.text=p.join("<br />");c.push(i("subtitle",j))}catch(o){for(;b<
+e&&f[b];)b++}for(;b<e&&!f[b];)b++}n.data=c;return n})})(Popcorn);(function(r){function f(c,b){var e={};e[c]=b;return e}function n(c){c=c.split(":");try{var b=c[2].split(",");if(b.length===1)b=c[2].split(".");return parseFloat(c[0],10)*3600+parseFloat(c[1],10)*60+parseFloat(b[0],10)+parseFloat(b[1],10)/1E3}catch(e){return 0}}r.parser("parseSRT",function(c){var b={title:"",remote:"",data:[]},e=[],h=0,i=0,j,p,m,o;c=c.text.split(/(?:\r\n|\r|\n)/gm);for(h=c.length-1;h>=0&&!c[h];)h--;m=h+1;for(h=0;h<m;h++){o={};p=[];o.id=parseInt(c[h++],10);j=c[h++].split(/[\t ]*--\>[\t ]*/);
+o.start=n(j[0]);i=j[1].indexOf(" ");if(i!==-1)j[1]=j[1].substr(0,i);for(o.end=n(j[1]);h<m&&c[h];)p.push(c[h++]);o.text=p.join("\\N").replace(/\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}/gi,"");o.text=o.text.replace(/</g,"&lt;").replace(/>/g,"&gt;");o.text=o.text.replace(/&lt;(\/?(font|b|u|i|s))((\s+(\w|\w[\w\-]*\w)(\s*=\s*(?:\".*?\"|'.*?'|[^'\">\s]+))?)+\s*|\s*)(\/?)&gt;/gi,"<$1$3$7>");o.text=o.text.replace(/\\N/gi,"<br />");e.push(f("subtitle",o))}b.data=e;return b})})(Popcorn);(function(r){function f(b,e){var h=b.substr(10).split(","),i;i={start:n(h[e.start]),end:n(h[e.end])};if(i.start===-1||i.end===-1)throw"Invalid time";var j=q.call(m,/\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}/gi,""),p=j.replace,m;m=h.length;q=[];for(var o=e.text;o<m;o++)q.push(h[o]);m=q.join(",");var q=m.replace;i.text=p.call(j,/\\N/gi,"<br />");return i}function n(b){var e=b.split(":");if(b.length!==10||e.length<3)return-1;return parseInt(e[0],10)*3600+parseInt(e[1],10)*60+parseFloat(e[2],10)}function c(b,
+e){var h={};h[b]=e;return h}r.parser("parseSSA",function(b){var e={title:"",remote:"",data:[]},h=[],i=0,j;b=b.text.split(/(?:\r\n|\r|\n)/gm);for(j=b.length;i<j&&b[i]!=="[Events]";)i++;var p=b[++i].substr(8).split(", "),m={},o,q;q=0;for(o=p.length;q<o;q++)if(p[q]==="Start")m.start=q;else if(p[q]==="End")m.end=q;else if(p[q]==="Text")m.text=q;for(;++i<j&&b[i]&&b[i][0]!=="[";)try{h.push(c("subtitle",f(b[i],m)))}catch(s){}e.data=h;return e})})(Popcorn);(function(r){function f(i,j,p){var m=i.firstChild;i=n(i,p);p=[];for(var o;m;){if(m.nodeType===1)if(m.nodeName==="p")p.push(c(m,j,i));else if(m.nodeName==="div"){o=b(m.getAttribute("begin"));if(o<0)o=j;p.push.apply(p,f(m,o,i))}m=m.nextSibling}return p}function n(i,j){var p=i.getAttribute("region");return p!==null?p:j||""}function c(i,j,p){var m={};m.text=(i.textContent||i.text).replace(e,"").replace(h,"<br />");m.id=i.getAttribute("xml:id")||i.getAttribute("id");m.start=b(i.getAttribute("begin"),j);
+m.end=b(i.getAttribute("end"),j);m.target=n(i,p);if(m.end<0){m.end=b(i.getAttribute("duration"),0);if(m.end>=0)m.end+=m.start;else m.end=Number.MAX_VALUE}return{subtitle:m}}function b(i,j){var p;if(!i)return-1;try{return r.util.toSeconds(i)}catch(m){for(var o=i.length-1;o>=0&&i[o]<="9"&&i[o]>="0";)o--;p=o;o=parseFloat(i.substring(0,p));p=i.substring(p);return o*({h:3600,m:60,s:1,ms:0.0010}[p]||-1)+(j||0)}}var e=/^[\s]+|[\s]+$/gm,h=/(?:\r\n|\r|\n)/gm;r.parser("parseTTML",function(i){var j={title:"",
+remote:"",data:[]};if(!i.xml||!i.xml.documentElement)return j;i=i.xml.documentElement.firstChild;if(!i)return j;for(;i.nodeName!=="body";)i=i.nextSibling;if(i)j.data=f(i,0);return j})})(Popcorn);(function(r){r.parser("parseTTXT",function(f){var n={title:"",remote:"",data:[]},c=function(j){j=j.split(":");var p=0;try{return parseFloat(j[0],10)*60*60+parseFloat(j[1],10)*60+parseFloat(j[2],10)}catch(m){p=0}return p},b=function(j,p){var m={};m[j]=p;return m};f=f.xml.lastChild.lastChild;for(var e=Number.MAX_VALUE,h=[];f;){if(f.nodeType===1&&f.nodeName==="TextSample"){var i={};i.start=c(f.getAttribute("sampleTime"));i.text=f.getAttribute("text");if(i.text){i.end=e-0.0010;h.push(b("subtitle",i))}e=
+i.start}f=f.previousSibling}n.data=h.reverse();return n})})(Popcorn);(function(r){function f(c){var b=c.split(":");c=c.length;var e;if(c!==12&&c!==9)throw"Bad cue";c=b.length-1;try{e=parseInt(b[c-1],10)*60+parseFloat(b[c],10);if(c===2)e+=parseInt(b[0],10)*3600}catch(h){throw"Bad cue";}return e}function n(c,b){var e={};e[c]=b;return e}r.parser("parseVTT",function(c){var b={title:"",remote:"",data:[]},e=[],h=0,i=0,j,p;c=c.text.split(/(?:\r\n|\r|\n)/gm);i=c.length;if(i===0||c[0]!=="WEBVTT")return b;for(h++;h<i;){j=[];try{for(var m=h;m<i&&!c[m];)m++;h=m;var o=c[h++];m=
+void 0;var q={};if(!o||o.indexOf("--\>")===-1)throw"Bad cue";m=o.replace(/--\>/," --\> ").split(/[\t ]+/);if(m.length<2)throw"Bad cue";q.id=o;q.start=f(m[0]);q.end=f(m[2]);for(p=q;h<i&&c[h];)j.push(c[h++]);p.text=j.join("<br />");e.push(n("subtitle",p))}catch(s){for(h=h;h<i&&c[h];)h++;h=h}}b.data=e;return b})})(Popcorn);(function(r){r.parser("parseXML","XML",function(f){var n={title:"",remote:"",data:[]},c={},b=function(m){m=m.split(":");if(m.length===1)return parseFloat(m[0],10);else if(m.length===2)return parseFloat(m[0],10)+parseFloat(m[1]/12,10);else if(m.length===3)return parseInt(m[0]*60,10)+parseFloat(m[1],10)+parseFloat(m[2]/12,10);else if(m.length===4)return parseInt(m[0]*3600,10)+parseInt(m[1]*60,10)+parseFloat(m[2],10)+parseFloat(m[3]/12,10)},e=function(m){for(var o={},q=0,s=m.length;q<s;q++){var d=m.item(q).nodeName,
+A=m.item(q).nodeValue,y=c[A];if(d==="in")o.start=b(A);else if(d==="out")o.end=b(A);else if(d==="resourceid")for(var x in y){if(y.hasOwnProperty(x))if(!o[x]&&x!=="id")o[x]=y[x]}else o[d]=A}return o},h=function(m,o){var q={};q[m]=o;return q},i=function(m,o,q){var s={};r.extend(s,o,e(m.attributes),{text:m.textContent||m.text});o=m.childNodes;if(o.length<1||o.length===1&&o[0].nodeType===3)if(q)c[s.id]=s;else n.data.push(h(m.nodeName,s));else for(m=0;m<o.length;m++)o[m].nodeType===1&&i(o[m],s,q)};f=f.documentElement.childNodes;
+for(var j=0,p=f.length;j<p;j++)if(f[j].nodeType===1)f[j].nodeName==="manifest"?i(f[j],{},true):i(f[j],{},false);return n})})(Popcorn);(function(){var r=false,f=false;Popcorn.player("soundcloud",{_canPlayType:function(n,c){return/(?:http:\/\/www\.|http:\/\/|www\.|\.|^)(soundcloud)/.test(c)&&n.toLowerCase()!=="video"},_setup:function(n){function c(){r=true;SC.initialize({client_id:"PRaNFlda6Bhf5utPjUsptg"});SC.get("/resolve",{url:e.src},function(A){e.width=e.style.width?""+e.offsetWidth:"560";e.height=e.style.height?""+e.offsetHeight:"315";h.scrolling="no";h.frameborder="no";h.id="soundcloud-"+Popcorn.guid();h.src="http://w.soundcloud.com/player/?url="+
+A.uri+"&show_artwork=false&buying=false&liking=false&sharing=false";h.width="100%";h.height="100%";n.loadListener=function(){n.widget=o=SC.Widget(h.id);o.bind(SC.Widget.Events.FINISH,function(){e.pause();e.dispatchEvent("ended")});o.bind(SC.Widget.Events.PLAY_PROGRESS,function(y){j=y.currentPosition/1E3;e.dispatchEvent("timeupdate")});o.bind(SC.Widget.Events.PLAY,function(){p=m=false;e.dispatchEvent("play");e.dispatchEvent("playing");e.currentTime=j;d.next()});o.bind(SC.Widget.Events.PAUSE,function(){p=
+m=true;e.dispatchEvent("pause");d.next()});o.bind(SC.Widget.Events.READY,function(){o.getDuration(function(y){q=y/1E3;e.style.visibility="visible";e.dispatchEvent("durationchange");e.readyState=4;e.dispatchEvent("readystatechange");e.dispatchEvent("loadedmetadata");e.dispatchEvent("loadeddata");e.dispatchEvent("canplaythrough");e.dispatchEvent("load");!e.paused&&e.play()});o.getVolume(function(y){i=y/100})})};h.addEventListener("load",n.loadListener,false);e.appendChild(h)})}function b(){if(f)(function A(){setTimeout(function(){r?
+c():A()},100)})();else{f=true;Popcorn.getScript("http://w.soundcloud.com/player/api.js",function(){Popcorn.getScript("http://connect.soundcloud.com/sdk.js",function(){c()})})}}var e=this,h=document.createElement("iframe"),i=1,j=0,p=true,m=true,o,q=0,s=false,d=Popcorn.player.playerQueue();n._container=h;e.style.visibility="hidden";e.play=function(){p=false;d.add(function(){if(m)o&&o.play();else d.next()})};e.pause=function(){p=true;d.add(function(){if(m)d.next();else o&&o.pause()})};Object.defineProperties(e,
+{muted:{set:function(A){if(A){o&&o.getVolume(function(y){i=y/100});o&&o.setVolume(0);s=true}else{o&&o.setVolume(i*100);s=false}e.dispatchEvent("volumechange")},get:function(){return s}},volume:{set:function(A){o&&o.setVolume(A*100);i=A;e.dispatchEvent("volumechange")},get:function(){return s?0:i}},currentTime:{set:function(A){j=A;o&&o.seekTo(A*1E3);e.dispatchEvent("seeked");e.dispatchEvent("timeupdate")},get:function(){return j}},duration:{get:function(){return q}},paused:{get:function(){return p}}});
+r?c():b()},_teardown:function(n){var c=n.widget,b=SC.Widget.Events,e=n._container;n.destroyed=true;if(c)for(var h in b)c&&c.unbind(b[h]);else e.removeEventListener("load",n.loadEventListener,false)}})})();(function(){function r(n){var c=r.options;n=c.parser[c.strictMode?"strict":"loose"].exec(n);for(var b={},e=14;e--;)b[c.key[e]]=n[e]||"";b[c.q.name]={};b[c.key[12]].replace(c.q.parser,function(h,i,j){if(i)b[c.q.name][i]=j});return b}function f(n,c){return/player.vimeo.com\/video\/\d+/.test(c)||/vimeo.com\/\d+/.test(c)}r.options={strictMode:false,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",
+parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}};Popcorn.player("vimeo",{_canPlayType:f,_setup:function(n){function c(l,k){var t=y.src.split("?")[0],u=JSON.stringify({method:l,
+value:k});if(t.substr(0,2)==="//")t=window.location.protocol+t;y.contentWindow?y.contentWindow.postMessage(u,t):o.unload()}function b(l){if(l.origin==="http://player.vimeo.com"){var k;try{k=JSON.parse(l.data)}catch(t){console.warn(t)}if(k.player_id==m){k.method&&a[k.method]&&a[k.method](k);k.event&&g[k.event]&&g[k.event](k)}}}function e(){d||(d=setInterval(function(){o.dispatchEvent("timeupdate")},i));s||(s=setInterval(function(){c("getCurrentTime")},j))}function h(){if(d){clearInterval(d);d=0}if(s){clearInterval(s);
+s=0}}var i=250,j=16,p={MEDIA_ERR_ABORTED:1,MEDIA_ERR_NETWORK:2,MEDIA_ERR_DECODE:3,MEDIA_ERR_SRC_NOT_SUPPORTED:4},m,o=this,q={q:[],queue:function(l){this.q.push(l);this.process()},process:function(){if(A)for(;this.q.length;)this.q.shift()()}},s,d,A,y=document.createElement("iframe"),x={error:null,src:o.src,NETWORK_EMPTY:0,NETWORK_IDLE:1,NETWORK_LOADING:2,NETWORK_NO_SOURCE:3,networkState:0,HAVE_NOTHING:0,HAVE_METADATA:1,HAVE_CURRENT_DATA:2,HAVE_FUTURE_DATA:3,HAVE_ENOUGH_DATA:4,readyState:0,seeking:false,
+currentTime:0,duration:NaN,paused:true,ended:false,autoplay:false,loop:false,volume:1,muted:false,width:0,height:0};Popcorn.forEach("error networkState readyState seeking duration paused ended".split(" "),function(l){Object.defineProperty(o,l,{get:function(){return x[l]}})});Object.defineProperties(o,{src:{get:function(){return x.src},set:function(l){x.src=l;o.load()}},currentTime:{get:function(){return x.currentTime},set:function(l){q.queue(function(){c("seekTo",l)});x.seeking=true;o.dispatchEvent("seeking")}},
+autoplay:{get:function(){return x.autoplay},set:function(l){x.autoplay=!!l}},loop:{get:function(){return x.loop},set:function(l){x.loop=!!l;q.queue(function(){c("setLoop",loop)})}},volume:{get:function(){return x.volume},set:function(l){x.volume=l;q.queue(function(){c("setVolume",x.muted?0:x.volume)});o.dispatchEvent("volumechange")}},muted:{get:function(){return x.muted},set:function(l){x.muted=!!l;q.queue(function(){c("setVolume",x.muted?0:x.volume)});o.dispatchEvent("volumechange")}},width:{get:function(){return y.width},
+set:function(l){y.width=l}},height:{get:function(){return y.height},set:function(l){y.height=l}}});var a={getCurrentTime:function(l){x.currentTime=parseFloat(l.value)},getDuration:function(l){x.duration=parseFloat(l.value);if(!isNaN(x.duration)){x.readyState=4;o.dispatchEvent("durationchange");o.dispatchEvent("loadedmetadata");o.dispatchEvent("loadeddata");o.dispatchEvent("canplay");o.dispatchEvent("canplaythrough")}},getVolume:function(l){x.volume=parseFloat(l.value)}},g={ready:function(){c("addEventListener",
+"loadProgress");c("addEventListener","playProgress");c("addEventListener","play");c("addEventListener","pause");c("addEventListener","finish");c("addEventListener","seek");c("getDuration");A=true;q.process();o.dispatchEvent("loadstart")},loadProgress:function(l){o.dispatchEvent("progress");x.duration=parseFloat(l.data.duration)},playProgress:function(l){x.currentTime=parseFloat(l.data.seconds)},play:function(){if(x.seeking){x.seeking=false;o.dispatchEvent("seeked")}x.paused=false;x.ended=false;e();
+o.dispatchEvent("play")},pause:function(){x.paused=true;h();o.dispatchEvent("pause")},finish:function(){x.ended=true;h();o.dispatchEvent("ended")},seek:function(l){x.currentTime=parseFloat(l.data.seconds);x.seeking=false;x.ended=false;o.dispatchEvent("timeupdate");o.dispatchEvent("seeked")}};o.load=function(){A=false;m=Popcorn.guid();var l=r(x.src),k={},t=[],u={api:1,player_id:m};if(f(o.nodeName,l.source)){Popcorn.extend(k,n);Popcorn.extend(k,l.queryKey);Popcorn.extend(k,u);l="http://player.vimeo.com/video/"+
+/\d+$/.exec(l.path)+"?";for(var v in k)k.hasOwnProperty(v)&&t.push(encodeURIComponent(v)+"="+encodeURIComponent(k[v]));l+=t.join("&");x.loop=!!l.match(/loop=1/);x.autoplay=!!l.match(/autoplay=1/);y.width=o.style.width?o.style.width:500;y.height=o.style.height?o.style.height:281;y.frameBorder=0;y.webkitAllowFullScreen=true;y.mozAllowFullScreen=true;y.allowFullScreen=true;y.src=l;o.appendChild(y)}else{l=x.MEDIA_ERR_SRC_NOT_SUPPORTED;x.error={};Popcorn.extend(x.error,p);x.error.code=l;o.dispatchEvent("error")}};
+o.unload=function(){h();window.removeEventListener("message",b,false)};o.play=function(){q.queue(function(){c("play")})};o.pause=function(){q.queue(function(){c("pause")})};setTimeout(function(){window.addEventListener("message",b,false);o.load()},0)},_teardown:function(){this.unload&&this.unload()}})})();(function(r,f){r.onYouTubePlayerAPIReady=function(){onYouTubePlayerAPIReady.ready=true;for(var c=0;c<onYouTubePlayerAPIReady.waiting.length;c++)onYouTubePlayerAPIReady.waiting[c]()};if(r.YT){r.quarantineYT=r.YT;r.YT=null}onYouTubePlayerAPIReady.waiting=[];var n=false;f.player("youtube",{_canPlayType:function(c,b){return typeof b==="string"&&/(?:http:\/\/www\.|http:\/\/|www\.|\.|^)(youtu)/.test(b)&&c.toLowerCase()!=="video"},_setup:function(c){if(!r.YT&&!n){n=true;f.getScript("//youtube.com/player_api")}var b=
+this,e=false,h=document.createElement("div"),i=0,j=true,p=false,m=0,o=false,q=100,s=f.player.playerQueue(),d=function(){f.player.defineProperty(b,"currentTime",{set:function(y){if(!c.destroyed){p=true;i=Math.round(+y*100)/100}},get:function(){return i}});f.player.defineProperty(b,"paused",{get:function(){return j}});f.player.defineProperty(b,"muted",{set:function(y){if(c.destroyed)return y;if(c.youtubeObject.isMuted()!==y){y?c.youtubeObject.mute():c.youtubeObject.unMute();o=c.youtubeObject.isMuted();
+b.dispatchEvent("volumechange")}return c.youtubeObject.isMuted()},get:function(){if(c.destroyed)return 0;return c.youtubeObject.isMuted()}});f.player.defineProperty(b,"volume",{set:function(y){if(c.destroyed)return y;if(c.youtubeObject.getVolume()/100!==y){c.youtubeObject.setVolume(y*100);q=c.youtubeObject.getVolume();b.dispatchEvent("volumechange")}return c.youtubeObject.getVolume()/100},get:function(){if(c.destroyed)return 0;return c.youtubeObject.getVolume()/100}});b.play=function(){if(!c.destroyed){j=
+false;s.add(function(){if(c.youtubeObject.getPlayerState()!==1){p=false;c.youtubeObject.playVideo()}else s.next()})}};b.pause=function(){if(!c.destroyed){j=true;s.add(function(){c.youtubeObject.getPlayerState()!==2?c.youtubeObject.pauseVideo():s.next()})}}};h.id=b.id+f.guid();c._container=h;b.appendChild(h);var A=function(){var y,x,a,g,l=true,k=function(){if(!c.destroyed){if(p)if(i===c.youtubeObject.getCurrentTime()){p=false;b.dispatchEvent("seeked");b.dispatchEvent("timeupdate")}else c.youtubeObject.seekTo(i);
+else{i=c.youtubeObject.getCurrentTime();b.dispatchEvent("timeupdate")}setTimeout(k,250)}},t=function(z){var C=c.youtubeObject.getDuration();if(isNaN(C)||C===0)setTimeout(function(){t(z*2)},z*1E3);else{b.duration=C;b.dispatchEvent("durationchange");b.dispatchEvent("loadedmetadata");b.dispatchEvent("loadeddata");b.readyState=4;k();b.dispatchEvent("canplaythrough")}};c.controls=+c.controls===0||+c.controls===1?c.controls:1;c.annotations=+c.annotations===1||+c.annotations===3?c.annotations:1;y=/^.*(?:\/|v=)(.{11})/.exec(b.src)[1];
+x=(b.src.split("?")[1]||"").replace(/v=.{11}/,"");x=x.replace(/&t=(?:(\d+)m)?(?:(\d+)s)?/,function(z,C,E){C|=0;E|=0;m=+E+C*60;return""});x=x.replace(/&start=(\d+)?/,function(z,C){C|=0;m=C;return""});e=/autoplay=1/.test(x);x=x.split(/[\&\?]/g);a={wmode:"transparent"};for(var u=0;u<x.length;u++){g=x[u].split("=");a[g[0]]=g[1]}c.youtubeObject=new YT.Player(h.id,{height:"100%",width:"100%",wmode:"transparent",playerVars:a,videoId:y,events:{onReady:function(){q=b.volume;o=b.muted;v();j=b.paused;d();c.youtubeObject.playVideo();
+b.currentTime=m},onStateChange:function(z){if(!(c.destroyed||z.data===-1))if(z.data===2){j=true;b.dispatchEvent("pause");s.next()}else if(z.data===1&&!l){j=false;b.dispatchEvent("play");b.dispatchEvent("playing");s.next()}else if(z.data===0)b.dispatchEvent("ended");else if(z.data===1&&l){l=false;if(e||!b.paused)j=false;j&&c.youtubeObject.pauseVideo();t(0.025)}},onError:function(z){if([2,100,101,150].indexOf(z.data)!==-1){b.error={customCode:z.data};b.dispatchEvent("error")}}}});var v=function(){if(!c.destroyed){if(o!==
+c.youtubeObject.isMuted()){o=c.youtubeObject.isMuted();b.dispatchEvent("volumechange")}if(q!==c.youtubeObject.getVolume()){q=c.youtubeObject.getVolume();b.dispatchEvent("volumechange")}setTimeout(v,250)}}};onYouTubePlayerAPIReady.ready?A():onYouTubePlayerAPIReady.waiting.push(A)},_teardown:function(c){c.destroyed=true;var b=c.youtubeObject;if(b){b.stopVideo();b.clearVideo&&b.clearVideo()}this.removeChild(document.getElementById(c._container.id))}})})(window,Popcorn);
diff --git a/record-and-playback/presentation/playback/presentation/lib/writing.js b/record-and-playback/presentation/playback/presentation/lib/writing.js
index 42dcf0920b771ecf7440f16dfb26ff7471d1a8c7..07563e33fd4b2100c726a1a71264346047be3a66 100755
--- a/record-and-playback/presentation/playback/presentation/lib/writing.js
+++ b/record-and-playback/presentation/playback/presentation/lib/writing.js
@@ -315,8 +315,10 @@ function runPopcorn() {
           else var thisimg = svgobj.getSVGDocument('svgfile').getElementById(current_image);
   
           var offsets = thisimg.getBoundingClientRect();
-          imageXOffset = (1600 - parseInt(thisimg.getAttribute("width"), 10))/2;
-          imageYOffset = (1200 - parseInt(thisimg.getAttribute("height"), 10))/2;
+          // Offsets divided by 4. By 2 because of the padding and by 2 again because 800x600 is half  1600x1200
+          imageXOffset = (1600 - parseInt(thisimg.getAttribute("width"), 10))/4;
+          imageYOffset = (1200 - parseInt(thisimg.getAttribute("height"), 10))/4;
+
           
           var vboxVal = getViewboxAtTime(t);
           if(vboxVal !== undefined) {
diff --git a/record-and-playback/presentation/scripts/publish/presentation.rb b/record-and-playback/presentation/scripts/publish/presentation.rb
index ebbbd504ea50d32a31b3db668bc11b65863f4797..87e4d6316d3ae897ceddf4e6ee4d110bfb6df274 100644
--- a/record-and-playback/presentation/scripts/publish/presentation.rb
+++ b/record-and-playback/presentation/scripts/publish/presentation.rb
@@ -155,7 +155,7 @@ def processClearEvents
 		$pageCleared = clearEvent.xpath(".//pageNumber")[0].text()
 		slideFolder = clearEvent.xpath(".//presentation")[0].text()
 		#$clearPageTimes[clearTime] = [$pageCleared, $canvas_number, "presentation/#{slideFolder}/slide-#{$pageCleared.to_i+1}.png", nil]
-		$clearPageTimes[($prev_clear_time..clearTime)] = [$pageCleared, $canvas_number, "presentation/#{slideFolder}/slide-#{$pageCleared.to_i+1}.png", nil]
+		$clearPageTimes[($prev_clear_time..clearTime)] = [$pageCleared, $canvas_number, "presentation/#{slideFolder}/slide-#{$pageCleared}.png", nil]
 		$prev_clear_time = clearTime
 		$canvas_number+=1
 	end
@@ -469,7 +469,7 @@ def processShapesAndClears
 			# Print out the gathered/detected images. 
 			$slides_compiled.each do |key, val|
 				$val = val
-				$xml.image(:id => "image#{$val[2].to_i}", :in => $val[0].join(' '), :out => $val[1].join(' '), 'xlink:href' => key[0], :height => key[1], :width => key[2], :visibility => :hidden, :text => $val[3])
+				$xml.image(:id => "image#{$val[2].to_i}", :in => $val[0].join(' '), :out => $val[1].join(' '), 'xlink:href' => key[0], :height => key[1], :width => key[2], :visibility => :hidden, :text => $val[3], :x => 0)
 				$canvas_number+=1
 				$xml.g(:class => :canvas, :id => "canvas#{$val[2].to_i}", :image => "image#{$val[2].to_i}", :display => :none) do
 					
@@ -792,3 +792,4 @@ end
 performance_end = Time.now
 
 
+