Repository: openmeetings
Updated Branches:
  refs/heads/master 51d669a97 -> 92e2d79dd


[OPENMEETINGS-1714] more issues are fixed


Project: http://git-wip-us.apache.org/repos/asf/openmeetings/repo
Commit: http://git-wip-us.apache.org/repos/asf/openmeetings/commit/92e2d79d
Tree: http://git-wip-us.apache.org/repos/asf/openmeetings/tree/92e2d79d
Diff: http://git-wip-us.apache.org/repos/asf/openmeetings/diff/92e2d79d

Branch: refs/heads/master
Commit: 92e2d79ddc9ebdb8d35ebb52e67ec064c93b680c
Parents: 51d669a
Author: Maxim Solodovnik <[email protected]>
Authored: Fri Oct 13 23:15:45 2017 +0700
Committer: Maxim Solodovnik <[email protected]>
Committed: Fri Oct 13 23:15:45 2017 +0700

----------------------------------------------------------------------
 .../core/remote/RecordingService.java           | 373 -------------------
 .../core/remote/ScopeApplicationAdapter.java    |   1 +
 .../core/service/RecordingService.java          | 367 ++++++++++++++++++
 .../apache/openmeetings/rdc/KeyCodesTest.java   |   4 -
 .../openmeetings/rdc/ReadKeyCodesTest.java      |   4 -
 5 files changed, 368 insertions(+), 381 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/openmeetings/blob/92e2d79d/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java
----------------------------------------------------------------------
diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java
deleted file mode 100644
index c270f59..0000000
--- 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/RecordingService.java
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * 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.ScopeApplicationAdapter.getApp;
-import static 
org.apache.openmeetings.util.OpenmeetingsVariables.getWebAppRootKey;
-
-import java.util.Date;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.openmeetings.IApplication;
-import org.apache.openmeetings.core.converter.BaseConverter;
-import 
org.apache.openmeetings.core.data.record.converter.InterviewConverterTask;
-import 
org.apache.openmeetings.core.data.record.converter.RecordingConverterTask;
-import org.apache.openmeetings.core.data.record.listener.StreamListener;
-import org.apache.openmeetings.core.util.IClientUtil;
-import org.apache.openmeetings.core.util.WebSocketHelper;
-import org.apache.openmeetings.db.dao.record.RecordingDao;
-import org.apache.openmeetings.db.dao.record.RecordingMetaDataDao;
-import org.apache.openmeetings.db.dao.server.ISessionManager;
-import org.apache.openmeetings.db.dao.user.UserDao;
-import org.apache.openmeetings.db.entity.basic.Client;
-import org.apache.openmeetings.db.entity.basic.IClient;
-import org.apache.openmeetings.db.entity.file.BaseFileItem.Type;
-import org.apache.openmeetings.db.entity.record.Recording;
-import org.apache.openmeetings.db.entity.record.RecordingMetaData;
-import org.apache.openmeetings.db.entity.record.RecordingMetaData.Status;
-import org.apache.openmeetings.db.entity.room.StreamClient;
-import org.apache.openmeetings.db.entity.user.User;
-import org.apache.openmeetings.util.CalendarPatterns;
-import org.apache.openmeetings.util.message.RoomMessage;
-import org.apache.openmeetings.util.message.TextRoomMessage;
-import org.red5.logging.Red5LoggerFactory;
-import org.red5.server.api.IConnection;
-import org.red5.server.api.scope.IScope;
-import org.red5.server.api.service.IPendingServiceCall;
-import org.red5.server.api.service.IPendingServiceCallback;
-import org.red5.server.api.service.IServiceCapableConnection;
-import org.red5.server.api.stream.IBroadcastStream;
-import org.red5.server.api.stream.IStreamListener;
-import org.red5.server.stream.ClientBroadcastStream;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import com.github.openjson.JSONObject;
-
-@Service
-public class RecordingService implements IPendingServiceCallback {
-       private static final Logger log = 
Red5LoggerFactory.getLogger(RecordingService.class, getWebAppRootKey());
-
-       /**
-        * Stores a reference to all available listeners we need that 
reference, as the internal references stored with the
-        * red5 stream object might be gone when the user closes the browser. 
But each listener has an asynchronous
-        * component that needs to be closed no matter how the user leaves the 
application!
-        */
-       private static final Map<Long, StreamListener> streamListeners = new 
ConcurrentHashMap<>();
-
-       // Spring Beans
-       @Autowired
-       private ISessionManager sessionManager;
-       @Autowired
-       private UserDao userDao;
-       @Autowired
-       private RecordingConverterTask recordingConverter;
-       @Autowired
-       private InterviewConverterTask interviewConverter;
-       @Autowired
-       private RecordingDao recordingDao;
-       @Autowired
-       private ScopeApplicationAdapter scopeAdapter;
-       @Autowired
-       private RecordingMetaDataDao metaDataDao;
-
-       @Override
-       public void resultReceived(IPendingServiceCall arg0) {
-               //no-op
-       }
-
-       private static String generateFileName(Long recordingId, String 
streamid) {
-               String dateString = CalendarPatterns.getTimeForStreamId(new 
Date());
-               return "rec_" + recordingId + "_stream_" + streamid + "_" + 
dateString;
-       }
-
-       public void startRecording(final IScope scope, IClient client, boolean 
isInterview) {
-               try {
-                       log.debug("##REC:: recordMeetingStream ::");
-
-                       Long roomId = client.getRoomId();
-
-                       Date now = new Date();
-
-                       Recording recording = new Recording();
-
-                       recording.setHash(UUID.randomUUID().toString());
-                       recording.setName(String.format("%s %s", isInterview ? 
"Interview" : "Recording", CalendarPatterns.getDateWithTimeByMiliSeconds(new 
Date())));
-                       Long ownerId = client.getUserId();
-                       User u = userDao.get(ownerId);
-                       if (u != null && User.Type.contact == u.getType()) {
-                               ownerId = u.getOwnerId();
-                       }
-                       recording.setInsertedBy(ownerId);
-                       recording.setType(Type.Recording);
-                       recording.setInterview(isInterview);
-
-                       recording.setRoomId(roomId);
-                       recording.setRecordStart(now);
-
-                       if (!isInterview) {
-                               recording.setWidth(client.getWidth());
-                               recording.setHeight(client.getHeight());
-                       }
-
-                       recording.setOwnerId(ownerId);
-                       recording.setStatus(Recording.Status.RECORDING);
-                       recording = recordingDao.update(recording);
-                       // Receive recordingId
-                       Long recordingId = recording.getId();
-                       IClientUtil.setRecordingId(scope, recordingId);
-                       log.debug("##REC:: recording created by USER: {}", 
ownerId);
-
-                       // Update Client and set Flag
-                       client.setRecordingStarted(true);
-                       if (!(client instanceof Client)) {
-                               IApplication iapp = getApp();
-                               Client c = 
iapp.getOmClientBySid(client.getSid());
-                               c.setRecordingId(recordingId);
-                               c.setRecordingStarted(true);
-                               iapp.update(c);
-                       }
-                       sessionManager.update(client);
-
-                       // get all stream and start recording them
-                       for (IConnection conn : scope.getClientConnections()) {
-                               if (conn != null && conn instanceof 
IServiceCapableConnection) {
-                                       startStreamRecord(conn, recordingId, 
isInterview);
-                               }
-                       }
-                       // Send every user a notification that the recording 
did start
-                       WebSocketHelper.sendRoom(new TextRoomMessage(roomId, 
ownerId, RoomMessage.Type.recordingStarted
-                                       , new JSONObject().put("uid", 
client.getUid()).put("sid", client.getSid()).toString()));
-               } catch (Exception err) {
-                       log.error("[startRecording]", err);
-               }
-       }
-
-       public void stopRecording(IScope scope, IClient client) {
-               try {
-                       Long recordingId = IClientUtil.getRecordingId(scope);
-                       log.debug("stopRecordAndSave {}, {}, ID: {}", 
client.getLogin(), client.getRemoteAddress(), recordingId);
-                       if (recordingId == null) {
-                               log.error("Unable to find recordingId on 
recording stop");
-                               return;
-                       }
-                       IApplication iapp = getApp();
-                       Client recClient = null;
-                       for (Client c : 
iapp.getOmRoomClients(client.getRoomId())) {
-                               if (c.getRecordingId() != null) {
-                                       recClient = c;
-                                       break;
-                               }
-                       }
-                       if (recClient == null) {
-                               log.warn("Unable to find Recording client");
-                       } else {
-                               WebSocketHelper.sendRoom(new 
TextRoomMessage(recClient.getRoomId(), recClient.getUserId(), 
RoomMessage.Type.recordingStoped, recClient.getSid()));
-                               // Store to database
-                               recClient.setRecordingId(null);
-                               recClient.setRecordingStarted(false);
-                               sessionManager.update(recClient);
-                       }
-                       // get all stream and stop recording them
-                       for (IConnection conn : scope.getClientConnections()) {
-                               if (conn != null && conn instanceof 
IServiceCapableConnection) {
-                                       StreamClient rcl = 
sessionManager.get(IClientUtil.getId(conn.getClient()));
-                                       stopStreamRecord(scope, rcl);
-                               }
-                       }
-                       recordingDao.updateEndTime(recordingId, new Date());
-
-                       // Reset values
-                       log.debug("recordingConverterTask {}", 
recordingConverter);
-
-                       Recording recording = recordingDao.get(recordingId);
-                       if (recording.isInterview()) {
-                               
interviewConverter.startConversionThread(recordingId);
-                       } else {
-                               
recordingConverter.startConversionThread(recordingId);
-                       }
-               } catch (Exception err) {
-                       log.error("[-- stopRecording --]", err);
-               }
-       }
-
-       /**
-        * Start recording the published stream for the specified broadcast-Id
-        *
-        * @param conn
-        * @param broadcastid
-        * @param streamName
-        * @param metaId
-        * @param isScreenSharing
-        * @param isInterview
-        */
-       private void addListener(IConnection conn, String broadcastid, String 
streamName, Long metaId, boolean isScreenSharing, boolean isInterview) {
-               log.debug("Recording show for: {}", 
conn.getScope().getContextPath());
-               log.debug("Name of CLient and Stream to be recorded: {}", 
broadcastid);
-               log.debug("Scope " + conn);
-               log.debug("Scope " + conn.getScope());
-               // Get a reference to the current broadcast stream.
-               ClientBroadcastStream stream = (ClientBroadcastStream) 
scopeAdapter.getBroadcastStream(conn.getScope(), broadcastid);
-
-               if (stream == null) {
-                       log.debug("Unable to get stream: {}", streamName);
-                       return;
-               }
-               // Save the stream to disk.
-               log.debug("### stream: [{}, name: {}, scope: {}, metaId: {}, 
sharing ? {}, interview ? {}]"
-                               , stream, streamName, conn.getScope(), metaId, 
isScreenSharing, isInterview);
-               StreamListener streamListener = new 
StreamListener(!isScreenSharing, streamName, conn.getScope(), metaId, 
isScreenSharing, isInterview);
-
-               streamListeners.put(metaId, streamListener);
-               stream.addStreamListener(streamListener);
-       }
-
-       /**
-        * Stops recording the publishing stream for the specified IConnection.
-        *
-        * @param scope
-        * @param broadcastId
-        * @param metaId
-        */
-       public void removeListener(IScope scope, String broadcastId, Long 
metaId) {
-               try {
-                       log.debug("** removeListener: scope: {}, broadcastId: 
{} || {}", scope, broadcastId, scope.getContextPath());
-
-                       IBroadcastStream stream = 
scopeAdapter.getBroadcastStream(scope, broadcastId);
-
-                       // the stream can be null if the user just closes the 
browser
-                       // without canceling the recording before leaving
-                       // Iterate through all stream listeners and stop the 
appropriate
-                       if (stream != null && stream.getStreamListeners() != 
null) {
-                               for (IStreamListener iStreamListener : 
stream.getStreamListeners()) {
-                                       
stream.removeStreamListener(iStreamListener);
-                               }
-                       }
-
-                       if (metaId == null) {
-                               // this should be fixed, can be useful for 
debugging, after all this is an error
-                               // but we don't want the application to 
completely stop the process
-                               log.error("recordingMetaDataId is null");
-                               return;
-                       }
-
-                       StreamListener listenerAdapter = 
streamListeners.get(metaId);
-                       log.debug("Stream Closing :: " + metaId);
-
-                       RecordingMetaData metaData = metaDataDao.get(metaId);
-                       BaseConverter.printMetaInfo(metaData, "Stopping the 
stream");
-                       // Manually call finish on the stream so that there is 
no endless loop waiting in the RecordingConverter waiting for the stream to 
finish
-                       // this would normally happen in the Listener
-                       Status s = metaData.getStreamStatus();
-                       if (Status.NONE == s) {
-                               log.debug("Stream was not started, no need to 
stop :: stream with id {}", metaId);
-                       } else {
-                               metaData.setStreamStatus(listenerAdapter == 
null && s == Status.STARTED ? Status.STOPPED : Status.STOPPING);
-                               log.debug("Stopping the stream :: New status == 
{}", metaData.getStreamStatus());
-                       }
-                       metaDataDao.update(metaData);
-                       if (listenerAdapter == null) {
-                               log.debug("Stream Not Found :: " + metaId);
-                               log.debug("Available Streams :: " + 
streamListeners.size());
-
-                               for (Long entryKey : streamListeners.keySet()) {
-                                       log.debug("Stored recordingMetaDataId 
in Map: {}", entryKey);
-                               }
-                               throw new IllegalStateException("Could not find 
Listener to stop! metaId " + metaId);
-                       }
-
-                       listenerAdapter.closeStream();
-                       streamListeners.remove(metaId);
-
-               } catch (Exception err) {
-                       log.error("[removeListener]", err);
-               }
-       }
-
-       public void stopStreamRecord(IScope scope, StreamClient rcl) {
-               if (rcl == null || rcl.getMetaId() == null || 
rcl.getBroadcastId() == null) {
-                       return;
-               }
-               log.debug("is this users still alive? stop it : {}", rcl);
-
-               removeListener(scope, rcl.getBroadcastId(), rcl.getMetaId());
-
-               // Update Meta Data
-               metaDataDao.updateEndDate(rcl.getMetaId(), new Date());
-
-               // Remove Meta Data
-               rcl.setMetaId(null);
-               sessionManager.update(rcl);
-       }
-
-       public void startStreamRecord(IConnection conn) {
-               Long recordingId = IClientUtil.getRecordingId(conn.getScope());
-               Recording rec = recordingDao.get(recordingId);
-               startStreamRecord(conn, recordingId, rec.isInterview());
-       }
-
-       public void startStreamRecord(IConnection conn, Long recordingId, 
boolean isInterview) {
-               Date now = new Date();
-
-               StreamClient rcl = 
sessionManager.get(IClientUtil.getId(conn.getClient()));
-               String broadcastId = rcl.getBroadcastId();
-               if (rcl.getMetaId() != null && 
streamListeners.get(rcl.getMetaId()) != null) {
-                       log.debug("startStreamRecord[{}]:: existing metaId: 
{}", broadcastId, rcl.getMetaId());
-                       return;
-               }
-
-               // If its the recording client we need another type of Meta Data
-               if (broadcastId != null) {
-                       boolean audioOnly = "a".equals(rcl.getAvsettings());
-                       boolean videoOnly = "v".equals(rcl.getAvsettings());
-                       if (Client.Type.sharing == rcl.getType()) {
-                               if (rcl.isSharingStarted() || 
rcl.isRecordingStarted()) {
-                                       String streamName = 
generateFileName(recordingId, broadcastId);
-
-                                       Long metaId = 
metaDataDao.add(recordingId, now, false, false, true, streamName, null);
-
-                                       // Start FLV Recording
-                                       addListener(conn, rcl.getBroadcastId(), 
streamName, metaId, true, isInterview);
-
-                                       // Add Meta Data
-                                       rcl.setMetaId(metaId);
-                                       sessionManager.update(rcl);
-                               }
-                       } else if ("av".equals(rcl.getAvsettings()) || 
audioOnly || videoOnly) {
-                               // if the user does publish av, a, v
-                               // But we only record av or a, video only is 
not interesting
-                               String streamName = 
generateFileName(recordingId, broadcastId);
-
-                               Long metaId = metaDataDao.add(recordingId, now, 
audioOnly, videoOnly, false, streamName,
-                                               rcl.getInterviewPodId());
-
-                               // Start FLV recording
-                               addListener(conn, broadcastId, streamName, 
metaId, !audioOnly, isInterview);
-
-                               // Add Meta Data
-                               rcl.setMetaId(metaId);
-                               sessionManager.update(rcl);
-                       }
-               }
-               log.debug("startStreamRecord[{}]:: resulting metaId: {}", 
broadcastId, rcl.getMetaId());
-       }
-}

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/92e2d79d/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ScopeApplicationAdapter.java
----------------------------------------------------------------------
diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ScopeApplicationAdapter.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ScopeApplicationAdapter.java
index 75c78c8..8ee0499 100644
--- 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ScopeApplicationAdapter.java
+++ 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/ScopeApplicationAdapter.java
@@ -37,6 +37,7 @@ import java.util.Map;
 import java.util.UUID;
 
 import org.apache.openmeetings.IApplication;
+import org.apache.openmeetings.core.service.RecordingService;
 import org.apache.openmeetings.core.util.IClientUtil;
 import org.apache.openmeetings.core.util.WebSocketHelper;
 import org.apache.openmeetings.db.dao.basic.ConfigurationDao;

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/92e2d79d/openmeetings-core/src/main/java/org/apache/openmeetings/core/service/RecordingService.java
----------------------------------------------------------------------
diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/service/RecordingService.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/service/RecordingService.java
new file mode 100644
index 0000000..18bfa4e
--- /dev/null
+++ 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/service/RecordingService.java
@@ -0,0 +1,367 @@
+/*
+ * 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.service;
+
+import static 
org.apache.openmeetings.core.remote.ScopeApplicationAdapter.getApp;
+import static 
org.apache.openmeetings.util.OpenmeetingsVariables.getWebAppRootKey;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.openmeetings.IApplication;
+import org.apache.openmeetings.core.converter.BaseConverter;
+import 
org.apache.openmeetings.core.data.record.converter.InterviewConverterTask;
+import 
org.apache.openmeetings.core.data.record.converter.RecordingConverterTask;
+import org.apache.openmeetings.core.data.record.listener.StreamListener;
+import org.apache.openmeetings.core.remote.ScopeApplicationAdapter;
+import org.apache.openmeetings.core.util.IClientUtil;
+import org.apache.openmeetings.core.util.WebSocketHelper;
+import org.apache.openmeetings.db.dao.record.RecordingDao;
+import org.apache.openmeetings.db.dao.record.RecordingMetaDataDao;
+import org.apache.openmeetings.db.dao.server.ISessionManager;
+import org.apache.openmeetings.db.dao.user.UserDao;
+import org.apache.openmeetings.db.entity.basic.Client;
+import org.apache.openmeetings.db.entity.basic.IClient;
+import org.apache.openmeetings.db.entity.file.BaseFileItem.Type;
+import org.apache.openmeetings.db.entity.record.Recording;
+import org.apache.openmeetings.db.entity.record.RecordingMetaData;
+import org.apache.openmeetings.db.entity.record.RecordingMetaData.Status;
+import org.apache.openmeetings.db.entity.room.StreamClient;
+import org.apache.openmeetings.db.entity.user.User;
+import org.apache.openmeetings.util.CalendarPatterns;
+import org.apache.openmeetings.util.message.RoomMessage;
+import org.apache.openmeetings.util.message.TextRoomMessage;
+import org.red5.logging.Red5LoggerFactory;
+import org.red5.server.api.IConnection;
+import org.red5.server.api.scope.IScope;
+import org.red5.server.api.service.IServiceCapableConnection;
+import org.red5.server.api.stream.IBroadcastStream;
+import org.red5.server.api.stream.IStreamListener;
+import org.red5.server.stream.ClientBroadcastStream;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.github.openjson.JSONObject;
+
+@Service
+public class RecordingService {
+       private static final Logger log = 
Red5LoggerFactory.getLogger(RecordingService.class, getWebAppRootKey());
+
+       /**
+        * Stores a reference to all available listeners we need that 
reference, as the internal references stored with the
+        * red5 stream object might be gone when the user closes the browser. 
But each listener has an asynchronous
+        * component that needs to be closed no matter how the user leaves the 
application!
+        */
+       private static final Map<Long, StreamListener> streamListeners = new 
ConcurrentHashMap<>();
+
+       // Spring Beans
+       @Autowired
+       private ISessionManager sessionManager;
+       @Autowired
+       private UserDao userDao;
+       @Autowired
+       private RecordingConverterTask recordingConverter;
+       @Autowired
+       private InterviewConverterTask interviewConverter;
+       @Autowired
+       private RecordingDao recordingDao;
+       @Autowired
+       private ScopeApplicationAdapter scopeAdapter;
+       @Autowired
+       private RecordingMetaDataDao metaDataDao;
+
+       private static String generateFileName(Long recordingId, String 
streamid) {
+               String dateString = CalendarPatterns.getTimeForStreamId(new 
Date());
+               return "rec_" + recordingId + "_stream_" + streamid + "_" + 
dateString;
+       }
+
+       public void startRecording(final IScope scope, IClient client, boolean 
isInterview) {
+               try {
+                       log.debug("##REC:: recordMeetingStream ::");
+
+                       Long roomId = client.getRoomId();
+
+                       Date now = new Date();
+
+                       Recording recording = new Recording();
+
+                       recording.setHash(UUID.randomUUID().toString());
+                       recording.setName(String.format("%s %s", isInterview ? 
"Interview" : "Recording", CalendarPatterns.getDateWithTimeByMiliSeconds(new 
Date())));
+                       Long ownerId = client.getUserId();
+                       User u = userDao.get(ownerId);
+                       if (u != null && User.Type.contact == u.getType()) {
+                               ownerId = u.getOwnerId();
+                       }
+                       recording.setInsertedBy(ownerId);
+                       recording.setType(Type.Recording);
+                       recording.setInterview(isInterview);
+
+                       recording.setRoomId(roomId);
+                       recording.setRecordStart(now);
+
+                       if (!isInterview) {
+                               recording.setWidth(client.getWidth());
+                               recording.setHeight(client.getHeight());
+                       }
+
+                       recording.setOwnerId(ownerId);
+                       recording.setStatus(Recording.Status.RECORDING);
+                       recording = recordingDao.update(recording);
+                       // Receive recordingId
+                       Long recordingId = recording.getId();
+                       IClientUtil.setRecordingId(scope, recordingId);
+                       log.debug("##REC:: recording created by USER: {}", 
ownerId);
+
+                       // Update Client and set Flag
+                       client.setRecordingStarted(true);
+                       if (!(client instanceof Client)) {
+                               IApplication iapp = getApp();
+                               Client c = 
iapp.getOmClientBySid(client.getSid());
+                               c.setRecordingId(recordingId);
+                               c.setRecordingStarted(true);
+                               iapp.update(c);
+                       }
+                       sessionManager.update(client);
+
+                       // get all stream and start recording them
+                       for (IConnection conn : scope.getClientConnections()) {
+                               if (conn != null && conn instanceof 
IServiceCapableConnection) {
+                                       startStreamRecord(conn, recordingId, 
isInterview);
+                               }
+                       }
+                       // Send every user a notification that the recording 
did start
+                       WebSocketHelper.sendRoom(new TextRoomMessage(roomId, 
ownerId, RoomMessage.Type.recordingStarted
+                                       , new JSONObject().put("uid", 
client.getUid()).put("sid", client.getSid()).toString()));
+               } catch (Exception err) {
+                       log.error("[startRecording]", err);
+               }
+       }
+
+       public void stopRecording(IScope scope, IClient client) {
+               try {
+                       Long recordingId = IClientUtil.getRecordingId(scope);
+                       log.debug("stopRecordAndSave {}, {}, ID: {}", 
client.getLogin(), client.getRemoteAddress(), recordingId);
+                       if (recordingId == null) {
+                               log.error("Unable to find recordingId on 
recording stop");
+                               return;
+                       }
+                       IApplication iapp = getApp();
+                       Client recClient = null;
+                       for (Client c : 
iapp.getOmRoomClients(client.getRoomId())) {
+                               if (c.getRecordingId() != null) {
+                                       recClient = c;
+                                       break;
+                               }
+                       }
+                       if (recClient == null) {
+                               log.warn("Unable to find Recording client");
+                       } else {
+                               WebSocketHelper.sendRoom(new 
TextRoomMessage(recClient.getRoomId(), recClient.getUserId(), 
RoomMessage.Type.recordingStoped, recClient.getSid()));
+                               // Store to database
+                               recClient.setRecordingId(null);
+                               recClient.setRecordingStarted(false);
+                               sessionManager.update(recClient);
+                       }
+                       // get all stream and stop recording them
+                       for (IConnection conn : scope.getClientConnections()) {
+                               if (conn != null && conn instanceof 
IServiceCapableConnection) {
+                                       StreamClient rcl = 
sessionManager.get(IClientUtil.getId(conn.getClient()));
+                                       stopStreamRecord(scope, rcl);
+                               }
+                       }
+                       recordingDao.updateEndTime(recordingId, new Date());
+
+                       // Reset values
+                       log.debug("recordingConverterTask {}", 
recordingConverter);
+
+                       Recording recording = recordingDao.get(recordingId);
+                       if (recording.isInterview()) {
+                               
interviewConverter.startConversionThread(recordingId);
+                       } else {
+                               
recordingConverter.startConversionThread(recordingId);
+                       }
+               } catch (Exception err) {
+                       log.error("[-- stopRecording --]", err);
+               }
+       }
+
+       /**
+        * Start recording the published stream for the specified broadcast-Id
+        *
+        * @param conn
+        * @param broadcastid
+        * @param streamName
+        * @param metaId
+        * @param isScreenSharing
+        * @param isInterview
+        */
+       private void addListener(IConnection conn, String broadcastid, String 
streamName, Long metaId, boolean isScreenSharing, boolean isInterview) {
+               log.debug("Recording show for: {}", 
conn.getScope().getContextPath());
+               log.debug("Name of CLient and Stream to be recorded: {}", 
broadcastid);
+               log.debug("Scope " + conn);
+               log.debug("Scope " + conn.getScope());
+               // Get a reference to the current broadcast stream.
+               ClientBroadcastStream stream = (ClientBroadcastStream) 
scopeAdapter.getBroadcastStream(conn.getScope(), broadcastid);
+
+               if (stream == null) {
+                       log.debug("Unable to get stream: {}", streamName);
+                       return;
+               }
+               // Save the stream to disk.
+               log.debug("### stream: [{}, name: {}, scope: {}, metaId: {}, 
sharing ? {}, interview ? {}]"
+                               , stream, streamName, conn.getScope(), metaId, 
isScreenSharing, isInterview);
+               StreamListener streamListener = new 
StreamListener(!isScreenSharing, streamName, conn.getScope(), metaId, 
isScreenSharing, isInterview);
+
+               streamListeners.put(metaId, streamListener);
+               stream.addStreamListener(streamListener);
+       }
+
+       /**
+        * Stops recording the publishing stream for the specified IConnection.
+        *
+        * @param scope
+        * @param broadcastId
+        * @param metaId
+        */
+       private void removeListener(IScope scope, String broadcastId, Long 
metaId) {
+               try {
+                       log.debug("** removeListener: scope: {}, broadcastId: 
{} || {}", scope, broadcastId, scope.getContextPath());
+
+                       IBroadcastStream stream = 
scopeAdapter.getBroadcastStream(scope, broadcastId);
+
+                       // the stream can be null if the user just closes the 
browser
+                       // without canceling the recording before leaving
+                       // Iterate through all stream listeners and stop the 
appropriate
+                       if (stream != null && stream.getStreamListeners() != 
null) {
+                               for (IStreamListener iStreamListener : 
stream.getStreamListeners()) {
+                                       
stream.removeStreamListener(iStreamListener);
+                               }
+                       }
+
+                       if (metaId == null) {
+                               // this should be fixed, can be useful for 
debugging, after all this is an error
+                               // but we don't want the application to 
completely stop the process
+                               log.error("recordingMetaDataId is null");
+                               return;
+                       }
+
+                       StreamListener listenerAdapter = 
streamListeners.get(metaId);
+                       log.debug("Stream Closing :: " + metaId);
+
+                       RecordingMetaData metaData = metaDataDao.get(metaId);
+                       BaseConverter.printMetaInfo(metaData, "Stopping the 
stream");
+                       // Manually call finish on the stream so that there is 
no endless loop waiting in the RecordingConverter waiting for the stream to 
finish
+                       // this would normally happen in the Listener
+                       Status s = metaData.getStreamStatus();
+                       if (Status.NONE == s) {
+                               log.debug("Stream was not started, no need to 
stop :: stream with id {}", metaId);
+                       } else {
+                               metaData.setStreamStatus(listenerAdapter == 
null && s == Status.STARTED ? Status.STOPPED : Status.STOPPING);
+                               log.debug("Stopping the stream :: New status == 
{}", metaData.getStreamStatus());
+                       }
+                       metaDataDao.update(metaData);
+                       if (listenerAdapter == null) {
+                               log.debug("Stream Not Found :: " + metaId);
+                               log.debug("Available Streams :: " + 
streamListeners.size());
+
+                               for (Long entryKey : streamListeners.keySet()) {
+                                       log.debug("Stored recordingMetaDataId 
in Map: {}", entryKey);
+                               }
+                               throw new IllegalStateException("Could not find 
Listener to stop! metaId " + metaId);
+                       }
+
+                       listenerAdapter.closeStream();
+                       streamListeners.remove(metaId);
+
+               } catch (Exception err) {
+                       log.error("[removeListener]", err);
+               }
+       }
+
+       public void stopStreamRecord(IScope scope, StreamClient rcl) {
+               if (rcl == null || rcl.getMetaId() == null || 
rcl.getBroadcastId() == null) {
+                       return;
+               }
+               log.debug("is this users still alive? stop it : {}", rcl);
+
+               removeListener(scope, rcl.getBroadcastId(), rcl.getMetaId());
+
+               // Update Meta Data
+               metaDataDao.updateEndDate(rcl.getMetaId(), new Date());
+
+               // Remove Meta Data
+               rcl.setMetaId(null);
+               sessionManager.update(rcl);
+       }
+
+       public void startStreamRecord(IConnection conn) {
+               Long recordingId = IClientUtil.getRecordingId(conn.getScope());
+               Recording rec = recordingDao.get(recordingId);
+               startStreamRecord(conn, recordingId, rec.isInterview());
+       }
+
+       private void startStreamRecord(IConnection conn, Long recordingId, 
boolean isInterview) {
+               Date now = new Date();
+
+               StreamClient rcl = 
sessionManager.get(IClientUtil.getId(conn.getClient()));
+               String broadcastId = rcl.getBroadcastId();
+               if (rcl.getMetaId() != null && 
streamListeners.get(rcl.getMetaId()) != null) {
+                       log.debug("startStreamRecord[{}]:: existing metaId: 
{}", broadcastId, rcl.getMetaId());
+                       return;
+               }
+
+               // If its the recording client we need another type of Meta Data
+               if (broadcastId != null) {
+                       boolean audioOnly = "a".equals(rcl.getAvsettings());
+                       boolean videoOnly = "v".equals(rcl.getAvsettings());
+                       if (Client.Type.sharing == rcl.getType()) {
+                               if (rcl.isSharingStarted() || 
rcl.isRecordingStarted()) {
+                                       String streamName = 
generateFileName(recordingId, broadcastId);
+
+                                       Long metaId = 
metaDataDao.add(recordingId, now, false, false, true, streamName, null);
+
+                                       // Start FLV Recording
+                                       addListener(conn, rcl.getBroadcastId(), 
streamName, metaId, true, isInterview);
+
+                                       // Add Meta Data
+                                       rcl.setMetaId(metaId);
+                                       sessionManager.update(rcl);
+                               }
+                       } else if ("av".equals(rcl.getAvsettings()) || 
audioOnly || videoOnly) {
+                               // if the user does publish av, a, v
+                               // But we only record av or a, video only is 
not interesting
+                               String streamName = 
generateFileName(recordingId, broadcastId);
+
+                               Long metaId = metaDataDao.add(recordingId, now, 
audioOnly, videoOnly, false, streamName,
+                                               rcl.getInterviewPodId());
+
+                               // Start FLV recording
+                               addListener(conn, broadcastId, streamName, 
metaId, !audioOnly, isInterview);
+
+                               // Add Meta Data
+                               rcl.setMetaId(metaId);
+                               sessionManager.update(rcl);
+                       }
+               }
+               log.debug("startStreamRecord[{}]:: resulting metaId: {}", 
broadcastId, rcl.getMetaId());
+       }
+}

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/92e2d79d/openmeetings-core/src/test/java/org/apache/openmeetings/rdc/KeyCodesTest.java
----------------------------------------------------------------------
diff --git 
a/openmeetings-core/src/test/java/org/apache/openmeetings/rdc/KeyCodesTest.java 
b/openmeetings-core/src/test/java/org/apache/openmeetings/rdc/KeyCodesTest.java
index 411067e..5fae12b 100644
--- 
a/openmeetings-core/src/test/java/org/apache/openmeetings/rdc/KeyCodesTest.java
+++ 
b/openmeetings-core/src/test/java/org/apache/openmeetings/rdc/KeyCodesTest.java
@@ -40,10 +40,6 @@ public class KeyCodesTest extends Frame implements 
KeyListener {
        String msg1 = "";
        String msg2 = "";
 
-       public static void main(String[] args) {
-               new KeyCodesTest();
-       }
-
        public KeyCodesTest() {
                super("TestKeyCodes");
                addKeyListener(this);

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/92e2d79d/openmeetings-core/src/test/java/org/apache/openmeetings/rdc/ReadKeyCodesTest.java
----------------------------------------------------------------------
diff --git 
a/openmeetings-core/src/test/java/org/apache/openmeetings/rdc/ReadKeyCodesTest.java
 
b/openmeetings-core/src/test/java/org/apache/openmeetings/rdc/ReadKeyCodesTest.java
index cd5968e..acf0780 100644
--- 
a/openmeetings-core/src/test/java/org/apache/openmeetings/rdc/ReadKeyCodesTest.java
+++ 
b/openmeetings-core/src/test/java/org/apache/openmeetings/rdc/ReadKeyCodesTest.java
@@ -29,10 +29,6 @@ public class ReadKeyCodesTest extends Frame implements 
KeyListener {
        String msg1 = "";
        String msg2 = "";
 
-       public static void main(String[] args) {
-               new ReadKeyCodesTest();
-       }
-
        public ReadKeyCodesTest() {
                super("TestKeyCodes");
                addKeyListener(this);

Reply via email to