bigbluebutton-Github/bigbluebutton-client/src/ScreenshareStandalone.mxml
2017-05-29 13:58:18 +01:00

361 lines
14 KiB
XML
Executable File

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