New implementaion of multiple connections
This implemetantion create a NetConnection when a webcam view is requested, when the connection is ready an event triggers the view window creation. Also, this implementation keep track of how many streams are using a connection, and if no one is using it anymore the connection is closed.
This commit is contained in:
parent
2870cacf8d
commit
660730fb01
@ -41,6 +41,7 @@ package org.bigbluebutton.modules.videoconf.business
|
||||
import org.bigbluebutton.modules.videoconf.events.ConnectedEvent;
|
||||
import org.bigbluebutton.modules.videoconf.events.StartBroadcastEvent;
|
||||
import org.bigbluebutton.modules.videoconf.model.VideoConfOptions;
|
||||
import org.bigbluebutton.modules.videoconf.events.PlayConnectionReady;
|
||||
|
||||
|
||||
public class VideoProxy
|
||||
@ -55,8 +56,12 @@ package org.bigbluebutton.modules.videoconf.business
|
||||
|
||||
// Dictionary<url,NetConnection> used for stream playing
|
||||
private var playConnectionDict:Dictionary;
|
||||
// Dictionary<url,int> used to keep track of how many streams use a URL
|
||||
private var playConnectionCountDict:Dictionary;
|
||||
// Dictionary<userID,streamNamePrefix> used for stream playing
|
||||
private var streamNamePrefixDict:Dictionary;
|
||||
// Dictionary<userID,url>
|
||||
private var userUrlDict:Dictionary;
|
||||
|
||||
private function parseOptions():void {
|
||||
videoOptions = new VideoConfOptions();
|
||||
@ -74,12 +79,15 @@ package org.bigbluebutton.modules.videoconf.business
|
||||
nc.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
|
||||
nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
|
||||
playConnectionDict = new Dictionary();
|
||||
playConnectionCountDict = new Dictionary();
|
||||
streamNamePrefixDict = new Dictionary();
|
||||
userUrlDict = new Dictionary();
|
||||
}
|
||||
|
||||
public function connect():void {
|
||||
nc.connect(_url);
|
||||
playConnectionDict[_url] = nc;
|
||||
playConnectionCountDict[_url] = 0;
|
||||
}
|
||||
|
||||
private function onAsyncError(event:AsyncErrorEvent):void{
|
||||
@ -96,6 +104,7 @@ package org.bigbluebutton.modules.videoconf.business
|
||||
private function onNetStatus(event:NetStatusEvent):void{
|
||||
switch(event.info.code){
|
||||
case "NetConnection.Connect.Success":
|
||||
ns = new NetStream(nc);
|
||||
onConnectedToVideoApp();
|
||||
break;
|
||||
default:
|
||||
@ -111,19 +120,36 @@ package org.bigbluebutton.modules.videoconf.business
|
||||
return this.nc;
|
||||
}
|
||||
|
||||
public function getPlayConnectionFor(userID:String):NetConnection{
|
||||
LogUtil.debug("VideoProxy::getPlayConnectionFor:: Looking for connection for stream from [" + userID + "]");
|
||||
private function onPlayNetStatus(event:NetStatusEvent):void {
|
||||
switch(event.info.code){
|
||||
case "NetConnection.Connect.Success":
|
||||
var dispatcher:Dispatcher = new Dispatcher();
|
||||
dispatcher.dispatchEvent(new PlayConnectionReady(PlayConnectionReady.PLAY_CONNECTION_READY));
|
||||
break;
|
||||
default:
|
||||
LogUtil.debug("[" + event.info.code + "] for a play connection");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function createPlayConnectionFor(userID:String):void {
|
||||
LogUtil.debug("VideoProxy::createPlayConnectionFor:: Creating connection for stream from [" + userID + "]");
|
||||
// TODO: Ask LB for path to current user
|
||||
var connectionPath:String = "10.0.3.203/10.0.3.254/10.0.3.79";
|
||||
var serverIp:String = connectionPath.split("/")[0];
|
||||
var ipRegex:RegExp = /([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/;
|
||||
var newUrl:String = _url.replace(ipRegex, serverIp);
|
||||
|
||||
// Store URL for this user
|
||||
userUrlDict[userID] = newUrl;
|
||||
|
||||
var streamPrefix:String;
|
||||
if(connectionPath != serverIp) // More than one server -> has prefix
|
||||
streamPrefix = connectionPath.replace(serverIp + "/", "") + "/";
|
||||
else
|
||||
streamPrefix = "";
|
||||
// Set current user streamPrefix to use the current path
|
||||
streamNamePrefixDict[userID] = streamPrefix;
|
||||
|
||||
// If connection with this URL does not exist
|
||||
if(!playConnectionDict[newUrl]){
|
||||
@ -131,20 +157,38 @@ package org.bigbluebutton.modules.videoconf.business
|
||||
var connection:NetConnection = new NetConnection();
|
||||
connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
|
||||
connection.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
|
||||
connection.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
|
||||
connection.addEventListener(NetStatusEvent.NET_STATUS, onPlayNetStatus);
|
||||
connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
|
||||
connection.connect(newUrl);
|
||||
// TODO change to trace
|
||||
LogUtil.debug("VideoProxy::getPlayConnectionFor:: Creating NetConnection for [" + newUrl + "]");
|
||||
LogUtil.debug("VideoProxy::createPlayConnectionFor:: Creating NetConnection for [" + newUrl + "]");
|
||||
playConnectionDict[newUrl] = connection;
|
||||
playConnectionCountDict[newUrl] = 0;
|
||||
}
|
||||
else {
|
||||
if(playConnectionDict[newUrl].connected) {
|
||||
// Connection is ready, send event
|
||||
var dispatcher:Dispatcher = new Dispatcher();
|
||||
dispatcher.dispatchEvent(new PlayConnectionReady(PlayConnectionReady.PLAY_CONNECTION_READY));
|
||||
}
|
||||
// TODO change to trace
|
||||
LogUtil.debug("VideoProxy::getPlayConnectionFor:: Found NetConnection for [" + newUrl + "]");
|
||||
LogUtil.debug("VideoProxy::createPlayConnectionFor:: Found NetConnection for [" + newUrl + "]");
|
||||
}
|
||||
// Set current user streamPrefix to use the current path
|
||||
streamNamePrefixDict[userID] = streamPrefix;
|
||||
return playConnectionDict[newUrl];
|
||||
}
|
||||
|
||||
public function playConnectionIsReadyFor(userID:String):Boolean {
|
||||
var userUrl:String = userUrlDict[userID];
|
||||
if(playConnectionDict[userUrl].connected)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getPlayConnectionFor(userID:String):NetConnection {
|
||||
var userUrl:String = userUrlDict[userID];
|
||||
playConnectionCountDict[userUrl] = playConnectionCountDict[userUrl] + 1;
|
||||
// TODO: change to trace
|
||||
LogUtil.debug("VideoProxy:: getPlayConnection:: URL: [" + userUrl + "], count: [" + playConnectionCountDict[userUrl] + "]");
|
||||
return playConnectionDict[userUrl];
|
||||
}
|
||||
|
||||
public function getStreamNamePrefixFor(userID:String):String{
|
||||
@ -159,8 +203,27 @@ package org.bigbluebutton.modules.videoconf.business
|
||||
}
|
||||
}
|
||||
|
||||
public function closePlayConnectionFor(userID:String):void {
|
||||
var userUrl:String = userUrlDict[userID];
|
||||
// Do not close publish connection, no matter what
|
||||
if(playConnectionDict[userUrl] == nc)
|
||||
return;
|
||||
if(userUrl != null) {
|
||||
var count:int = playConnectionCountDict[userUrl] - 1;
|
||||
// TODO: change to trace
|
||||
LogUtil.debug("VideoProxy:: closePlayConnectionFor:: userID: [" + userID + "], URL: [" + userUrl + "], new streamCount: [" + count + "]");
|
||||
playConnectionCountDict[userUrl] = count;
|
||||
if(count <= 0) {
|
||||
// No one else is using this NetConnection
|
||||
var connection:NetConnection = playConnectionDict[userUrl];
|
||||
if(connection != null) connection.close();
|
||||
delete playConnectionDict[userUrl];
|
||||
delete playConnectionCountDict[userUrl];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function startPublishing(e:StartBroadcastEvent):void{
|
||||
ns = new NetStream(nc);
|
||||
ns.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
|
||||
ns.addEventListener( IOErrorEvent.IO_ERROR, onIOError );
|
||||
ns.addEventListener( AsyncErrorEvent.ASYNC_ERROR, onAsyncError );
|
||||
@ -227,14 +290,25 @@ package org.bigbluebutton.modules.videoconf.business
|
||||
ns.attachCamera(null);
|
||||
ns.close();
|
||||
ns = null;
|
||||
}
|
||||
ns = new NetStream(nc);
|
||||
}
|
||||
}
|
||||
|
||||
public function disconnect():void {
|
||||
LogUtil.debug("VideoProxy:: disconnecting from Video application");
|
||||
stopBroadcasting();
|
||||
// Close publish NetConnection
|
||||
if (nc != null) nc.close();
|
||||
//TODO: Close play NetConnections
|
||||
// Close play NetConnections
|
||||
for (var k:Object in playConnectionDict) {
|
||||
var connection:NetConnection = playConnectionDict[k];
|
||||
connection.close();
|
||||
}
|
||||
// Reset dictionaries
|
||||
playConnectionDict = new Dictionary();
|
||||
playConnectionCountDict = new Dictionary();
|
||||
streamNamePrefixDict = new Dictionary();
|
||||
userUrlDict = new Dictionary();
|
||||
}
|
||||
|
||||
public function onBWCheck(... rest):Number {
|
||||
|
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||
*
|
||||
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along
|
||||
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package org.bigbluebutton.modules.videoconf.events
|
||||
{
|
||||
import flash.events.Event;
|
||||
|
||||
public class PlayConnectionReady extends Event
|
||||
{
|
||||
public static const PLAY_CONNECTION_READY:String = "a netconnetion is ready";
|
||||
|
||||
public function PlayConnectionReady(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
|
||||
{
|
||||
super(type, bubbles, cancelable);
|
||||
}
|
||||
}
|
||||
}
|
@ -38,6 +38,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
import org.bigbluebutton.modules.videoconf.events.VideoModuleStartEvent;
|
||||
import org.bigbluebutton.modules.videoconf.events.VideoModuleStopEvent;
|
||||
import org.bigbluebutton.modules.users.events.ViewCameraEvent;
|
||||
import org.bigbluebutton.modules.videoconf.events.PlayConnectionReady;
|
||||
]]>
|
||||
</mx:Script>
|
||||
|
||||
@ -115,6 +116,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
<MethodInvoker generator="{VideoEventMapDelegate}" method="handleCamSettingsClosedEvent" arguments="{event}"/>
|
||||
</EventHandlers>
|
||||
|
||||
<EventHandlers type="{PlayConnectionReady.PLAY_CONNECTION_READY}">
|
||||
<MethodInvoker generator="{VideoEventMapDelegate}" method="handlePlayConnectionReady" />
|
||||
</EventHandlers>
|
||||
<!-- ~~~~~~~~~~~~~~~~~~ INJECTORS ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
</EventMap>
|
||||
|
@ -20,7 +20,6 @@ package org.bigbluebutton.modules.videoconf.maps
|
||||
{
|
||||
import flash.events.IEventDispatcher;
|
||||
import flash.media.Camera;
|
||||
import flash.net.NetConnection;
|
||||
|
||||
import mx.collections.ArrayCollection;
|
||||
|
||||
@ -56,6 +55,7 @@ package org.bigbluebutton.modules.videoconf.maps
|
||||
import org.bigbluebutton.modules.videoconf.views.ToolbarButton;
|
||||
import org.bigbluebutton.modules.videoconf.views.VideoWindow;
|
||||
import org.flexunit.runner.manipulation.filters.IncludeAllFilter;
|
||||
import org.bigbluebutton.modules.videoconf.events.PlayConnectionReady;
|
||||
|
||||
public class VideoEventMapDelegate
|
||||
{
|
||||
@ -73,6 +73,9 @@ package org.bigbluebutton.modules.videoconf.maps
|
||||
private var _isPublishing:Boolean = false;
|
||||
private var _isPreviewWebcamOpen:Boolean = false;
|
||||
private var _isWaitingActivation:Boolean = false;
|
||||
|
||||
// Store userID of windows waiting for a NetConnection
|
||||
private var pendingVideoWindowsList:Object = new Object();
|
||||
|
||||
public function VideoEventMapDelegate(dispatcher:IEventDispatcher)
|
||||
{
|
||||
@ -94,7 +97,7 @@ package org.bigbluebutton.modules.videoconf.maps
|
||||
if (!_ready) return;
|
||||
LogUtil.debug("VideoEventMapDelegate:: [" + me + "] Viewing [" + userID + " stream [" + stream + "]");
|
||||
if (! UserManager.getInstance().getConference().amIThisUser(userID)) {
|
||||
openViewWindowFor(userID);
|
||||
initPlayConnectionFor(userID);
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,7 +217,7 @@ package org.bigbluebutton.modules.videoconf.maps
|
||||
closeWindow(userID);
|
||||
}
|
||||
LogUtil.debug("VideoEventMapDelegate:: [" + me + "] openWebcamWindowFor:: View user's = [" + userID + "] webcam.");
|
||||
openViewWindowFor(userID);
|
||||
initPlayConnectionFor(userID);
|
||||
} else {
|
||||
if (UsersUtil.isMe(userID) && options.autoStart) {
|
||||
LogUtil.debug("VideoEventMapDelegate:: [" + me + "] openWebcamWindowFor:: It's ME and AutoStart. Start publishing.");
|
||||
@ -280,6 +283,7 @@ package org.bigbluebutton.modules.videoconf.maps
|
||||
if (win != null) {
|
||||
LogUtil.debug("VideoEventMapDelegate:: [" + me + "] closeWindow:: Closing [" + win.getWindowType() + "] for [" + userID + "] [" + UsersUtil.getUserName(userID) + "]");
|
||||
win.close();
|
||||
proxy.closePlayConnectionFor(userID);
|
||||
var cwe:CloseWindowEvent = new CloseWindowEvent();
|
||||
cwe.window = win;
|
||||
_dispatcher.dispatchEvent(cwe);
|
||||
@ -288,34 +292,45 @@ package org.bigbluebutton.modules.videoconf.maps
|
||||
}
|
||||
}
|
||||
|
||||
private function openViewWindowFor(userID:String):void {
|
||||
LogUtil.debug("VideoEventMapDelegate:: [" + me + "] openViewWindowFor:: Opening VIEW window for [" + userID + "] [" + UsersUtil.getUserName(userID) + "]");
|
||||
|
||||
// Check if NetConnection is ready
|
||||
var playConnection:NetConnection = proxy.getPlayConnectionFor(userID);
|
||||
if (playConnection.connected) {
|
||||
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);
|
||||
var playStream:String = proxy.getStreamNamePrefixFor(userID) + bbbUser.streamName;
|
||||
LogUtil.debug("VideoEventMapDelegate:: [" + me + "] openViewWindowFor:: StreamName for [" + userID + "] : [" + playStream + "]");
|
||||
window.startVideo(playConnection, playStream);
|
||||
|
||||
webcamWindows.addWindow(window);
|
||||
openWindow(window);
|
||||
dockWindow(window);
|
||||
}
|
||||
else {
|
||||
LogUtil.debug("VideoEventMapDelegate:: [" + me + "] openViewWindowFor:: NetConnection for [" + userID + "] isn't ready yet.");
|
||||
}
|
||||
private function initPlayConnectionFor(userID:String):void {
|
||||
//TODO: Change to trace
|
||||
LogUtil.debug("VideoEventMapDelegate:: initPlayConnectionFor : [" + userID + "]");
|
||||
// Store the userID
|
||||
pendingVideoWindowsList[userID] = true;
|
||||
// Request the connection
|
||||
proxy.createPlayConnectionFor(userID);
|
||||
}
|
||||
|
||||
public function handlePlayConnectionReady():void {
|
||||
// Iterate through all pending windows
|
||||
for(var userID:String in pendingVideoWindowsList) {
|
||||
if(proxy.playConnectionIsReadyFor(userID)) {
|
||||
delete pendingVideoWindowsList[userID];
|
||||
openViewWindowFor(userID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function openViewWindowFor(userID:String):void {
|
||||
LogUtil.debug("VideoEventMapDelegate:: [" + 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);
|
||||
var streamName:String = proxy.getStreamNamePrefixFor(userID) + bbbUser.streamName;
|
||||
window.startVideo(proxy.getPlayConnectionFor(userID), 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;
|
||||
|
Loading…
Reference in New Issue
Block a user