- broadcast messages to other clients without using shared object

This commit is contained in:
Richard Alam 2012-07-13 20:30:32 +00:00
parent 5b55b6930b
commit 45faed3019
7 changed files with 122 additions and 118 deletions

View File

@ -71,6 +71,7 @@ public class ConnectionInvokerService {
IScope scope = scopes.get(message.getDest()); IScope scope = scopes.get(message.getDest());
if (scope != null) { if (scope != null) {
List<Object> params = new ArrayList<Object>(); List<Object> params = new ArrayList<Object>();
params.add(message.getMessageName());
params.add(message.getMessage()); params.add(message.getMessage());
ServiceUtils.invokeOnAllConnections(scope, "onMessageFromServer", params.toArray()); ServiceUtils.invokeOnAllConnections(scope, "onMessageFromServer", params.toArray());
} }

View File

@ -1,15 +1,11 @@
package org.bigbluebutton.conference.service.recorder.whiteboard; package org.bigbluebutton.conference.service.recorder.whiteboard;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.bigbluebutton.conference.service.recorder.Recorder;
import org.bigbluebutton.conference.service.recorder.RecorderApplication; import org.bigbluebutton.conference.service.recorder.RecorderApplication;
import org.red5.logging.Red5LoggerFactory; import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.bigbluebutton.conference.service.whiteboard.IWhiteboardRoomListener; import org.bigbluebutton.conference.service.whiteboard.IWhiteboardRoomListener;
import org.bigbluebutton.conference.service.whiteboard.Presentation; import org.bigbluebutton.conference.service.whiteboard.Presentation;
import org.bigbluebutton.conference.service.whiteboard.Shape;
public class WhiteboardEventRecorder implements IWhiteboardRoomListener{ public class WhiteboardEventRecorder implements IWhiteboardRoomListener{
private static Logger log = Red5LoggerFactory.getLogger( WhiteboardEventRecorder.class, "bigbluebutton" ); private static Logger log = Red5LoggerFactory.getLogger( WhiteboardEventRecorder.class, "bigbluebutton" );

View File

@ -25,12 +25,10 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.bigbluebutton.conference.BigBlueButtonSession; import org.bigbluebutton.conference.BigBlueButtonSession;
import org.bigbluebutton.conference.ClientMessage; import org.bigbluebutton.conference.ClientMessage;
import org.bigbluebutton.conference.ConnectionInvokerService; import org.bigbluebutton.conference.ConnectionInvokerService;
import org.bigbluebutton.conference.Constants; import org.bigbluebutton.conference.Constants;
import org.red5.compatibility.flex.messaging.io.ArrayCollection;
import org.red5.logging.Red5LoggerFactory; import org.red5.logging.Red5LoggerFactory;
import org.red5.server.adapter.IApplication; import org.red5.server.adapter.IApplication;
import org.red5.server.adapter.MultiThreadedApplicationAdapter; import org.red5.server.adapter.MultiThreadedApplicationAdapter;
@ -55,22 +53,22 @@ public class WhiteboardApplication extends MultiThreadedApplicationAdapter imple
private ConnectionInvokerService connInvokerService; private ConnectionInvokerService connInvokerService;
@Override @Override
public boolean appStart(IScope app){ public boolean appStart(IScope app) {
log.info("Starting Whiteboard Application"); log.info("Starting Whiteboard Application");
this.scope = app; this.scope = app;
return true; return true;
} }
public void setRoomManager(WhiteboardRoomManager manager){ public void setRoomManager(WhiteboardRoomManager manager) {
this.roomManager = manager; this.roomManager = manager;
} }
@Override @Override
public void appStop(IScope scope){ public void appStop(IScope scope) {
roomManager.removeRoom(getLocalScope().getName()); roomManager.removeRoom(getLocalScope().getName());
} }
public void setActivePresentation(String name, int numPages){ public void setActivePresentation(String name, int numPages) {
WhiteboardRoom room = roomManager.getRoom(getLocalScope().getName()); WhiteboardRoom room = roomManager.getRoom(getLocalScope().getName());
if (room.presentationExists(name)) { if (room.presentationExists(name)) {
room.setActivePresentation(name); room.setActivePresentation(name);
@ -79,62 +77,62 @@ public class WhiteboardApplication extends MultiThreadedApplicationAdapter imple
} }
} }
public void enableWhiteboard(boolean enabled){ public void enableWhiteboard(boolean enabled) {
roomManager.getRoom(getLocalScope().getName()).setWhiteboardEnabled(enabled); roomManager.getRoom(getLocalScope().getName()).setWhiteboardEnabled(enabled);
ISharedObject drawSO = getSharedObject(getLocalScope(), WHITEBOARD_SHARED_OBJECT); // ISharedObject drawSO = getSharedObject(getLocalScope(), WHITEBOARD_SHARED_OBJECT);
List<Boolean> arguments = new ArrayList<Boolean>(); // List<Boolean> arguments = new ArrayList<Boolean>();
arguments.add(enabled); // arguments.add(enabled);
drawSO.sendMessage("modifyEnabledCallback", arguments); // drawSO.sendMessage("modifyEnabledCallback", arguments);
}
public boolean isWhiteboardEnabled(){
return roomManager.getRoom(getLocalScope().getName()).isWhiteboardEnabled();
}
public void sendAnnotationHistory(String userid) {
Map<String, Object> message = new HashMap<String, Object>(); Map<String, Object> message = new HashMap<String, Object>();
message.put("type", "pencil"); message.put("enabled", roomManager.getRoom(getLocalScope().getName()).isWhiteboardEnabled());
ClientMessage m = new ClientMessage(ClientMessage.BROADCAST, getLocalScope().getName(), "EnableWhiteboardCommand", message);
ClientMessage m = new ClientMessage(ClientMessage.DIRECT, userid, "receiveAnnotationHistory", message);
connInvokerService.sendMessage(m); connInvokerService.sendMessage(m);
} }
/* public void isWhiteboardEnabled(String userid) {
public void sendShape(double[] shape, String type, int color, int thickness, String id, String status){ Map<String, Object> message = new HashMap<String, Object>();
Shape newShape = new Shape(shape, type, color, thickness, id, status); message.put("enabled", roomManager.getRoom(getLocalScope().getName()).isWhiteboardEnabled());
roomManager.getRoom(getLocalScope().getName()).addShape(newShape); ClientMessage m = new ClientMessage(ClientMessage.DIRECT, userid, "IsWhiteboardEnabledReply", message);
ISharedObject drawSO = getSharedObject(getLocalScope(), WHITEBOARD_SHARED_OBJECT); connInvokerService.sendMessage(m);
List<Object> arguments = newShape.toList();
drawSO.sendMessage("addSegment", arguments);
} }
*/
public void sendAnnotation(Map<String, Object> annotation) { public void sendAnnotationHistory(String userid) {
ISharedObject drawSO = getSharedObject(getLocalScope(), WHITEBOARD_SHARED_OBJECT); Map<String, Object> message = new HashMap<String, Object>();
roomManager.getRoom(getLocalScope().getName()).addAnnotation(annotation); List<Map<String, Object>> annotations = roomManager.getRoom(getLocalScope().getName()).getAnnotations();
List<Object> arguments = new ArrayList<Object>(); message.put("count", new Integer(annotations.size()));
arguments.add(annotation); message.put("annotations", annotations);
drawSO.sendMessage("receiveAnnotation", arguments); ClientMessage m = new ClientMessage(ClientMessage.DIRECT, userid, "RequestAnnotationHistoryReply", message);
connInvokerService.sendMessage(m);
} }
public int getNumShapesOnPage(int pageNum){ public void sendAnnotation(Map<String, Object> annotation) {
// ISharedObject drawSO = getSharedObject(getLocalScope(), WHITEBOARD_SHARED_OBJECT);
// roomManager.getRoom(getLocalScope().getName()).addAnnotation(annotation);
// List<Object> arguments = new ArrayList<Object>();
// arguments.add(annotation);
// drawSO.sendMessage("receiveAnnotation", arguments);
Map<String, Object> message = new HashMap<String, Object>();
roomManager.getRoom(getLocalScope().getName()).addAnnotation(annotation);
message.put("annotation", annotation);
ClientMessage m = new ClientMessage(ClientMessage.BROADCAST, getLocalScope().getName(), "NewAnnotationCommand", annotation);
connInvokerService.sendMessage(m);
}
public int getNumShapesOnPage(int pageNum) {
Presentation pres = roomManager.getRoom(getLocalScope().getName()).getActivePresentation(); Presentation pres = roomManager.getRoom(getLocalScope().getName()).getActivePresentation();
pres.setActivePage(pageNum); pres.setActivePage(pageNum);
return pres.getActivePage().getNumShapesOnPage(); return pres.getActivePage().getNumShapesOnPage();
} }
public List<Map<String, Object>> getShapes(){
List<Map<String, Object>> shapesList = roomManager.getRoom(getLocalScope().getName()).getShapes();
return shapesList; public void clear() {
}
public void clear(){
roomManager.getRoom(getLocalScope().getName()).clear(); roomManager.getRoom(getLocalScope().getName()).clear();
ISharedObject drawSO = getSharedObject(getLocalScope(), WHITEBOARD_SHARED_OBJECT); ISharedObject drawSO = getSharedObject(getLocalScope(), WHITEBOARD_SHARED_OBJECT);
drawSO.sendMessage("clear", new ArrayList<Object>()); drawSO.sendMessage("clear", new ArrayList<Object>());
} }
public void undo(){ public void undo() {
roomManager.getRoom(getLocalScope().getName()).undo(); roomManager.getRoom(getLocalScope().getName()).undo();
ISharedObject drawSO = getSharedObject(getLocalScope(), WHITEBOARD_SHARED_OBJECT); ISharedObject drawSO = getSharedObject(getLocalScope(), WHITEBOARD_SHARED_OBJECT);
drawSO.sendMessage("undo", new ArrayList<Object>()); drawSO.sendMessage("undo", new ArrayList<Object>());

View File

@ -26,9 +26,6 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.bigbluebutton.conference.service.chat.IChatRoomListener;
import org.red5.compatibility.flex.messaging.io.ArrayCollection;
import org.red5.server.api.IScope; import org.red5.server.api.IScope;
public class WhiteboardRoom { public class WhiteboardRoom {
@ -50,6 +47,7 @@ public class WhiteboardRoom {
public IScope getScope(){ public IScope getScope(){
return this.scope; return this.scope;
} }
/** /**
* Add a new presentation. Will also set the activePresentation * Add a new presentation. Will also set the activePresentation
@ -97,7 +95,7 @@ public class WhiteboardRoom {
notifyAddShape(activePresentation, annotation); notifyAddShape(activePresentation, annotation);
} }
public List<Map<String, Object>> getShapes(){ public List<Map<String, Object>> getAnnotations(){
return activePresentation.getActivePage().getShapes(); return activePresentation.getActivePage().getShapes();
} }

View File

@ -22,10 +22,7 @@
package org.bigbluebutton.conference.service.whiteboard; package org.bigbluebutton.conference.service.whiteboard;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.red5.compatibility.flex.messaging.io.ArrayCollection;
import org.red5.logging.Red5LoggerFactory; import org.red5.logging.Red5LoggerFactory;
import org.red5.server.api.Red5; import org.red5.server.api.Red5;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -47,18 +44,18 @@ public class WhiteboardService {
} }
public void sendAnnotation(Map<String, Object> annotation) { public void sendAnnotation(Map<String, Object> annotation) {
for (Map.Entry<String, Object> entry : annotation.entrySet()) { // for (Map.Entry<String, Object> entry : annotation.entrySet()) {
String key = entry.getKey(); // String key = entry.getKey();
Object value = entry.getValue(); // Object value = entry.getValue();
if (key.equals("points")) { // if (key.equals("points")) {
String points = "points=["; // String points = "points=[";
ArrayList<Double> v = (ArrayList<Double>) value; // ArrayList<Double> v = (ArrayList<Double>) value;
log.debug(points + pointsToString(v) + "]"); // log.debug(points + pointsToString(v) + "]");
} else { // } else {
log.debug(key + "=[" + value + "]"); // log.debug(key + "=[" + value + "]");
} // }
} // }
application.sendAnnotation(annotation); application.sendAnnotation(annotation);
} }
@ -69,7 +66,7 @@ public class WhiteboardService {
datapoints += i + ","; datapoints += i + ",";
} }
// Trim the trailing comma // Trim the trailing comma
log.debug("Data Point = " + datapoints); // log.debug("Data Point = " + datapoints);
return datapoints.substring(0, datapoints.length() - 1); return datapoints.substring(0, datapoints.length() - 1);
} }
@ -84,23 +81,9 @@ public class WhiteboardService {
return 1; //application.getNumShapesOnPage(pageNum); return 1; //application.getNumShapesOnPage(pageNum);
} }
//public List<Map<String, Object>> getShapes(){ public void requestAnnotationHistory() {
public void getShapes(){ log.info("WhiteboardApplication - requestAnnotationHistory");
log.info("WhiteboardApplication - Returning shapes");
List<Map<String, Object>> shapes = application.getShapes();
application.sendAnnotationHistory(Red5.getConnectionLocal().getClient().getId()); application.sendAnnotationHistory(Red5.getConnectionLocal().getClient().getId());
/*System.out.println("Number of shapes: " + shapes.size());
System.out.println("First shape. Num params: " + shapes.get(0).length);
System.out.println("double[] : " + (double[])shapes.get(0)[0]);
System.out.println("type : " + shapes.get(0)[1]);
System.out.println("color : " + shapes.get(0)[2]);
System.out.println("thickness : " + shapes.get(0)[3]);
System.out.println("parentWidth : " + shapes.get(0)[4]);
System.out.println("parentHeight : " + shapes.get(0)[5]);*/
//return shapes;
} }
public void clear(){ public void clear(){
@ -123,8 +106,8 @@ public class WhiteboardService {
application.enableWhiteboard(enable); application.enableWhiteboard(enable);
} }
public boolean isWhiteboardEnabled(){ public void isWhiteboardEnabled(){
return application.isWhiteboardEnabled(); application.isWhiteboardEnabled(Red5.getConnectionLocal().getClient().getId());
} }
} }

View File

@ -102,7 +102,49 @@ package org.bigbluebutton.modules.whiteboard.business
public function onMessage(messageName:String, message:Object):void { public function onMessage(messageName:String, message:Object):void {
LogUtil.debug("WB: received message " + messageName); LogUtil.debug("WB: received message " + messageName);
switch (messageName) {
case "RequestAnnotationHistoryReply":
handleRequestAnnotationHistoryReply(message);
break;
case "IsWhiteboardEnabledReply":
handleIsWhiteboardEnabledReply(message);
break;
case "EnableWhiteboardCommand":
handleEnableWhiteboardCommand(message);
break;
case "NewAnnotationCommand":
handleNewAnnotationCommand(message);
break;
default:
LogUtil.warn("Cannot handle message [" + messageName + "]");
}
} }
private function handleEnableWhiteboardCommand(message:Object):void {
//if (result as Boolean) modifyEnabledCallback(true);
LogUtil.debug("Handle Whiteboard Enabled Command " + message.enabled);
}
private function handleNewAnnotationCommand(message:Object):void {
LogUtil.debug("Handle new annotation[" + message.type + ", " + message.id + ", " + message.status + "]");
}
private function handleIsWhiteboardEnabledReply(message:Object):void {
//if (result as Boolean) modifyEnabledCallback(true);
LogUtil.debug("Whiteboard Enabled? " + message.enabled);
}
private function handleRequestAnnotationHistoryReply(message:Object):void {
if (message.count == 0) {
LogUtil.debug("No annotations.");
} else {
LogUtil.debug("Number of annotations in history = " + message.count);
}
}
/** /**
* Once a shared object is created, it is synced accross all clients, and this method is invoked * Once a shared object is created, it is synced accross all clients, and this method is invoked
@ -134,7 +176,7 @@ package org.bigbluebutton.modules.whiteboard.business
); //_netConnection.call ); //_netConnection.call
} }
public function checkIsWhiteboardOn():void{ public function checkIsWhiteboardOn():void {
var nc:NetConnection = connection; var nc:NetConnection = connection;
nc.call( nc.call(
"whiteboard.isWhiteboardEnabled",// Remote function name "whiteboard.isWhiteboardEnabled",// Remote function name
@ -142,7 +184,7 @@ package org.bigbluebutton.modules.whiteboard.business
// On successful result // On successful result
function(result:Object):void { function(result:Object):void {
LogUtil.debug("Whiteboard::checkIsWhiteboardOn() : " + result as String); LogUtil.debug("Whiteboard::checkIsWhiteboardOn() : " + result as String);
if (result as Boolean) modifyEnabledCallback(true); // if (result as Boolean) modifyEnabledCallback(true);
}, },
// status - On error occurred // status - On error occurred
function(status:Object):void { function(status:Object):void {
@ -156,24 +198,21 @@ package org.bigbluebutton.modules.whiteboard.business
); //_netConnection.call ); //_netConnection.call
} }
public function getPageHistory(e:PageEvent):void{ public function getPageHistory(e:PageEvent):void {
var nc:NetConnection = connection; var nc:NetConnection = connection;
nc.call( nc.call("whiteboard.setActivePage",
"whiteboard.setActivePage",// Remote function name new Responder(
new Responder( function(result:Object):void { // On successful result
// On successful result
function(result:Object):void {
if ((result as int) != e.shapes.length) { if ((result as int) != e.shapes.length) {
LogUtil.debug("Whiteboard: Need to retrieve shapes. Have " + e.shapes.length + " on client, " LogUtil.debug("Whiteboard: Need to retrieve shapes. Have " + e.shapes.length + " on client, " + (result as int) + " on server");
+ (result as int) + " on server");
LogUtil.debug("Whiteboard: Retrieving shapes on page" + e.pageNum); LogUtil.debug("Whiteboard: Retrieving shapes on page" + e.pageNum);
getHistory(); getHistory();
} else{ } else{
LogUtil.debug("Whiteboard: Shapes up to date, no need to update"); LogUtil.debug("Whiteboard: Shapes up to date, no need to update");
} }
}, },
// status - On error occurred
function(status:Object):void { function(status:Object):void { // status - On error occurred
LogUtil.error("Error occurred: Whiteboard::DrawProxy::getPageHistory()"); LogUtil.error("Error occurred: Whiteboard::DrawProxy::getPageHistory()");
for (var x:Object in status) { for (var x:Object in status) {
LogUtil.error(x + " : " + status[x]); LogUtil.error(x + " : " + status[x]);
@ -254,13 +293,7 @@ package org.bigbluebutton.modules.whiteboard.business
dispatcher.dispatchEvent(e); dispatcher.dispatchEvent(e);
} }
public function receiveAnnotation(annotation:Object):void {
for(var id:String in annotation) {
var value:Object = annotation[id];
LogUtil.debug(id + " = " + value);
}
}
/** /**
* Sends a call out to the red5 server to notify the clients that the board needs to be cleared * Sends a call out to the red5 server to notify the clients that the board needs to be cleared
@ -362,7 +395,7 @@ package org.bigbluebutton.modules.whiteboard.business
private function getHistory():void{ private function getHistory():void{
var nc:NetConnection = connection; var nc:NetConnection = connection;
nc.call( nc.call(
"whiteboard.getShapes",// Remote function name "whiteboard.requestAnnotationHistory",// Remote function name
new Responder( new Responder(
// On successful result // On successful result
function(result:Object):void { function(result:Object):void {
@ -381,10 +414,6 @@ package org.bigbluebutton.modules.whiteboard.business
); //_netConnection.call ); //_netConnection.call
} }
public function receiveAnnotationHistory(result:Object):void {
LogUtil.debug("Got annotation history");
}
private function receivedShapesHistory(result:Object):void{ private function receivedShapesHistory(result:Object):void{
if (result == null) return; if (result == null) return;

View File

@ -33,8 +33,7 @@ package org.bigbluebutton.modules.whiteboard.managers
public class PageManager public class PageManager
{ {
private var pageNum:int; private var pageNum:int;
private var pages:ArrayCollection; private var pages:ArrayCollection;
private var dispatcher:Dispatcher; private var dispatcher:Dispatcher;
public function PageManager() public function PageManager()
@ -44,21 +43,21 @@ package org.bigbluebutton.modules.whiteboard.managers
dispatcher = new Dispatcher(); dispatcher = new Dispatcher();
} }
public function addShapeToPage(e:WhiteboardUpdate):void{ public function addShapeToPage(e:WhiteboardUpdate):void {
(pages.getItemAt(pageNum) as ArrayCollection).addItem(e.data); (pages.getItemAt(pageNum) as ArrayCollection).addItem(e.data);
} }
public function undoShapeFromPage():void{ public function undoShapeFromPage():void {
var page:ArrayCollection = pages.getItemAt(pageNum) as ArrayCollection; var page:ArrayCollection = pages.getItemAt(pageNum) as ArrayCollection;
if (page.length > 0) page.removeItemAt(page.length - 1); if (page.length > 0) page.removeItemAt(page.length - 1);
} }
public function clearPage():void{ public function clearPage():void {
var page:ArrayCollection = pages.getItemAt(pageNum) as ArrayCollection; var page:ArrayCollection = pages.getItemAt(pageNum) as ArrayCollection;
page.removeAll(); page.removeAll();
} }
public function loadPage(e:PageEvent):void{ public function loadPage(e:PageEvent):void {
if (pages.length ==0 ) return; if (pages.length ==0 ) return;
if ((pages.getItemAt(e.pageNum) as ArrayCollection).length == 0) return; if ((pages.getItemAt(e.pageNum) as ArrayCollection).length == 0) return;
@ -67,15 +66,15 @@ package org.bigbluebutton.modules.whiteboard.managers
timer.start(); timer.start();
} }
private function defferedLoad(e:TimerEvent):void{ private function defferedLoad(e:TimerEvent):void {
gotoPage(this.pageNum); gotoPage(this.pageNum);
} }
public function changePage(e:NavigationEvent):void{ public function changePage(e:NavigationEvent):void {
gotoPage(e.pageNumber); gotoPage(e.pageNumber);
} }
private function gotoPage(pageNumber:int):void{ private function gotoPage(pageNumber:int):void {
if (pages == null || pages.length < pageNumber) return; if (pages == null || pages.length < pageNumber) return;
var event:PageEvent = new PageEvent(PageEvent.CHANGE_PAGE); var event:PageEvent = new PageEvent(PageEvent.CHANGE_PAGE);
@ -85,7 +84,7 @@ package org.bigbluebutton.modules.whiteboard.managers
dispatcher.dispatchEvent(event); dispatcher.dispatchEvent(event);
} }
public function createPages(e:PresentationEvent):void{ public function createPages(e:PresentationEvent):void {
pages.removeAll(); pages.removeAll();
for (var i:int = 0; i<e.numberOfSlides; i++){ for (var i:int = 0; i<e.numberOfSlides; i++){
pages.addItem(new ArrayCollection()); pages.addItem(new ArrayCollection());