[OPENMEETINGS-551] basic video support is added
Project: http://git-wip-us.apache.org/repos/asf/openmeetings/repo Commit: http://git-wip-us.apache.org/repos/asf/openmeetings/commit/838bfbe3 Tree: http://git-wip-us.apache.org/repos/asf/openmeetings/tree/838bfbe3 Diff: http://git-wip-us.apache.org/repos/asf/openmeetings/diff/838bfbe3 Branch: refs/heads/master Commit: 838bfbe3b9987bd4c9cfadb39cb08a3b79fff66c Parents: e227dd4 Author: Maxim Solodovnik <[email protected]> Authored: Thu Apr 13 16:29:41 2017 +0000 Committer: Maxim Solodovnik <[email protected]> Committed: Thu Apr 13 16:29:41 2017 +0000 ---------------------------------------------------------------------- .../remote/red5/ScopeApplicationAdapter.java | 6 +- .../openmeetings/db/entity/basic/Client.java | 64 +++++++++- openmeetings-flash/src/main/flex/main.mxml | 122 ++++++++++++------- .../flex/org/apache/openmeetings/OmVideo.as | 44 ++++--- .../openmeetings/web/app/Application.java | 2 +- .../openmeetings/web/common/MainPanel.java | 56 +++++---- .../apache/openmeetings/web/pages/HashPage.java | 5 +- .../apache/openmeetings/web/room/RoomPanel.html | 5 + .../apache/openmeetings/web/room/RoomPanel.java | 20 ++- .../openmeetings/web/room/VideoSettings.java | 6 +- .../org/apache/openmeetings/web/room/room.js | 94 ++++++++++++++ .../apache/openmeetings/web/room/settings.js | 7 +- .../web/room/sidebar/RoomSidebar.java | 14 ++- .../web/util/ExtendedClientProperties.java | 27 +++- openmeetings-web/src/main/webapp/css/room.css | 19 ++- pom.xml | 2 +- 16 files changed, 373 insertions(+), 120 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java ---------------------------------------------------------------------- diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java index ab9d5ab..f0e5db7 100644 --- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java +++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java @@ -201,6 +201,9 @@ public class ScopeApplicationAdapter extends MultiThreadedApplicationAdapter imp String tcUrl = map.containsKey("tcUrl") ? (String)map.get("tcUrl") : ""; Map<String, Object> connParams = getConnParams(params); String uid = (String)connParams.get("uid"); + if ("noclient".equals(uid)) { + return true; + } String securityCode = (String)connParams.get(SECURITY_CODE_PARAM); String parentSid = (String)map.get("parentSid"); if (parentSid == null) { @@ -249,9 +252,6 @@ public class ScopeApplicationAdapter extends MultiThreadedApplicationAdapter imp log.warn("No UIDs are provided, client is rejected"); return rejectClient(); } - if ("networktest".equals(uid)) { - return true; - } if (map.containsKey("screenClient")) { Client parent = sessionManager.getClientByPublicSID(parentSid, null); http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/Client.java ---------------------------------------------------------------------- diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/Client.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/Client.java index 8ec7b27..0f8fc82 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/Client.java +++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/Client.java @@ -28,6 +28,10 @@ import org.apache.openmeetings.db.dao.user.UserDao; import org.apache.openmeetings.db.entity.room.Room.Right; import org.apache.openmeetings.db.entity.user.User; import org.apache.wicket.protocol.ws.api.registry.IKey; +import org.apache.wicket.util.string.Strings; + +import com.github.openjson.JSONArray; +import com.github.openjson.JSONObject; /** * Temporary class, later will be merged with {@link org.apache.openmeetings.db.entity.room.Client} @@ -65,6 +69,7 @@ public class Client implements IClient { private int mic = -1; private int width = 0; private int height = 0; + private long broadcastId = -1; public Client(String sessionId, int pageId, Long userId, UserDao dao) { this.sessionId = sessionId; @@ -157,6 +162,16 @@ public class Client implements IClient { return activities; } + public boolean hasAnyActivity(Activity... aa) { + boolean res = false; + if (aa != null) { + for (Activity a : aa) { + res |= activities.contains(a); + } + } + return res; + } + public boolean hasActivity(Activity a) { return activities.contains(a); } @@ -243,8 +258,9 @@ public class Client implements IClient { return cam; } - public void setCam(int cam) { + public Client setCam(int cam) { this.cam = cam; + return this; } public boolean isMicEnabled() { @@ -255,32 +271,45 @@ public class Client implements IClient { return mic; } - public void setMic(int mic) { + public Client setMic(int mic) { this.mic = mic; + return this; } public int getWidth() { return width; } - public void setWidth(int width) { + public Client setWidth(int width) { this.width = width; + return this; } public int getHeight() { return height; } - public void setHeight(int height) { + public Client setHeight(int height) { this.height = height; + return this; } public String getRemoteAddress() { return remoteAddress; } - public void setRemoteAddress(String remoteAddress) { + public Client setRemoteAddress(String remoteAddress) { this.remoteAddress = remoteAddress; + return this; + } + + public long getBroadcastId() { + return broadcastId; + } + + public Client setBroadcastId(long broadcastId) { + this.broadcastId = broadcastId; + return this; } @Override @@ -313,6 +342,31 @@ public class Client implements IClient { return true; } + public JSONObject toJson() { + JSONObject u = new JSONObject(); + if (user != null) { + JSONObject a = new JSONObject(); + u.put("firstName", user.getFirstname()) + .put("lastName", user.getLastname()) + .put("address", a); + if (user.getAddress() != null) { + if (Strings.isEmpty(user.getFirstname()) && Strings.isEmpty(user.getLastname())) { + a.put("email", user.getAddress().getEmail()); + } + a.put("country", user.getAddress().getCountry()); + } + } + return new JSONObject() + .put("user", u) + .put("uid", uid) + .put("rights", new JSONArray(rights)) + .put("activities", new JSONArray(activities)) + .put("pod", pod) + .put("broadcastId", broadcastId) + .put("width", width) + .put("height", height); + } + @Override public String toString() { return "Client [uid=" + uid + ", sessionId=" + sessionId + ", pageId=" + pageId + ", userId=" + user.getId() + ", roomId=" + roomId http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-flash/src/main/flex/main.mxml ---------------------------------------------------------------------- diff --git a/openmeetings-flash/src/main/flex/main.mxml b/openmeetings-flash/src/main/flex/main.mxml index 1e3867b..d731972 100644 --- a/openmeetings-flash/src/main/flex/main.mxml +++ b/openmeetings-flash/src/main/flex/main.mxml @@ -60,46 +60,72 @@ } private function appInit(evt:Event):void { - var tla:Object = FlexGlobals.topLevelApplication; - debug("appInit()", tla.parameters); - audioOnly = 'true' == tla.parameters['audioOnly']; - interview = 'true' == tla.parameters['interview']; - var _fps:int = parseInt(tla.parameters['fps']); + var params:Object = FlexGlobals.topLevelApplication.parameters; + debug("appInit()", params); + audioOnly = 'true' == params.audioOnly; + interview = 'true' == params.interview; + var _fps:int = parseInt(params.fps); FPS = (isNaN(_fps) || _fps < 1 ? 30 : _fps); - video = new OmVideo(videoDisplay, tla.parameters); - - ExternalInterface.addCallback("getDevices", function ():Object { - return { - cams: Camera.names - , mics: Microphone.names - }; - }); - ExternalInterface.addCallback("camChanged", function (val:int):void { - selectedCam = val; - camChanged(null); - }); - ExternalInterface.addCallback("micChanged", function (val:int):void { - selectedMic = val; - camChanged(null); - }); - ExternalInterface.addCallback("resChanged", function (width:int, height:int):void { - setResolution(width, height, true); - }); - ExternalInterface.addCallback("close", function ():void { - video.reset(); - }); - ExternalInterface.addCallback("init", function (camIdx:int, micIdx:int, width:int, height:int):void { - selectedCam = camIdx; - selectedMic = micIdx; - setResolution(width, height, true); - }); - ExternalInterface.addCallback("startRec", function ():void { - startTestRecording(); - }); - ExternalInterface.addCallback("play", function ():void { - playTestRecording(); - }); - ExternalInterface.call("VideoSettings.initSwf"); + video = new OmVideo(videoDisplay, params); + switch (params.mode) { + case 'settings': + { + ExternalInterface.addCallback("getDevices", function ():Object { + return { + cams: Camera.names + , mics: Microphone.names + }; + }); + ExternalInterface.addCallback("camChanged", function (val:int):void { + selectedCam = val; + camChanged(null); + }); + ExternalInterface.addCallback("micChanged", function (val:int):void { + selectedMic = val; + camChanged(null); + }); + ExternalInterface.addCallback("resChanged", function (width:int, height:int):void { + setResolution(width, height, true); + }); + ExternalInterface.addCallback("close", function ():void { + video.reset(); + }); + ExternalInterface.addCallback("init", function (camIdx:int, micIdx:int, width:int, height:int):void { + selectedCam = camIdx; + selectedMic = micIdx; + setResolution(width, height, true); + }); + ExternalInterface.addCallback("startRec", function ():void { + startTestRecording(); + }); + ExternalInterface.addCallback("play", function ():void { + playTestRecording(); + }); + ExternalInterface.call("VideoSettings.initSwf"); + } + break; + case OmVideo.BROADCAST: + { + selectedCam = params.cam; + selectedMic = params.mic; + video.resize(Math.max(300, params.width), Math.max(200, params.height)); + attachCamera(function():void { + video.resize(params.width, params.height); + video.reset(); + var cam:Camera = getCam(); + video.attachCamera(cam); + video.broadcast(params.broadcastId, cam, getMic()); + ExternalInterface.call("VideoManager.resetSize", params.uid); + }); + } + break; + case OmVideo.PLAY: + { + video.resize(params.width, params.height); + video.play(params.broadcastId); // TODO audio/video + } + break; + } } private function uncaughtError(e:UncaughtErrorEvent):void { @@ -160,7 +186,7 @@ return _camera; } - private function attachCamera():void { + private function attachCamera(callback:Function):void { if (!camAvail()) { return; } @@ -179,13 +205,12 @@ debug("Unable to connect to active camera."); break; case 'Camera.Unmuted': - ExternalInterface.call("VideoSettings.allowRec", true); - _attachCamera(getCam()); + callback(); break; } }); } else { - _attachCamera(cam); + callback(); } } else { var _mic:Microphone = getMic(); @@ -226,6 +251,11 @@ } } + private function settingsCameraCallback():void { + ExternalInterface.call("VideoSettings.allowRec", true); + _attachCamera(getCam()); + } + private function setResolution(width:int, height:int, attach:Boolean):void { if (!interview) { debug("onselect WxH :: " + width + "x" + height); @@ -233,17 +263,17 @@ video.resize(width, height); if (attach) { - attachCamera(); + attachCamera(settingsCameraCallback); } } } private function camChanged(e:Event):void { - attachCamera(); + attachCamera(settingsCameraCallback); } private function playTestRecording():void { - video.play(recName); + video.play(recName + ".flv"); } private function startTestRecording():void { http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-flash/src/main/flex/org/apache/openmeetings/OmVideo.as ---------------------------------------------------------------------- diff --git a/openmeetings-flash/src/main/flex/org/apache/openmeetings/OmVideo.as b/openmeetings-flash/src/main/flex/org/apache/openmeetings/OmVideo.as index cbc0ffe..e23e1ac 100644 --- a/openmeetings-flash/src/main/flex/org/apache/openmeetings/OmVideo.as +++ b/openmeetings-flash/src/main/flex/org/apache/openmeetings/OmVideo.as @@ -145,7 +145,7 @@ public class OmVideo { } videoStreamSettings.setQuality(cam.bandwidth, cam.quality); videoStreamSettings.setKeyFrameInterval(cam.keyFrameInterval); - debug("::keyFrameInterval " + cam.keyFrameInterval); + debug("::camera settings ", cam.keyFrameInterval, cam.width, cam.height, cam.fps); videoStreamSettings.setMode(cam.width, cam.height, cam.fps); ns.videoStreamSettings = videoStreamSettings; } @@ -160,7 +160,7 @@ public class OmVideo { } } - private function publish(mode:String, name:String, cam:Camera, mic:Microphone, f:Function):void { + private function connect(callback:Function):void { if (nc == null || !nc.connected) { var url:String = params.url; //TODO fallback debug("NetConnection is not connected", url); @@ -168,7 +168,7 @@ public class OmVideo { nc.addEventListener(NetStatusEvent.NET_STATUS, function onConnectionStatus(e:NetStatusEvent):void { debug("ConnectionStatus: " + e.info.code); if (e.info.code == "NetConnection.Connect.Success") { - _publish(mode, name, cam, mic, f); + callback(); } else { //TODO } @@ -197,27 +197,37 @@ public class OmVideo { , nativeSsl: 'best' == params.proxyType }); } else { - _publish(mode, name, cam, mic, f); + callback(); } } + public function broadcast(name:String, cam:Camera, mic:Microphone):void { + connect(function():void { + _publish(BROADCAST, name, cam, mic, null); + }); + } + public function record(name:String, cam:Camera, mic:Microphone, f:Function):void { - publish(RECORD, name, cam, mic, f); + connect(function():void { + _publish(RECORD, name, cam, mic, f); + }); } public function play(name:String):void { - debug("PLAY::", name); - if (ns != null){ - reset(); - } - mode = PLAY; - createStream(); - //invokes Method in baseVideoView which shows the stream - getVideo().attachNetStream(ns); - //FIXME: Commented out, cause this leads to Buffer-Full/Buffer-Empty Events - //after re-syncing the stream - //this.setBuffer(0.1); - ns.play(name + ".flv"); + connect(function():void { + debug("PLAY::", name); + if (ns != null){ + reset(); + } + mode = PLAY; + createStream(); + //invokes Method in baseVideoView which shows the stream + getVideo().attachNetStream(ns); + //FIXME: Commented out, cause this leads to Buffer-Full/Buffer-Empty Events + //after re-syncing the stream + //this.setBuffer(0.1); + ns.play(name); + }); } public function reset():void { http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java ---------------------------------------------------------------------- diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java index 0f361dd..271f119 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java @@ -137,7 +137,7 @@ public class Application extends AuthenticatedWebApplication implements IApplica //chain of Resource Loaders, if not found it will search in Wicket's internal //Resource Loader for a the property key getResourceSettings().getStringResourceLoaders().add(0, new LabelResourceLoader()); - getJavaScriptLibrarySettings().setJQueryReference(JQueryResourceReference.getV3()); + getJavaScriptLibrarySettings().setJQueryReference(JQueryResourceReference.getV2()); super.init(); http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java ---------------------------------------------------------------------- diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java index 3055c86..b4da5e9 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/common/MainPanel.java @@ -63,6 +63,7 @@ import org.apache.openmeetings.web.user.UserInfoDialog; import org.apache.openmeetings.web.user.chat.ChatPanel; import org.apache.openmeetings.web.user.rooms.RoomEnterBehavior; import org.apache.openmeetings.web.util.ContactsHelper; +import org.apache.openmeetings.web.util.ExtendedClientProperties; import org.apache.openmeetings.web.util.OmUrlFragment; import org.apache.wicket.Component; import org.apache.wicket.MarkupContainer; @@ -127,10 +128,29 @@ public class MainPanel extends Panel { super(id); this.panel = _panel; setOutputMarkupId(true); - add(topControls.setOutputMarkupPlaceholderTag(true).setMarkupId("topControls")); menu = new MenuPanel("menu", getMainMenu()); contents = new WebMarkupContainer("contents"); - add(contents.add(client == null ? EMPTY : _panel).setOutputMarkupId(true).setMarkupId("contents")); + add(chat = new ChatPanel("chatPanel")); + add(newMessage = new MessageDialog("newMessageDialog", new CompoundPropertyModel<>(new PrivateMessage())) { + private static final long serialVersionUID = 1L; + + @Override + public void onClose(IPartialPageRequestHandler handler, DialogButton button) { + BasePanel bp = getCurrentPanel(); + if (send.equals(button) && bp != null) { + bp.onNewMessageClose(handler); + } + } + }); + add(userInfo = new UserInfoDialog("userInfoDialog", newMessage)); + add(new OmAjaxClientInfoBehavior()); + } + + @Override + protected void onInitialize() { + super.onInitialize(); + add(topControls.setOutputMarkupPlaceholderTag(true).setMarkupId("topControls")); + add(contents.add(client == null ? EMPTY : panel).setOutputMarkupId(true).setMarkupId("contents")); topControls.add(menu.setVisible(false), topLinks.setVisible(false).setOutputMarkupPlaceholderTag(true).setMarkupId("topLinks")); topLinks.add(new AjaxLink<Void>("messages") { private static final long serialVersionUID = 1L; @@ -157,24 +177,21 @@ public class MainPanel extends Panel { about.open(target); } }); + add(about); if (getApplication().getDebugSettings().isDevelopmentUtilitiesEnabled()) { add(new DebugBar("dev").setOutputMarkupId(true)); } else { add(new EmptyPanel("dev").setVisible(false)); } - add(about, chat = new ChatPanel("chatPanel")); - add(newMessage = new MessageDialog("newMessageDialog", new CompoundPropertyModel<>(new PrivateMessage())) { + topLinks.add(new ConfirmableAjaxBorder("logout", getString("310"), getString("634")) { private static final long serialVersionUID = 1L; @Override - public void onClose(IPartialPageRequestHandler handler, DialogButton button) { - BasePanel bp = getCurrentPanel(); - if (send.equals(button) && bp != null) { - bp.onNewMessageClose(handler); - } + protected void onSubmit(AjaxRequestTarget target) { + getSession().invalidate(); + setResponsePage(Application.get().getSignInPageClass()); } }); - add(userInfo = new UserInfoDialog("userInfoDialog", newMessage)); add(new AbstractDefaultAjaxBehavior() { private static final long serialVersionUID = 1L; @@ -224,9 +241,9 @@ public class MainPanel extends Panel { @Override protected void onConnect(ConnectedMessage msg) { super.onConnect(msg); + ExtendedClientProperties cp = WebSession.get().getExtendedProperties(); client = new Client(getSession().getId(), msg.getKey().hashCode(), getUserId(), getBean(UserDao.class)); - client.setRemoteAddress(WebSession.get().getClientInfo().getProperties().getRemoteAddress()); - addOnlineUser(client); + addOnlineUser(cp.update(client)); log.debug("WebSocketBehavior::onConnect [uid: {}, session: {}, key: {}]", client.getUid(), msg.getSessionId(), msg.getKey()); } @@ -268,21 +285,6 @@ public class MainPanel extends Panel { } } }); - add(new OmAjaxClientInfoBehavior()); - } - - @Override - protected void onInitialize() { - super.onInitialize(); - topLinks.add(new ConfirmableAjaxBorder("logout", getString("310"), getString("634")) { - private static final long serialVersionUID = 1L; - - @Override - protected void onSubmit(AjaxRequestTarget target) { - getSession().invalidate(); - setResponsePage(Application.get().getSignInPageClass()); - } - }); } private static int getLevel() { http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/HashPage.java ---------------------------------------------------------------------- diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/HashPage.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/HashPage.java index 9ec4dea..8e4f8c6 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/HashPage.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/HashPage.java @@ -153,9 +153,10 @@ public class HashPage extends BaseInitedPage implements IUpdatable { @Override protected void onClientInfo(AjaxRequestTarget target, WebClientInfo info) { super.onClientInfo(target, info); + ExtendedClientProperties cp = (ExtendedClientProperties)info.getProperties(); target.appendJavaScript( - VideoSettings.getInitScript((ExtendedClientProperties)info.getProperties(), "hibernate", "networktest") - .append("VideoSettings.open();")); + String.format("VideoSettings.init(%s);VideoSettings.open();" + , VideoSettings.getInitJson(cp, "hibernate", "noclient"))); } })); error = false; http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html ---------------------------------------------------------------------- diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html index 80fae9f..87afb87 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html @@ -42,5 +42,10 @@ <div id="disconnected-dlg" wicket:message="title:204, data-reload:753" style="display:none"> <wicket:message key="556"/> </div> + <div style="display:none"> + <div id="user-video"> + <div class="video"></div> + </div> + </div> </wicket:panel> </html> http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java ---------------------------------------------------------------------- diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java index c4d9728..abb98dc 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.java @@ -25,6 +25,7 @@ import static org.apache.openmeetings.web.app.Application.getBean; import static org.apache.openmeetings.web.app.Application.getOnlineClient; import static org.apache.openmeetings.web.app.Application.getRoomClients; import static org.apache.openmeetings.web.app.WebSession.getDateFormat; +import static org.apache.openmeetings.web.app.WebSession.getSid; import static org.apache.openmeetings.web.app.WebSession.getUserId; import java.util.Calendar; @@ -81,6 +82,7 @@ import org.apache.wicket.request.resource.ResourceReference; import org.red5.logging.Red5LoggerFactory; import org.slf4j.Logger; +import com.github.openjson.JSONObject; import com.googlecode.wicket.jquery.core.JQueryBehavior; import com.googlecode.wicket.jquery.core.Options; import com.googlecode.wicket.jquery.ui.interaction.droppable.Droppable; @@ -115,7 +117,10 @@ public class RoomPanel extends BasePanel { , getUserId(), "0", r.getId() , cp.getRemoteAddress() , "" + r.getId()); - target.appendJavaScript(VideoSettings.getInitScript(cp, "" + r.getId(), getClient().getUid())); + //TODO add all broadcasting clients + JSONObject options = VideoSettings.getInitJson(cp, "" + r.getId(), getClient().getUid()); + options.put("interview", Room.Type.interview == r.getType()); + target.appendJavaScript(String.format("VideoManager.init(%s);", options)); WebSocketHelper.sendRoom(new RoomMessage(r.getId(), getUserId(), RoomMessage.Type.roomEnter)); getMainPanel().getChat().roomEnter(r, target); if (r.isFilesOpened()) { @@ -354,9 +359,14 @@ public class RoomPanel extends BasePanel { } break; case rightUpdated: - sidebar.update(handler); - menu.update(handler); - wb.update(handler); + { + Client c = getOnlineClient(((TextRoomMessage)m).getText()); + handler.appendJavaScript(String.format("VideoManager.update(%s);" + , c.toJson().put("sid", getSid()).put("self", getClient().getUid().equals(c.getUid())))); + sidebar.update(handler); + menu.update(handler); + wb.update(handler); + } break; case roomEnter: sidebar.update(handler); @@ -581,7 +591,7 @@ public class RoomPanel extends BasePanel { } public void broadcast(Client client) { - WebSocketHelper.sendRoom(new RoomMessage(getRoom().getId(), getUserId(), RoomMessage.Type.rightUpdated)); + WebSocketHelper.sendRoom(new TextRoomMessage(getRoom().getId(), getUserId(), RoomMessage.Type.rightUpdated, client.getUid())); RoomBroadcaster.sendUpdatedClient(client); } http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/VideoSettings.java ---------------------------------------------------------------------- diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/VideoSettings.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/VideoSettings.java index 98319fc..0b9a08c 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/VideoSettings.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/VideoSettings.java @@ -65,12 +65,12 @@ public class VideoSettings extends Panel { return String.format("%s://%s:%s/%s", protocol, host, port, app); } - public static StringBuilder getInitScript(ExtendedClientProperties cp, String scope, String uid) { + public static JSONObject getInitJson(ExtendedClientProperties cp, String scope, String uid) { JSONObject gs = getBean(ScopeApplicationAdapter.class).getFlashSettings(); JSONObject s = new JSONObject() .put(FLASH_VIDEO_CODEC, gs.get(FLASH_VIDEO_CODEC)) .put(FLASH_FPS, gs.get(FLASH_FPS)) - .put("SID", WebSession.getSid()) + .put("sid", WebSession.getSid()) .put("wmode", cp.isBrowserInternetExplorer() && cp.getBrowserVersionMajor() == 11 ? "opaque" : "direct"); if (!Strings.isEmpty(uid)) { s.put("uid", uid); @@ -90,6 +90,6 @@ public class VideoSettings extends Panel { } catch (Exception e) { log.error("Error while constructing video settings parameters", e); } - return new StringBuilder("VideoSettings.init(").append(s.toString()).append(");"); + return s; } } http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/room.js ---------------------------------------------------------------------- diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/room.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/room.js index 989aa20..ffbfc79 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/room.js +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/room.js @@ -16,6 +16,99 @@ * specific language governing permissions and limitations * under the License. */ +var Video = (function() { + var self = {}, c, box, v, vc, t, swf; + + function _getName() { + return c.user.firstName + ' ' + c.user.lastName; + } + function _resetSize() { + v.dialog("option", "width", c.width).dialog("option", "height", t.height() + c.height + 2); + vc.width(c.width).height(c.height); + swf.attr('width', c.width).attr('height', c.height); + } + function _init(_box, _c) { + c = _c; + box = _box; + var _id = "video" + c.uid, name = _getName() + , w = c.self ? Math.max(300, c.width) : c.width + , h = c.self ? Math.max(200, c.height) : c.height; + box.append($('#user-video').clone().attr('id', _id).attr('title', name).data(self)); + v = $('#' + _id); + v.dialog({ + classes: { + 'ui-dialog': 'ui-corner-all video user-video' + , 'ui-dialog-titlebar': 'ui-corner-all no-close' + } + , width: w + , minWidth: 40 + , minHeight: 50 + , autoOpen: true + , modal: false + //resizeStop + }); + t = v.parent().find('.ui-dialog-titlebar').attr('title', name); + vc = v.find('.video'); + vc.width(w).height(h); + //broadcast + var o = VideoManager.getOptions(); + if (c.self) { + o.cam = c.cam; + o.mic = c.mic; + o.mode = 'broadcast'; + } else { + o.mode = 'play'; + } + o.width = c.width; + o.height = c.height; + o.uid = c.uid; + o.sid = c.sid; + o.broadcastId = c.broadcastId; + swf = initVideo(vc, _id + '-swf', o); + swf.attr('width', w).attr('height', h); + } + function _update(_c) { + // TODO check, update video + c = _c; + } + + self.update = _update; + self.init = _init; + self.resetSize = _resetSize; + return self; +}); +var VideoManager = (function() { + var self = {}, box, options; + + function _init(_options) { + options = _options; + VideoSettings.init(self.getOptions()); + box = $('.room.box'); + } + function _getVid(uid) { + return "video" + uid; + } + function _update(o) { + var _id = _getVid(o.uid) + , video = o.activities.indexOf('broadcastV') > -1 + , audio = o.activities.indexOf('broadcastA') > -1 + , av = audio || video + , v = $('#' + _id); + if (av && v.length != 1) { + Video().init(box, o); + } else if (av && v.length == 1) { + v.data().update(o); + } else if (!av && v.length == 1) { + v.remove(); + } + } + + self.getOptions = function() { return JSON.parse(JSON.stringify(options)); }; + self.init = _init; + self.update = _update; + self.resetSize = function(uid) { $('#' + _getVid(uid)).data().resetSize(); }; + return self; +})(); function setRoomSizes() { var sb = $(".room.sidebar.left") , w = $(window).width() - sb.width() - 5 @@ -73,6 +166,7 @@ function roomUnload() { WbArea.destroy(); } VideoSettings.close(); + $('.ui-dialog.user-video').remove(); } function startPrivateChat(el) { Chat.addTab('chatTab-u' + el.parent().parent().data("userid"), el.parent().parent().find('.user.name').text()); http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/settings.js ---------------------------------------------------------------------- diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/settings.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/settings.js index 9c96224..0a46761 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/settings.js +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/settings.js @@ -41,7 +41,11 @@ var VideoSettings = (function() { } } function _save() { - localStorage.setItem('openmeetings', JSON.stringify(s)); + var _s = JSON.stringify(s); + localStorage.setItem('openmeetings', _s); + if (typeof avSettings === 'function') { + avSettings(_s); + } } function _init(options) { vs = $('#video-settings'); @@ -85,6 +89,7 @@ var VideoSettings = (function() { lm.progressbar({ value: 0 }); options.width = 300; options.height = 200; + options.mode = 'settings'; swf = initVideo(vidScroll, 'video-settings-swf', options)[0]; vs.find('input, button').prop('disabled', true); vs.find('button').button(); http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomSidebar.java ---------------------------------------------------------------------- diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomSidebar.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomSidebar.java index ffa6ba1..62aaf2d 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomSidebar.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/sidebar/RoomSidebar.java @@ -27,6 +27,7 @@ import static org.apache.wicket.ajax.attributes.CallbackParameter.explicit; import java.util.ArrayList; import java.util.List; +import org.apache.openmeetings.core.remote.red5.ScopeApplicationAdapter; import org.apache.openmeetings.db.entity.basic.Client; import org.apache.openmeetings.db.entity.basic.Client.Activity; import org.apache.openmeetings.db.entity.basic.Client.Pod; @@ -34,6 +35,7 @@ import org.apache.openmeetings.db.entity.room.Room; import org.apache.openmeetings.db.entity.room.Room.Right; import org.apache.openmeetings.db.entity.room.Room.RoomElement; import org.apache.openmeetings.web.app.Application; +import org.apache.openmeetings.web.app.WebSession; import org.apache.openmeetings.web.common.ConfirmableAjaxBorder; import org.apache.openmeetings.web.common.ConfirmableAjaxBorder.ConfirmableBorderDialog; import org.apache.openmeetings.web.common.NameDialog; @@ -41,6 +43,7 @@ import org.apache.openmeetings.web.room.RoomBroadcaster; import org.apache.openmeetings.web.room.RoomPanel; import org.apache.openmeetings.web.room.RoomPanel.Action; import org.apache.openmeetings.web.room.VideoSettings; +import org.apache.openmeetings.web.util.ExtendedClientProperties; import org.apache.wicket.AttributeModifier; import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -212,13 +215,9 @@ public class RoomSidebar extends Panel { protected void respond(AjaxRequestTarget target) { StringValue s = getRequest().getRequestParameters().getParameterValue(PARAM_SETTINGS); if (!s.isEmpty()) { - JSONObject o = new JSONObject(s.toString()); + ExtendedClientProperties cp = WebSession.get().getExtendedProperties(); Client c = room.getClient(); - c.setCam(o.optInt("cam", -1)); - c.setMic(o.optInt("mic", -1)); - boolean interview = Room.Type.interview == room.getRoom().getType(); - c.setWidth(interview ? 320 : o.optInt("width")); - c.setHeight(interview ? 260 : o.optInt("height")); + cp.setSettings(new JSONObject(s.toString())).update(c, Room.Type.interview == room.getRoom().getType()); if (!avInited) { avInited = true; if (Room.Type.conference == room.getRoom().getType()) { @@ -419,6 +418,9 @@ public class RoomSidebar extends Panel { //pod has changed, no need to toggle c.set(a); } else { + if (!c.hasActivity(Activity.broadcastV) && Activity.broadcastV == a) { + c.setBroadcastId(ScopeApplicationAdapter.nextBroadCastId()); + } c.toggle(a); } room.broadcast(c); http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-web/src/main/java/org/apache/openmeetings/web/util/ExtendedClientProperties.java ---------------------------------------------------------------------- diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/util/ExtendedClientProperties.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/util/ExtendedClientProperties.java index 1e339ae..a59cbbf 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/util/ExtendedClientProperties.java +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/util/ExtendedClientProperties.java @@ -22,6 +22,8 @@ import static org.apache.openmeetings.web.app.Application.HASH_MAPPING; import static org.apache.openmeetings.web.app.Application.NOTINIT_MAPPING; import static org.apache.openmeetings.web.app.Application.SIGNIN_MAPPING; +import org.apache.directory.api.util.Strings; +import org.apache.openmeetings.db.entity.basic.Client; import org.apache.wicket.protocol.http.ClientProperties; import org.apache.wicket.request.IRequestParameters; @@ -29,6 +31,10 @@ import com.github.openjson.JSONObject; public class ExtendedClientProperties extends ClientProperties { private static final long serialVersionUID = 1L; + public static final String CAM = "cam"; + public static final String MIC = "mic"; + public static final String WIDTH = "width"; + public static final String HEIGHT = "height"; private String baseUrl; private String codebase; private String settings; @@ -41,13 +47,14 @@ public class ExtendedClientProperties extends ClientProperties { return baseUrl; } - public void setSettings(JSONObject s) { + public ExtendedClientProperties setSettings(JSONObject s) { settings = s.toString(); + return this; } public JSONObject getSettings() { try { - return settings == null ? new JSONObject() : new JSONObject(settings.toString()); + return Strings.isEmpty(settings) ? new JSONObject() : new JSONObject(settings.toString()); } catch (Exception e) { //can throw, no op } @@ -81,4 +88,20 @@ public class ExtendedClientProperties extends ClientProperties { codebase = sb.append("screenshare").toString(); settings = parameters.getParameterValue("settings").toString("{}"); } + + public Client update(Client c) { + return update(c, false); + } + + public Client update(Client c, boolean interview) { + JSONObject s = getSettings().optJSONObject("video"); + if (s == null) { + s = new JSONObject(); + } + return c.setRemoteAddress(getRemoteAddress()) + .setCam(s.optInt(CAM, -1)) + .setMic(s.optInt(MIC, -1)) + .setWidth(interview ? 320 : s.optInt(WIDTH, 0)) + .setHeight(interview ? 260 : s.optInt(HEIGHT, 0)); + } } http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/openmeetings-web/src/main/webapp/css/room.css ---------------------------------------------------------------------- diff --git a/openmeetings-web/src/main/webapp/css/room.css b/openmeetings-web/src/main/webapp/css/room.css index 36fab21..04d3a2b 100644 --- a/openmeetings-web/src/main/webapp/css/room.css +++ b/openmeetings-web/src/main/webapp/css/room.css @@ -352,7 +352,7 @@ font-weight: bold; background-color: #00FF00; } -.ui-dialog.video, .ui-dialog.video .ui-dialog-titlebar, .ui-dialog.video .video.ui-dialog-content { +.ui-dialog.video, .ui-dialog.video .ui-dialog-titlebar, .ui-dialog.video .ui-dialog-content { padding: 0; overflow: hidden; } @@ -574,3 +574,20 @@ border: 1px solid #888888; box-shadow: 5px 5px 5px #888888; } +.room.box .user-video { + display: inline-block !important; +} +.room.box .user-video .header { + height: 20px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} +.room.box .user-video .header .ui-dialog-title { + padding-left: 5px; +} +.room.box .user-video .video { + min-width: 40px; + min-height: 30px; + overflow: hidden; +} http://git-wip-us.apache.org/repos/asf/openmeetings/blob/838bfbe3/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index bbcf269..48faea7 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ <db>derby</db> <junit.version>4.12</junit.version> <maven.javadoc.version>2.10.3</maven.javadoc.version> - <maven.surefire.version>2.19.1</maven.surefire.version> + <maven.surefire.version>2.20</maven.surefire.version> <maven-site.version>3.3</maven-site.version> <wicket.version>8.0.0-SNAPSHOT</wicket.version> <wicketju.version>8.0.0-M5</wicketju.version>
