This is an automated email from the ASF dual-hosted git repository.

solomax pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openmeetings.git


The following commit(s) were added to refs/heads/master by this push:
     new b259b47  [OPENMEETINGS-1854] basic ability to create test recording is 
created
b259b47 is described below

commit b259b47c782b937cbcde7b4793771e09690865e6
Author: Maxim Solodovnik <[email protected]>
AuthorDate: Sun Mar 18 22:56:37 2018 +0700

    [OPENMEETINGS-1854] basic ability to create test recording is created
---
 .../apache/openmeetings/core/remote/KTestUser.java | 162 +++++++++++++++++++++
 .../org/apache/openmeetings/core/remote/KUser.java |   2 -
 .../openmeetings/core/remote/KurentoHandler.java   | 138 ++++++++++++------
 .../openmeetings/db/entity/basic/Client.java       |  16 +-
 .../openmeetings/db/entity/basic/IWsClient.java    |  35 +++++
 .../openmeetings/db/entity/basic/WsClient.java     |  89 +++++++++++
 .../org/apache/openmeetings/util/OmFileHelper.java |   2 +-
 .../apache/openmeetings/web/common/MainPanel.java  |   2 +-
 .../apache/openmeetings/web/pages/HashPage.java    |  11 +-
 .../web/room/RoomResourceReference.java            |   4 +-
 .../openmeetings/web/room/VideoSettings.html       |   5 +-
 .../apache/openmeetings/web/room/settings-base.js  |  92 ++++++------
 openmeetings-web/src/main/webapp/WEB-INF/web.xml   |   3 +-
 openmeetings-web/src/main/webapp/css/general.css   |   2 +-
 .../main/webapp/{ => css}/images/ajax-loader.gif   | Bin
 openmeetings-web/src/main/webapp/css/room.css      |   7 +
 openmeetings-web/src/main/webapp/images/delete.gif | Bin 351 -> 0 bytes
 openmeetings-web/src/main/webapp/images/down.png   | Bin 617 -> 0 bytes
 openmeetings-web/src/main/webapp/images/edit.png   | Bin 551 -> 0 bytes
 openmeetings-web/src/main/webapp/images/error.png  | Bin 666 -> 0 bytes
 openmeetings-web/src/main/webapp/images/info.png   | Bin 778 -> 0 bytes
 .../src/main/webapp/images/level_meter.png         | Bin 140 -> 0 bytes
 .../src/main/webapp/images/refresh.gif             | Bin 925 -> 0 bytes
 openmeetings-web/src/main/webapp/images/up.png     | Bin 546 -> 0 bytes
 .../main/webapp/{default => public}/deleted.odp    | Bin
 .../main/webapp/{default => public}/deleted.pdf    | Bin
 .../main/webapp/{default => public}/deleted.png    | Bin
 pom.xml                                            |   2 +-
 28 files changed, 463 insertions(+), 109 deletions(-)

diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KTestUser.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KTestUser.java
new file mode 100644
index 0000000..6f8e5cf
--- /dev/null
+++ 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KTestUser.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") +  you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openmeetings.core.remote;
+
+import static 
org.apache.openmeetings.core.remote.KurentoHandler.newTestKurentoMsg;
+import static org.apache.openmeetings.util.OmFileHelper.TEST_SETUP_PREFIX;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.openmeetings.db.entity.basic.IWsClient;
+import org.kurento.client.Continuation;
+import org.kurento.client.EventListener;
+import org.kurento.client.IceCandidate;
+import org.kurento.client.IceCandidateFoundEvent;
+import org.kurento.client.MediaPipeline;
+import org.kurento.client.MediaProfileSpecType;
+import org.kurento.client.MediaType;
+import org.kurento.client.RecorderEndpoint;
+import org.kurento.client.RecordingEvent;
+import org.kurento.client.StoppedEvent;
+import org.kurento.client.WebRtcEndpoint;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.openjson.JSONObject;
+
+public class KTestUser {
+       private final static Logger log = 
LoggerFactory.getLogger(KTestUser.class);
+       private MediaPipeline pipeline;
+       private WebRtcEndpoint webRtcEndpoint;
+       private String recPath = null;
+       private final ScheduledExecutorService scheduler = 
Executors.newScheduledThreadPool(1);
+       private ScheduledFuture<?> recHandle;
+       private int recTime;
+
+       public KTestUser(IWsClient _c, JSONObject msg, KurentoHandler handler, 
MediaPipeline pipeline) {
+               webRtcEndpoint = new WebRtcEndpoint.Builder(pipeline).build();
+               webRtcEndpoint.connect(webRtcEndpoint);
+
+               MediaProfileSpecType profile = getProfile(msg);
+               //FIXME TODO generated file uid
+               initRecPath(_c.getUid());
+               final RecorderEndpoint recorder = new 
RecorderEndpoint.Builder(pipeline, recPath)
+                               .withMediaProfile(profile).build();
+
+               recorder.addRecordingListener(new 
EventListener<RecordingEvent>() {
+                       @Override
+                       public void onEvent(RecordingEvent event) {
+                               recTime = 0;
+                               recHandle = scheduler.scheduleAtFixedRate(
+                                               () -> handler.sendClient(_c, 
newTestKurentoMsg().put("id", "testRecording").put("time", recTime++))
+                                               , 0, 1, TimeUnit.SECONDS);
+                               scheduler.schedule(() -> {
+                                               recorder.stop();
+                                               recHandle.cancel(true);
+                                       }, 5, TimeUnit.SECONDS);
+                       }
+               });
+               recorder.addStoppedListener(new EventListener<StoppedEvent>() {
+                       @Override
+                       public void onEvent(StoppedEvent event) {
+                               handler.sendClient(_c, 
newTestKurentoMsg().put("id", "testStopped"));
+                       }
+               });
+               switch (profile) {
+                       case MP4:
+                               webRtcEndpoint.connect(recorder, 
MediaType.AUDIO);
+                               webRtcEndpoint.connect(recorder, 
MediaType.VIDEO);
+                               break;
+                       case MP4_AUDIO_ONLY:
+                               webRtcEndpoint.connect(recorder, 
MediaType.AUDIO);
+                               break;
+                       case MP4_VIDEO_ONLY:
+                               webRtcEndpoint.connect(recorder, 
MediaType.VIDEO);
+                               break;
+                       default:
+                               //no-op
+                               break;
+               }
+
+               // 3. SDP negotiation
+               String sdpOffer = msg.getString("sdpOffer");
+               String sdpAnswer = webRtcEndpoint.processOffer(sdpOffer);
+
+               // 4. Gather ICE candidates
+               webRtcEndpoint.addIceCandidateFoundListener(new 
EventListener<IceCandidateFoundEvent>() {
+                       @Override
+                       public void onEvent(IceCandidateFoundEvent event) {
+                               IceCandidate cand = event.getCandidate();
+                               handler.sendClient(_c, newTestKurentoMsg()
+                                               .put("id", "testIceCandidate")
+                                               .put("candidate", new 
JSONObject()
+                                                               
.put("candidate", cand.getCandidate())
+                                                               .put("sdpMid", 
cand.getSdpMid())
+                                                               
.put("sdpMLineIndex", cand.getSdpMLineIndex())));
+                       }
+               });
+
+               handler.sendClient(_c, newTestKurentoMsg()
+                               .put("id", "testStartResponse")
+                               .put("sdpAnswer", sdpAnswer));
+               webRtcEndpoint.gatherCandidates();
+               recorder.record(new Continuation<Void>() {
+                       @Override
+                       public void onSuccess(Void result) throws Exception {
+                               log.info("Recording started successfully");
+                       }
+
+                       @Override
+                       public void onError(Throwable cause) throws Exception {
+                               log.error("Failed to start recording", cause);
+                       }
+               });
+       }
+
+       public void addCandidate(IceCandidate cand) {
+               webRtcEndpoint.addIceCandidate(cand);
+       }
+
+       private static MediaProfileSpecType getProfile(JSONObject msg) {
+               boolean a  = msg.getBoolean("audio"), v = 
msg.getBoolean("video");
+               if (a && v) {
+                       return MediaProfileSpecType.MP4;
+               } else if (v) {
+                       return MediaProfileSpecType.MP4_VIDEO_ONLY;
+               } else {
+                       return MediaProfileSpecType.MP4_AUDIO_ONLY;
+               }
+       }
+
+       private void initRecPath(String uid) {
+               try {
+                       //File f = new File(getStreamsDir(), 
String.format("%s%s.mp4", TEST_SETUP_PREFIX, uid));
+                       File f = new File("/tmp/", String.format("%s%s.mp4", 
TEST_SETUP_PREFIX, uid));
+                       recPath = String.format("file://%s", 
f.getCanonicalPath());
+                       log.info("Configured to record to {}", recPath);
+               } catch (IOException e) {
+                       log.error("Uexpected error while creating recording 
URI", e);
+               }
+       }
+}
diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KUser.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KUser.java
index fd1031b..7a3b4cb 100644
--- 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KUser.java
+++ 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KUser.java
@@ -182,9 +182,7 @@ public class KUser implements Closeable {
                        log.trace("PARTICIPANT {}: Released incoming EP for 
{}", this.uid, remoteParticipantName);
 
                        final WebRtcEndpoint ep = 
this.incomingMedia.get(remoteParticipantName);
-
                        ep.release(new Continuation<Void>() {
-
                                @Override
                                public void onSuccess(Void result) throws 
Exception {
                                        log.trace("PARTICIPANT {}: Released 
successfully incoming EP for {}", KUser.this.uid,
diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KurentoHandler.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KurentoHandler.java
index 0d72547..aae1cfc 100644
--- 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KurentoHandler.java
+++ 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KurentoHandler.java
@@ -18,15 +18,22 @@
  */
 package org.apache.openmeetings.core.remote;
 
+import java.io.IOException;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 
-import org.apache.openmeetings.core.util.WebSocketHelper;
 import org.apache.openmeetings.db.entity.basic.Client;
+import org.apache.openmeetings.db.entity.basic.IWsClient;
 import org.apache.openmeetings.db.manager.IClientManager;
+import org.apache.wicket.Application;
+import org.apache.wicket.protocol.ws.WebSocketSettings;
+import org.apache.wicket.protocol.ws.api.IWebSocketConnection;
+import org.apache.wicket.protocol.ws.api.registry.IWebSocketConnectionRegistry;
+import org.apache.wicket.protocol.ws.api.registry.PageIdKey;
+import org.apache.wicket.protocol.ws.concurrent.Executor;
 import org.kurento.client.IceCandidate;
 import org.kurento.client.KurentoClient;
 import org.slf4j.Logger;
@@ -43,9 +50,12 @@ public class KurentoHandler {
        private KurentoClient client;
        private final Map<Long, KRoom> rooms = new ConcurrentHashMap<>();
        final Map<String, KUser> usersByUid = new ConcurrentHashMap<>();
+       final Map<String, KTestUser> testsByUid = new ConcurrentHashMap<>();
 
        @Autowired
        private IClientManager clientManager;
+       @Autowired
+       private Application app;
 
        @PostConstruct
        private void init() {
@@ -64,46 +74,67 @@ public class KurentoHandler {
                }
        }
 
-       public void onMessage(String uid, JSONObject msg) {
-               final Client c = clientManager.get(uid);
-
-               if (c != null) {
-                       log.debug("Incoming message from user with ID '{}': 
{}", c.getUserId(), msg);
-               } else {
-                       log.debug("Incoming message from new user: {}", msg);
-               }
-               KUser user = getByUid(uid);
-               switch (msg.getString("id")) {
-                       case "joinRoom":
-                               joinRoom(c);
-                               break;
-                       case "receiveVideoFrom":
-                               final String senderUid = 
msg.getString("sender");
-                               final KUser sender = getByUid(senderUid);
-                               final String sdpOffer = 
msg.getString("sdpOffer");
-                               if (user == null) {
-                                       KRoom room = getRoom(c.getRoomId());
-                                       user = room.addUser(this, uid);
+       public void onMessage(IWsClient _c, JSONObject msg) {
+               final String cmdId = msg.getString("id");
+               if ("test".equals(msg.getString("mode"))) {
+                       KTestUser user = getTestByUid(_c.getUid());
+                       switch (cmdId) {
+                               case "testStart":
+                               {
+                                       //TODO FIXME assert null user ???
+                                       user = new KTestUser(_c, msg, this, 
client.createMediaPipeline());
+                                       testsByUid.put(_c.getUid(), user);
                                }
-                               user.receiveVideoFrom(this, sender, sdpOffer);
-                               break;
-                       case "onIceCandidate":
-                               JSONObject candidate = 
msg.getJSONObject("candidate");
-
-                               if (user == null) {
-                                       KRoom room = getRoom(c.getRoomId());
-                                       user = room.addUser(this, uid);
+                                       break;
+                               case "onTestIceCandidate":
+                               {
+                                       JSONObject candidate = 
msg.getJSONObject("candidate");
+
+                                       if (user != null) {
+                                               IceCandidate cand = new 
IceCandidate(candidate.getString("candidate"),
+                                                               
candidate.getString("sdpMid"), candidate.getInt("sdpMLineIndex"));
+                                               user.addCandidate(cand);
+                                       }
                                }
-                               IceCandidate cand = new 
IceCandidate(candidate.getString("candidate"),
-                                               candidate.getString("sdpMid"), 
candidate.getInt("sdpMLineIndex"));
-                               user.addCandidate(cand, msg.getString("uid"));
-                               break;
-                       case "testStart":
-                               break;
-                       case "onTestIceCandidate":
-                               break;
-                       default:
-                               break;
+                                       break;
+                       }
+               } else {
+                       final Client c = (Client)_c;
+
+                       if (c != null) {
+                               log.debug("Incoming message from user with ID 
'{}': {}", c.getUserId(), msg);
+                       } else {
+                               log.debug("Incoming message from new user: {}", 
msg);
+                       }
+                       KUser user = getByUid(_c.getUid());
+                       switch (cmdId) {
+                               case "joinRoom":
+                                       joinRoom(c);
+                                       break;
+                               case "receiveVideoFrom":
+                                       final String senderUid = 
msg.getString("sender");
+                                       final KUser sender = 
getByUid(senderUid);
+                                       final String sdpOffer = 
msg.getString("sdpOffer");
+                                       if (user == null) {
+                                               KRoom room = 
getRoom(c.getRoomId());
+                                               user = room.addUser(this, 
_c.getUid());
+                                       }
+                                       user.receiveVideoFrom(this, sender, 
sdpOffer);
+                                       break;
+                               case "onIceCandidate":
+                               {
+                                       JSONObject candidate = 
msg.getJSONObject("candidate");
+
+                                       if (user == null) {
+                                               KRoom room = 
getRoom(c.getRoomId());
+                                               user = room.addUser(this, 
_c.getUid());
+                                       }
+                                       IceCandidate cand = new 
IceCandidate(candidate.getString("candidate"),
+                                                       
candidate.getString("sdpMid"), candidate.getInt("sdpMLineIndex"));
+                                       user.addCandidate(cand, 
msg.getString("uid"));
+                               }
+                                       break;
+                       }
                }
        }
 
@@ -115,8 +146,25 @@ public class KurentoHandler {
                room.join(this, c.getUid());
        }
 
-       void sendClient(String uid, JSONObject msg) {
-               WebSocketHelper.sendClient(clientManager.get(uid), msg);
+       public void sendClient(String uid, JSONObject msg) {
+               sendClient(clientManager.get(uid), msg);
+       }
+
+       //FIXME TODO UNIFY THIS
+       void sendClient(IWsClient client, JSONObject msg) {
+               WebSocketSettings settings = WebSocketSettings.Holder.get(app);
+               IWebSocketConnectionRegistry reg = 
settings.getConnectionRegistry();
+               Executor executor = settings.getWebSocketPushMessageExecutor(); 
//FIXME TODO
+               final IWebSocketConnection wc = reg.getConnection(app, 
client.getSessionId(), new PageIdKey(client.getPageId()));
+               if (wc != null && wc.isOpen()) {
+                       executor.run(() -> {
+                               try {
+                                       wc.sendMessage(msg.toString());
+                               } catch (IOException e) {
+                                       log.error("Error while sending message 
to client", e);
+                               }
+                       });
+               }
        }
 
        /**
@@ -156,6 +204,10 @@ public class KurentoHandler {
                return uid == null ? null : usersByUid.get(uid);
        }
 
+       public KTestUser getTestByUid(String uid) {
+               return uid == null ? null : testsByUid.get(uid);
+       }
+
        public boolean exists(String name) {
                return usersByUid.keySet().contains(name);
        }
@@ -163,4 +215,8 @@ public class KurentoHandler {
        static JSONObject newKurentoMsg() {
                return new JSONObject().put("type", KURENTO_TYPE);
        }
+
+       static JSONObject newTestKurentoMsg() {
+               return newKurentoMsg().put("mode", "test");
+       }
 }
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 b731dfd..c386c3d 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
@@ -33,7 +33,6 @@ import org.apache.openmeetings.db.entity.room.StreamClient;
 import org.apache.openmeetings.db.entity.user.User;
 import org.apache.openmeetings.db.manager.IStreamClientManager;
 import org.apache.openmeetings.db.util.RoomHelper;
-import org.apache.wicket.protocol.ws.api.registry.IKey;
 import org.apache.wicket.util.string.Strings;
 
 import com.github.openjson.JSONArray;
@@ -44,7 +43,7 @@ import com.github.openjson.JSONObject;
  * @author solomax
  *
  */
-public class Client implements IClient {
+public class Client implements IClient, IWsClient {
        private static final long serialVersionUID = 1L;
 
        public enum Activity {
@@ -59,7 +58,7 @@ public class Client implements IClient {
                none, left, right;
        }
        private final String sessionId;
-       private int pageId;
+       private final int pageId;
        private User user;
        private Room room;
        private final String uid;
@@ -96,23 +95,16 @@ public class Client implements IClient {
                this.remoteAddress = rcl.getRemoteAddress();
        }
 
+       @Override
        public String getSessionId() {
                return sessionId;
        }
 
+       @Override
        public int getPageId() {
                return pageId;
        }
 
-       public Client setPageId(IKey key) {
-               this.pageId = key.hashCode();
-               return this;
-       }
-
-       public void setPageId(int pageId) {
-               this.pageId = pageId;
-       }
-
        public User getUser() {
                return user;
        }
diff --git 
a/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/IWsClient.java
 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/IWsClient.java
new file mode 100644
index 0000000..503e46e
--- /dev/null
+++ 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/IWsClient.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") +  you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openmeetings.db.entity.basic;
+
+import java.io.Serializable;
+
+/**
+ * Necessary for temp clients being created on HashPage
+ *
+ * {@link org.apache.openmeetings.db.entity.room.StreamClient}
+ * {@link org.apache.openmeetings.db.entity.basic.Client}
+ * @author solomax
+ *
+ */
+public interface IWsClient extends Serializable {
+       String getUid();
+       int getPageId();
+       String getSessionId();
+}
diff --git 
a/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/WsClient.java
 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/WsClient.java
new file mode 100644
index 0000000..3107d46
--- /dev/null
+++ 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/WsClient.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License") +  you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openmeetings.db.entity.basic;
+
+import java.util.UUID;
+
+/**
+ * Temporary class for test recording, will be unified
+ * @author solomax
+ *
+ */
+public class WsClient implements IWsClient {
+       private static final long serialVersionUID = 1L;
+
+       private final String sessionId;
+       private final int pageId;
+       private final String uid;
+
+       public WsClient(String sessionId, int pageId) {
+               this.sessionId = sessionId;
+               this.pageId = pageId;
+               uid = UUID.randomUUID().toString();
+       }
+       @Override
+       public String getSessionId() {
+               return sessionId;
+       }
+
+       @Override
+       public int getPageId() {
+               return pageId;
+       }
+
+       @Override
+       public String getUid() {
+               return uid;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((uid == null) ? 0 : uid.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj) {
+                       return true;
+               }
+               if (obj == null) {
+                       return false;
+               }
+               if (!(obj instanceof WsClient)) {
+                       return false;
+               }
+               WsClient other = (WsClient) obj;
+               if (uid == null) {
+                       if (other.uid != null) {
+                               return false;
+                       }
+               } else if (!uid.equals(other.uid)) {
+                       return false;
+               }
+               return true;
+       }
+
+       @Override
+       public String toString() {
+               return "Client [uid=" + uid + ", sessionId=" + sessionId + ", 
pageId=" + pageId + "]";
+       }
+}
diff --git 
a/openmeetings-util/src/main/java/org/apache/openmeetings/util/OmFileHelper.java
 
b/openmeetings-util/src/main/java/org/apache/openmeetings/util/OmFileHelper.java
index 829cc2f..458ff51 100644
--- 
a/openmeetings-util/src/main/java/org/apache/openmeetings/util/OmFileHelper.java
+++ 
b/openmeetings-util/src/main/java/org/apache/openmeetings/util/OmFileHelper.java
@@ -188,7 +188,7 @@ public class OmFileHelper {
        }
 
        public static File getStreamsSubDir(Long id) {
-               return getStreamsSubDir("" + id);
+               return getStreamsSubDir(String.valueOf(id));
        }
 
        public static File getStreamsSubDir(String name) {
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 1db863e..b72dbcd 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
@@ -168,7 +168,7 @@ public class MainPanel extends Panel {
                                        try {
                                                m = new 
JSONObject(msg.getText());
                                                if 
(KURENTO_TYPE.equals(m.optString("type"))) {
-                                                       kHandler.onMessage(uid, 
m);
+                                                       
kHandler.onMessage(getClient(), m);
                                                } else {
                                                        BasePanel p = 
getCurrentPanel();
                                                        if (p != null) {
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 c887f09..4ff7ca9 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
@@ -29,6 +29,7 @@ import org.apache.commons.lang3.time.FastDateFormat;
 import org.apache.openmeetings.core.remote.KurentoHandler;
 import org.apache.openmeetings.db.dao.record.RecordingDao;
 import org.apache.openmeetings.db.dao.room.RoomDao;
+import org.apache.openmeetings.db.entity.basic.WsClient;
 import org.apache.openmeetings.db.entity.record.Recording;
 import org.apache.openmeetings.db.entity.room.Invitation;
 import org.apache.openmeetings.db.entity.room.Invitation.Valid;
@@ -55,6 +56,7 @@ import 
org.apache.wicket.protocol.ws.api.WebSocketRequestHandler;
 import org.apache.wicket.protocol.ws.api.message.AbortedMessage;
 import org.apache.wicket.protocol.ws.api.message.AbstractClientMessage;
 import org.apache.wicket.protocol.ws.api.message.ClosedMessage;
+import org.apache.wicket.protocol.ws.api.message.ConnectedMessage;
 import org.apache.wicket.protocol.ws.api.message.ErrorMessage;
 import org.apache.wicket.protocol.ws.api.message.TextMessage;
 import org.apache.wicket.request.IRequestParameters;
@@ -186,6 +188,13 @@ public class HashPage extends BaseInitedPage implements 
IUpdatable {
                                                }
                                        }, new WebSocketBehavior() { //This WS 
will not be created in room
                                                private static final long 
serialVersionUID = 1L;
+                                               private WsClient c = null;
+
+                                               @Override
+                                               protected void 
onConnect(ConnectedMessage message) {
+                                                       
super.onConnect(message);
+                                                       c = new 
WsClient(message.getSessionId(), message.getKey().hashCode());
+                                               }
 
                                                @Override
                                                protected void 
onMessage(WebSocketRequestHandler handler, TextMessage msg) {
@@ -193,7 +202,7 @@ public class HashPage extends BaseInitedPage implements 
IUpdatable {
                                                        try {
                                                                m = new 
JSONObject(msg.getText());
                                                                if 
(KURENTO_TYPE.equals(m.optString("type"))) {
-                                                                       
kHandler.onMessage(null, m);
+                                                                       
kHandler.onMessage(c, m);
                                                                }
                                                        } catch (Exception e) {
                                                                //no-op
diff --git 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomResourceReference.java
 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomResourceReference.java
index 01e54bb..d41fb5c 100644
--- 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomResourceReference.java
+++ 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomResourceReference.java
@@ -24,7 +24,7 @@ import static 
org.apache.openmeetings.util.OmFileHelper.EXTENSION_PNG;
 import static org.apache.openmeetings.util.OmFileHelper.JPG_MIME_TYPE;
 import static org.apache.openmeetings.util.OmFileHelper.MP4_MIME_TYPE;
 import static org.apache.openmeetings.util.OmFileHelper.PNG_MIME_TYPE;
-import static org.apache.openmeetings.util.OmFileHelper.getOmHome;
+import static org.apache.openmeetings.util.OmFileHelper.getPublicDir;
 import static org.apache.openmeetings.web.app.Application.getBean;
 import static org.apache.openmeetings.web.app.WebSession.getUserId;
 
@@ -124,7 +124,7 @@ public class RoomResourceReference extends 
FileItemResourceReference<FileItem> {
        protected File getFile(FileItem f, String ext) {
                File file = f.getFile(ext);
                if (file == null || !file.exists()) {
-                       file = new File(new File(getOmHome(), "default"), 
String.format("deleted.%s", EXTENSION_PNG));
+                       file = new File(getPublicDir(), 
String.format("deleted.%s", EXTENSION_PNG));
                }
                return file;
        }
diff --git 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/VideoSettings.html
 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/VideoSettings.html
index b6df63d..ef379d5 100644
--- 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/VideoSettings.html
+++ 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/VideoSettings.html
@@ -71,7 +71,10 @@
                                </div>
                        </div>
                        <div class="vid-block">
-                               <div class="video-conainer"><video 
autoplay="autoplay"></video></div>
+                               <div class="video-conainer">
+                                       <div class="timer"><span 
class="time"></span>&nbsp;<wicket:message key="network.test.sec"/></div>
+                                       <video autoplay="autoplay"></video>
+                               </div>
                                <div class="level-meter" 
wicket:message="title:767"></div>
                                <div class="sett-row right">
                                        <div><button 
class="play"><wicket:message key="764"/></button></div>
diff --git 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/settings-base.js
 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/settings-base.js
index 3a07d64..893bcaa 100644
--- 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/settings-base.js
+++ 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/settings-base.js
@@ -1,6 +1,6 @@
 /* Licensed under the Apache License, Version 2.0 (the "License") 
http://www.apache.org/licenses/LICENSE-2.0 */
 var VideoSettings = (function() {
-       let vs, lm, s, cam, mic, res, o, rtcPeer, offerSdp
+       let vs, lm, s, cam, mic, res, o, rtcPeer, offerSdp, timer
                , vidScroll, vid, recBtn, playBtn, recAllowed = false;
        function _load() {
                s = Settings.load();
@@ -35,6 +35,9 @@ var VideoSettings = (function() {
                        rtcPeer.dispose();
                }
                offerSdp = null;
+       }
+       function _close() {
+               _clear();
                Wicket.Event.unsubscribe("/websocket/message", _onWsMessage);
        }
        function _init(options) {
@@ -45,9 +48,10 @@ var VideoSettings = (function() {
                mic = vs.find('select.mic');
                res = vs.find('select.cam-resolution');
                vidScroll = vs.find('.vid-block .video-conainer');
+               timer = vidScroll.find('.timer');
                vid = vidScroll.find('video');
                recBtn = vs.find('.rec-start').click(function() {
-                       recBtn.prop('disabled', true).button('refresh'); //TODO 
disable drop-downs
+                       recBtn.prop('disabled', true).button('refresh');
                        cam.prop('disabled', true);
                        mic.prop('disabled', true);
                        res.prop('disabled', true);
@@ -57,10 +61,20 @@ var VideoSettings = (function() {
                        OmUtil.sendMessage({
                                id : 'testStart'
                                , type: 'kurento'
+                               , mode: 'test'
                                , sdpOffer: offerSdp
                                , video: cnts.video !== false
                                , audio: cnts.audio !== false
                        });
+                       rtcPeer.on('icecandidate', function (candidate) {
+                                       console.log('Local candidate' + 
JSON.stringify(candidate));
+                                       OmUtil.sendMessage({
+                                               id : 'onTestIceCandidate'
+                                               , type: 'kurento'
+                                               , mode: 'test'
+                                               , candidate: candidate
+                                       });
+                               });
                });
                playBtn = vs.find('.play').click(function() {
                        //FIXME TODO swf.play();
@@ -79,20 +93,20 @@ var VideoSettings = (function() {
                                        }
                                        , click: function() {
                                                _save(true);
-                                               _clear();
+                                               _close();
                                                vs.dialog("close");
                                        }
                                }
                                , {
                                        text: vs.data('btn-cancel')
                                        , click: function() {
-                                               _clear();
+                                               _close();
                                                vs.dialog("close");
                                        }
                                }
                        ]
                        , close: function() {
-                               _clear();
+                               _close();
                        }
                });
                lm.progressbar({ value: 0 });
@@ -157,28 +171,16 @@ var VideoSettings = (function() {
                _clear();
                const cnts = _constraints();
                if (cnts.video !== false || cnts.audio !== false) {
-                       const options = {
-                               localVideo: vid[0]
-                               , mediaConstraints: cnts
-                               , onicecandidate: function (candidate) {
-                                       console.log('Local candidate' + 
JSON.stringify(candidate));
-                                       OmUtil.sendMessage({
-                                               id : 'onTestIceCandidate'
-                                               , type: 'kurento'
-                                               , candidate: candidate
-                                       });
-                               }
-
-                       }
                        rtcPeer = new 
kurentoUtils.WebRtcPeer.WebRtcPeerSendonly(
-                               options
-                               , function(error) {
+                               {
+                                       localVideo: vid[0], mediaConstraints: 
cnts
+                               }, function(error) {
                                        if (error) {
                                                return _error(error);
                                        }
                                        rtcPeer.generateOffer(function(error, 
_offerSdp) {
                                                if (error) {
-                                                       return 
console.error('Error generating the offer');
+                                                       return _error('Error 
generating the offer');
                                                }
                                                offerSdp = _offerSdp;
                                                _allowRec(true);
@@ -266,6 +268,7 @@ var VideoSettings = (function() {
        function _open() {
                Wicket.Event.subscribe("/websocket/message", _onWsMessage);
                recAllowed = false;
+               timer.hide();
                vs.dialog('open');
                _load();
                _initDevices();
@@ -277,43 +280,44 @@ var VideoSettings = (function() {
                                return; //ping
                        }
                        const m = jQuery.parseJSON(msg);
-                       if (m && 'kurento' === m.type) {
-                               console.info('Received message: ' + m);
-                               /* FIXME TODO
+                       if (m && 'kurento' === m.type && 'test' === m.mode) {
+                               console.info('Received message: ', m);
                                switch (m.id) {
-                                       case 'broadcast':
-                                               onBroadcast(m);
+                                       case 'testStartResponse':
+                                               console.log('SDP answer 
received from server. Processing ...');
+
+                                               
rtcPeer.processAnswer(m.sdpAnswer, function(error) {
+                                                       if (error) {
+                                                               return 
_error(error);
+                                                       }
+                                               });
                                                break;
-                                       case 'videoResponse':
-                                               onVideoResponse(m);
+                                       case 'testIceCandidate':
+                                               
rtcPeer.addIceCandidate(m.candidate, function(error) {
+                                                       if (error) {
+                                                               return 
_error('Error adding candidate: ' + error);
+                                                       }
+                                               });
                                                break;
-                                       case 'iceCandidate':
-                                               {
-                                                       const w = $('#' + 
VideoUtil.getVid(m.uid))
-                                                               , v = w.data()
-
-                                                       
v.getPeer().addIceCandidate(m.candidate, function (error) {
-                                                               if (error) {
-                                                                       
console.error("Error adding candidate: " + error);
-                                                                       return;
-                                                               }
-                                                       });
-                                               }
+                                       case 'testRecording':
+                                               
timer.show().find('.time').text(m.time);
+                                               break;
+                                       case 'testStopped':
+                                               timer.hide();
                                                break;
                                        default:
-                                               console.error('Unrecognized 
message', m);
+                                               _error('Unrecognized message', 
m);
                                }
-                               */
                        }
                } catch (err) {
                        //no-op
-                       console.error(err);
+                       _error(err);
                }
        }
        return {
                init: _init
                , open: _open
-               , close: function() { vs.dialog('close'); }
+               , close: function() { _close(); vs.dialog('close'); }
                , load: _load
                , save: _save
        };
diff --git a/openmeetings-web/src/main/webapp/WEB-INF/web.xml 
b/openmeetings-web/src/main/webapp/WEB-INF/web.xml
index 1a3fdc7..c13cab4 100644
--- a/openmeetings-web/src/main/webapp/WEB-INF/web.xml
+++ b/openmeetings-web/src/main/webapp/WEB-INF/web.xml
@@ -47,8 +47,7 @@
                </init-param>
                <init-param>
                        <param-name>ignorePaths</param-name>
-                       <!-- FIXME TODO check all this -->
-                       
<param-value>media,conf,css,default,docs,images,js,persistence,public,screenshare,streams,upload,uploadtemp,services,DownloadHandler</param-value>
+                       
<param-value>conf,css,docs,images,js,persistence,public,screenshare,streams,upload,services</param-value>
                </init-param>
        </filter>
        <filter-mapping>
diff --git a/openmeetings-web/src/main/webapp/css/general.css 
b/openmeetings-web/src/main/webapp/css/general.css
index 1d4f227..1c25fb6 100644
--- a/openmeetings-web/src/main/webapp/css/general.css
+++ b/openmeetings-web/src/main/webapp/css/general.css
@@ -69,7 +69,7 @@ html, body {
        position: absolute;
        right: 0;
        margin: 2px;
-       background-image: url(../images/ajax-loader.gif);
+       background-image: url(images/ajax-loader.gif);
        background-repeat: no-repeat;
        background-size: 28px 28px;
 }
diff --git a/openmeetings-web/src/main/webapp/images/ajax-loader.gif 
b/openmeetings-web/src/main/webapp/css/images/ajax-loader.gif
similarity index 100%
rename from openmeetings-web/src/main/webapp/images/ajax-loader.gif
rename to openmeetings-web/src/main/webapp/css/images/ajax-loader.gif
diff --git a/openmeetings-web/src/main/webapp/css/room.css 
b/openmeetings-web/src/main/webapp/css/room.css
index d485193..7fcfb8b 100644
--- a/openmeetings-web/src/main/webapp/css/room.css
+++ b/openmeetings-web/src/main/webapp/css/room.css
@@ -349,6 +349,13 @@
 .ui-dialog.video .vid-block .video-conainer {
        overflow: auto;
        max-height: 300px;
+       position: relative;
+}
+.ui-dialog.video .vid-block .video-conainer .timer {
+       background-color:grey;
+       width: 2.2em;
+       height: 1em;
+       position:absolute;
 }
 .ui-dialog.video .sett-row select, .ui-dialog.video .level-meter {
        width: 250px;
diff --git a/openmeetings-web/src/main/webapp/images/delete.gif 
b/openmeetings-web/src/main/webapp/images/delete.gif
deleted file mode 100644
index b6922ac..0000000
Binary files a/openmeetings-web/src/main/webapp/images/delete.gif and /dev/null 
differ
diff --git a/openmeetings-web/src/main/webapp/images/down.png 
b/openmeetings-web/src/main/webapp/images/down.png
deleted file mode 100644
index f070ea6..0000000
Binary files a/openmeetings-web/src/main/webapp/images/down.png and /dev/null 
differ
diff --git a/openmeetings-web/src/main/webapp/images/edit.png 
b/openmeetings-web/src/main/webapp/images/edit.png
deleted file mode 100644
index 2e2a1c4..0000000
Binary files a/openmeetings-web/src/main/webapp/images/edit.png and /dev/null 
differ
diff --git a/openmeetings-web/src/main/webapp/images/error.png 
b/openmeetings-web/src/main/webapp/images/error.png
deleted file mode 100644
index 628cf2d..0000000
Binary files a/openmeetings-web/src/main/webapp/images/error.png and /dev/null 
differ
diff --git a/openmeetings-web/src/main/webapp/images/info.png 
b/openmeetings-web/src/main/webapp/images/info.png
deleted file mode 100644
index 12cd1ae..0000000
Binary files a/openmeetings-web/src/main/webapp/images/info.png and /dev/null 
differ
diff --git a/openmeetings-web/src/main/webapp/images/level_meter.png 
b/openmeetings-web/src/main/webapp/images/level_meter.png
deleted file mode 100644
index 78192ef..0000000
Binary files a/openmeetings-web/src/main/webapp/images/level_meter.png and 
/dev/null differ
diff --git a/openmeetings-web/src/main/webapp/images/refresh.gif 
b/openmeetings-web/src/main/webapp/images/refresh.gif
deleted file mode 100644
index 7aff1a9..0000000
Binary files a/openmeetings-web/src/main/webapp/images/refresh.gif and 
/dev/null differ
diff --git a/openmeetings-web/src/main/webapp/images/up.png 
b/openmeetings-web/src/main/webapp/images/up.png
deleted file mode 100644
index 5d10417..0000000
Binary files a/openmeetings-web/src/main/webapp/images/up.png and /dev/null 
differ
diff --git a/openmeetings-web/src/main/webapp/default/deleted.odp 
b/openmeetings-web/src/main/webapp/public/deleted.odp
similarity index 100%
rename from openmeetings-web/src/main/webapp/default/deleted.odp
rename to openmeetings-web/src/main/webapp/public/deleted.odp
diff --git a/openmeetings-web/src/main/webapp/default/deleted.pdf 
b/openmeetings-web/src/main/webapp/public/deleted.pdf
similarity index 100%
rename from openmeetings-web/src/main/webapp/default/deleted.pdf
rename to openmeetings-web/src/main/webapp/public/deleted.pdf
diff --git a/openmeetings-web/src/main/webapp/default/deleted.png 
b/openmeetings-web/src/main/webapp/public/deleted.png
similarity index 100%
rename from openmeetings-web/src/main/webapp/default/deleted.png
rename to openmeetings-web/src/main/webapp/public/deleted.png
diff --git a/pom.xml b/pom.xml
index 1e479f1..3e9487d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,7 +61,7 @@
                <wicket.version>8.0.0-M9</wicket.version>
                <wicketju.version>8.0.0-M9.2</wicketju.version>
                <wickets.version>8.0.0-M9</wickets.version>
-               <red5-client.version>1.0.10-M4</red5-client.version>
+               <red5-client.version>1.0.10-M5</red5-client.version>
                <spring.version>4.3.14.RELEASE</spring.version>
                <mina.version>2.0.16</mina.version>
                <tomcat.version>9.0.6</tomcat.version>

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to