You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openmeetings.apache.org by so...@apache.org on 2018/11/08 14:54:09 UTC
[openmeetings] branch master updated: [OPENMEETINGS-1955] initial
commit on recording for non-interview rooms
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 16d3604 [OPENMEETINGS-1955] initial commit on recording for non-interview rooms
16d3604 is described below
commit 16d3604b3fe20cb0a848b76630bef0d4afae038c
Author: Maxim Solodovnik <so...@gmail.com>
AuthorDate: Thu Nov 8 21:53:56 2018 +0700
[OPENMEETINGS-1955] initial commit on recording for non-interview rooms
---
.../org/apache/openmeetings/core/remote/KRoom.java | 9 +++-
.../openmeetings/core/remote/KurentoHandler.java | 37 ++++++++++++++--
.../openmeetings/db/entity/basic/Client.java | 25 +++++++++--
.../org/apache/openmeetings/web/room/raw-sharer.js | 49 +++++++++++++++++++---
.../openmeetings/web/room/raw-video-manager.js | 8 ++--
.../apache/openmeetings/web/room/raw-video-util.js | 8 +++-
.../org/apache/openmeetings/web/room/raw-video.js | 18 +++++---
.../openmeetings/web/room/wb/InterviewWbPanel.java | 2 +-
8 files changed, 130 insertions(+), 26 deletions(-)
diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KRoom.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KRoom.java
index 70c1da5..a9e215c 100644
--- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KRoom.java
+++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/KRoom.java
@@ -35,6 +35,7 @@ import org.apache.openmeetings.core.util.WebSocketHelper;
import org.apache.openmeetings.db.dao.record.RecordingChunkDao;
import org.apache.openmeetings.db.dao.record.RecordingDao;
import org.apache.openmeetings.db.entity.basic.Client;
+import org.apache.openmeetings.db.entity.basic.Client.Activity;
import org.apache.openmeetings.db.entity.basic.Client.StreamDesc;
import org.apache.openmeetings.db.entity.basic.Client.StreamType;
import org.apache.openmeetings.db.entity.file.BaseFileItem;
@@ -145,6 +146,10 @@ public class KRoom {
log.debug("##REC:: recording created by USER: {}", ownerId);
for (final KStream stream : streams.values()) {
+ StreamDesc sd = c.getStream(stream.getUid());
+ if (StreamType.SCREEN == sd.getType()) {
+ sd.addActivity(Activity.RECORD);
+ }
stream.startRecord();
}
@@ -178,9 +183,9 @@ public class KRoom {
return sharingStarted.get();
}
- public void startSharing(KurentoHandler h, IClientManager cm, Client c, JSONObject msg) {
+ public void startSharing(KurentoHandler h, IClientManager cm, Client c, JSONObject msg, Activity...activities) {
if (sharingStarted.compareAndSet(false, true)) {
- StreamDesc sd = c.addStream(StreamType.SCREEN);
+ StreamDesc sd = c.addStream(StreamType.SCREEN, activities);
sd.setWidth(msg.getInt("width")).setHeight(msg.getInt("height"));
cm.update(c);
log.debug("User {}: has started broadcast", sd.getUid());
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 1fd218f..6191a7f 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
@@ -241,6 +241,9 @@ public class KurentoHandler {
sender = room.join(sd);
}
sender.startBroadcast(this, sd, msg.getString("sdpOffer"));
+ if (StreamType.SCREEN == sd.getType() && sd.hasActivity(Activity.RECORD) && !isRecording(c.getRoomId())) {
+ startRecording(c);
+ }
break;
case "onIceCandidate":
sender = getByUid(uid);
@@ -264,6 +267,20 @@ public class KurentoHandler {
startSharing(c, msg);
}
break;
+ case "wannaRecord":
+ if (recordingAllowed(c)) {
+ Room r = c.getRoom();
+ if (Room.Type.interview == r.getType()) {
+ log.warn("This shouldn't be called for interview room");
+ break;
+ }
+ if (isSharing(r.getId())) {
+ startRecording(c);
+ } else {
+ startSharing(c, msg, Activity.RECORD);
+ }
+ }
+ break;
case "stopSharing":
sender = getByUid(uid);
sd = stopSharing(c.getSid(), uid);
@@ -286,8 +303,10 @@ public class KurentoHandler {
}
KRoom room = getRoom(roomId);
if (room.isRecording()) {
- List<Client> clients = cm.listByRoom(roomId).parallelStream().filter(c -> c.getStreams().isEmpty()).collect(Collectors.toList());
- if (clients.isEmpty()) {
+ List<StreamDesc> streams = cm.listByRoom(roomId).parallelStream()
+ .flatMap(c -> c.getStreams().stream())
+ .collect(Collectors.toList());
+ if (streams.isEmpty()) {
log.info("No more streams in the room, stopping recording");
room.stopRecording(this, null, recDao);
}
@@ -369,6 +388,16 @@ public class KurentoHandler {
}
}
+ public boolean recordingAllowed(Client c) {
+ if (client == null) {
+ log.warn(WARN_NO_KURENTO);
+ return false;
+ }
+ Room r = c.getRoom();
+ return r != null && r.isAllowRecording() && c.hasRight(Right.moderator)
+ && !isRecording(r.getId());
+ }
+
public void startRecording(Client c) {
if (client == null) {
log.warn(WARN_NO_KURENTO);
@@ -418,9 +447,9 @@ public class KurentoHandler {
&& !isSharing(r.getId());
}
- private void startSharing(Client c, JSONObject msg) {
+ private void startSharing(Client c, JSONObject msg, Activity...activities) {
if (client != null && c.getRoomId() != null) {
- getRoom(c.getRoomId()).startSharing(this, cm, c, msg);
+ getRoom(c.getRoomId()).startSharing(this, cm, c, msg, activities);
}
}
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 4c362b7..d4f5375 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
@@ -212,8 +212,8 @@ public class Client implements IDataProviderEntity, IWsClient {
return this;
}
- public StreamDesc addStream(StreamType stype) {
- StreamDesc sd = new StreamDesc(stype);
+ public StreamDesc addStream(StreamType stype, Activity...activities) {
+ StreamDesc sd = new StreamDesc(stype, activities);
streams.put(sd.getUid(), sd);
return sd;
}
@@ -431,10 +431,14 @@ public class Client implements IDataProviderEntity, IWsClient {
sactivities.addAll(sd.sactivities);
}
- public StreamDesc(StreamType type) {
+ public StreamDesc(StreamType type, Activity...activities) {
this.uuid = randomUUID().toString();
this.type = type;
- setActivities();
+ if (activities == null) {
+ setActivities();
+ } else {
+ sactivities.addAll(Arrays.asList(activities));
+ }
if (StreamType.WEBCAM == type) {
boolean interview = room != null && Room.Type.interview == room.getType();
this.swidth = interview ? 320 : width;
@@ -496,6 +500,14 @@ public class Client implements IDataProviderEntity, IWsClient {
return sactivities.contains(a);
}
+ public void addActivity(Activity a) {
+ sactivities.add(a);
+ }
+
+ public void removeActivity(Activity a) {
+ sactivities.remove(a);
+ }
+
public Client getClient() {
return Client.this;
}
@@ -518,5 +530,10 @@ public class Client implements IDataProviderEntity, IWsClient {
.put("lastName", user.getLastname())
);
}
+
+ @Override
+ public String toString() {
+ return String.format("Stream[uid=%s,type=%s,activities=%s]", uid, type, sactivities);
+ }
}
}
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-sharer.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-sharer.js
index b902e76..63160b8 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-sharer.js
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-sharer.js
@@ -4,7 +4,8 @@ var SHARE_STARTED = 'started';
var SHARE_STOPED = 'stoped';
var Sharer = (function() {
const self = {};
- let sharer, type, fps, sbtn, rbtn, width, height, shareState = SHARE_STOPED;
+ let sharer, type, fps, sbtn, rbtn, width, height
+ , shareState = SHARE_STOPED, recState = SHARE_STOPED;
function _init() {
sharer = $('#sharer').dialog({
@@ -21,10 +22,7 @@ var Sharer = (function() {
});
sbtn = sharer.find('.share-start-stop').button({
icon: 'ui-icon-image'
- });
- width = sharer.find('.width');
- height = sharer.find('.height');
- sbtn.click(function() {
+ }).off().click(function() {
if (shareState === SHARE_STOPED) {
_setShareState(SHARE_STARTING);
VideoManager.sendMessage({
@@ -46,8 +44,31 @@ var Sharer = (function() {
_setShareState(SHARE_STOPED);
}
});
+ width = sharer.find('.width');
+ height = sharer.find('.height');
rbtn = sharer.find('.record-start-stop').button({
icon: 'ui-icon-bullet'
+ }).off().click(function() {
+ if (recState === SHARE_STOPED) {
+ _setRecState(SHARE_STARTING);
+ VideoManager.sendMessage({
+ id: 'wannaRecord'
+ , shareType: type.val()
+ , fps: fps.val()
+ , width: width.val()
+ , height: height.val()
+ });
+ } else {
+ const cuid = Room.getOptions().uid
+ , v = $('div[data-client-uid="' + cuid + '"][data-client-type="SCREEN"]')
+ , uid = v.data().stream().uid;
+ VideoManager.sendMessage({
+ id: 'stopRecord'
+ , uid: uid
+ });
+ VideoManager.close(uid, false);
+ _setRecState(SHARE_STOPED);
+ }
});
}
function _setShareState(state) {
@@ -67,6 +88,23 @@ var Sharer = (function() {
rbtn.button('enable');
}
}
+ function _setRecState(state) {
+ recState = state;
+ const dis = SHARE_STOPED !== state;
+ type.selectmenu('option', 'disabled', dis || VideoUtil.isEdge());
+ fps.selectmenu('option', 'disabled', dis || VideoUtil.isEdge());
+ width.prop('disabled', dis);
+ height.prop('disabled', dis);
+ rbtn.text(rbtn.data(dis ? 'stop' : 'start'));
+ rbtn.button('option', 'icon', dis ? 'ui-icon-stop' : 'ui-icon-image');
+ if (state === SHARE_STARTING) {
+ sbtn.button('disable');
+ rbtn.button('disable');
+ } else {
+ sbtn.button('enable');
+ rbtn.button('enable');
+ }
+ }
self.init = _init;
self.open = function() {
@@ -80,5 +118,6 @@ var Sharer = (function() {
}
};
self.setShareState = _setShareState;
+ self.setRecState = _setRecState;
return self;
})();
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video-manager.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video-manager.js
index 89036c4..6e8a872 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video-manager.js
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video-manager.js
@@ -17,9 +17,6 @@ var VideoManager = (function() {
const sd = msg.stream
, uid = sd.uid;
$('#' + VideoUtil.getVid(uid)).remove();
- if (sd.self && VideoUtil.isSharing(sd)) {
- return;
- }
Video().init(msg);
OmUtil.log(uid + ' registered in room');
}
@@ -105,7 +102,7 @@ var VideoManager = (function() {
}
c.streams.forEach(function(sd) {
sd.self = c.self;
- if (VideoUtil.isSharing(sd)) {
+ if (VideoUtil.isSharing(sd) || VideoUtil.isRecording(sd)) {
return;
}
const _id = VideoUtil.getVid(sd.uid)
@@ -147,6 +144,9 @@ var VideoManager = (function() {
return;
}
streams.forEach(function(sd) {
+ if (VideoUtil.isRecording(sd)) {
+ return;
+ }
const m = {stream: sd, iceServers: iceServers};
if (VideoUtil.isSharing(sd)) {
_highlight(share
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video-util.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video-util.js
index 7b21a2e..dcf7304 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video-util.js
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video-util.js
@@ -4,13 +4,18 @@ const WBA_WB_SEL = '.room.wb.area .ui-tabs-panel.ui-corner-bottom.ui-widget-cont
const VID_SEL = '.video.user-video';
const CAM_ACTIVITY = 'VIDEO';
const MIC_ACTIVITY = 'AUDIO';
+const SCREEN_ACTIVITY = 'SCREEN';
+const REC_ACTIVITY = 'RECORD';
var VideoUtil = (function() {
const self = {};
function _getVid(uid) {
return 'video' + uid;
}
function _isSharing(sd) {
- return 'SCREEN' === sd.type;
+ return !!sd && 'SCREEN' === sd.type && sd.activities.includes(SCREEN_ACTIVITY);
+ }
+ function _isRecording(sd) {
+ return !!sd && 'SCREEN' === sd.type && sd.activities.includes(REC_ACTIVITY);
}
function _hasAudio(sd) {
return !sd || sd.activities.includes(MIC_ACTIVITY);
@@ -133,6 +138,7 @@ var VideoUtil = (function() {
self.getVid = _getVid;
self.isSharing = _isSharing;
+ self.isRecording = _isRecording;
self.hasAudio = _hasAudio;
self.hasVideo = _hasVideo;
self.getRects = _getRects;
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video.js
index 218156f..8b41b3f 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video.js
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video.js
@@ -54,6 +54,7 @@ var Video = (function() {
callback(msg, cnts, stream);
}).catch(function(err) {
Sharer.setShareState(SHARE_STOPED);
+ Sharer.setRecState(SHARE_STOPED);
OmUtil.error(err);
});
} else if (b.name === 'Firefox') {
@@ -69,9 +70,12 @@ var Video = (function() {
callback(msg, cnts, stream);
}).catch(function(err) {
Sharer.setShareState(SHARE_STOPED);
+ Sharer.setRecState(SHARE_STOPED);
OmUtil.error(err);
});
} else {
+ Sharer.setShareState(SHARE_STOPED);
+ Sharer.setRecState(SHARE_STOPED);
Sharer.close();
OmUtil.error('Screen-sharing is not supported in ' + b.name + '[' + b.major + ']');
}
@@ -153,11 +157,14 @@ var Video = (function() {
if (VideoUtil.isSharing(sd)) {
Sharer.setShareState(SHARE_STARTED);
}
+ if (VideoUtil.isRecording(sd)) {
+ Sharer.setRecState(SHARE_STARTED);
+ }
});
});
}
function _createSendPeer(msg) {
- if (VideoUtil.isSharing(sd)) {
+ if (VideoUtil.isSharing(sd) || VideoUtil.isRecording(sd)) {
_getScreenStream(msg, __createSendPeer);
} else {
_getVideoStream(msg, __createSendPeer);
@@ -300,6 +307,7 @@ var Video = (function() {
, _w = sd.width
, _h = sd.height
, isSharing = VideoUtil.isSharing(sd)
+ , isRecording = VideoUtil.isRecording(sd)
, opts = Room.getOptions();
sd.self = sd.cuid === opts.uid;
const contSel = _initContainer(_id, name, opts);
@@ -309,7 +317,7 @@ var Video = (function() {
if (!sd.self && isSharing) {
Sharer.close();
}
- if (sd.self && isSharing) {
+ if (sd.self && (isSharing || isRecording)) {
v.hide();
} else {
v.dialog({
@@ -326,7 +334,7 @@ var Video = (function() {
});
_initDialog(v, opts);
}
- if (!isSharing) {
+ if (!isSharing && !isRecording) {
v.parent().find('.ui-dialog-titlebar-buttonpane')
.append($('#video-volume-btn').children().clone())
.append($('#video-refresh-btn').children().clone());
@@ -381,7 +389,7 @@ var Video = (function() {
_refresh(msg);
- if (!isSharing) {
+ if (!isSharing && !isRecording) {
VideoUtil.setPos(v, VideoUtil.getPos(VideoUtil.getRects(VID_SEL), sd.width, sd.height + 25));
}
return v;
@@ -401,7 +409,7 @@ var Video = (function() {
function _refresh(msg) {
_cleanup();
const _id = VideoUtil.getVid(sd.uid);
- const hasVideo = VideoUtil.hasVideo(sd) || VideoUtil.isSharing(sd)
+ const hasVideo = VideoUtil.hasVideo(sd) || VideoUtil.isSharing(sd) || VideoUtil.isRecording(sd)
, imgUrl = 'profile/' + sd.user.id + '?anti=' + new Date().getTime(); //TODO add normal URL ????
video = $(hasVideo ? '<video>' : '<audio>').attr('id', 'vid' + _id)
.width(vc.width()).height(vc.height())
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/InterviewWbPanel.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/InterviewWbPanel.java
index 93461e3..63c77f6 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/InterviewWbPanel.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/wb/InterviewWbPanel.java
@@ -55,7 +55,7 @@ public class InterviewWbPanel extends AbstractWbPanel {
@Override
protected void processWbAction(WbAction a, JSONObject obj, AjaxRequestTarget target) throws IOException {
Client c = rp.getClient();
- if (rp.getRoom().isAllowRecording() && c.hasRight(Right.moderator)) {
+ if (kurento.recordingAllowed(c)) {
switch (a) {
case startRecording:
kurento.startRecording(c);