diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/externalvideo/ExternalVideoApp2x.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/externalvideo/ExternalVideoApp2x.scala new file mode 100644 index 0000000000000000000000000000000000000000..0630711d6408f2a45fe3ec0c446c82978ca08142 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/externalvideo/ExternalVideoApp2x.scala @@ -0,0 +1,13 @@ +package org.bigbluebutton.core.apps.externalvideo + +import akka.actor.ActorContext +import akka.event.Logging + +class ExternalVideoApp2x(implicit val context: ActorContext) + extends StartExternalVideoPubMsgHdlr + with UpdateExternalVideoPubMsgHdlr + with StopExternalVideoPubMsgHdlr { + + val log = Logging(context.system, getClass) + +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/externalvideo/StartExternalVideoPubMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/externalvideo/StartExternalVideoPubMsgHdlr.scala new file mode 100644 index 0000000000000000000000000000000000000000..39a81d9aab31dd6bac923e3dfeaafe53659b66cc --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/externalvideo/StartExternalVideoPubMsgHdlr.scala @@ -0,0 +1,27 @@ +package org.bigbluebutton.core.apps.externalvideo + +import org.bigbluebutton.common2.msgs._ +import org.bigbluebutton.core.bus.MessageBus +import org.bigbluebutton.core.running.{ LiveMeeting } + +trait StartExternalVideoPubMsgHdlr { + this: ExternalVideoApp2x => + + def handle(msg: StartExternalVideoPubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = { + log.info("Received StartExternalVideoPubMsgr meetingId={} url={}", liveMeeting.props.meetingProp.intId, msg.body.externalVideoUrl) + + def broadcastEvent(msg: StartExternalVideoPubMsg) { + + val routing = Routing.addMsgToClientRouting(MessageTypes.DIRECT, liveMeeting.props.meetingProp.intId, "nodeJSapp") + val envelope = BbbCoreEnvelope(StartExternalVideoEvtMsg.NAME, routing) + val header = BbbClientMsgHeader(StartExternalVideoEvtMsg.NAME, liveMeeting.props.meetingProp.intId, msg.header.userId) + + val body = StartExternalVideoEvtMsgBody(msg.body.externalVideoUrl) + val event = StartExternalVideoEvtMsg(header, body) + val msgEvent = BbbCommonEnvCoreMsg(envelope, event) + bus.outGW.send(msgEvent) + } + + broadcastEvent(msg) + } +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/externalvideo/StopExternalVideoPubMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/externalvideo/StopExternalVideoPubMsgHdlr.scala new file mode 100644 index 0000000000000000000000000000000000000000..fb8ef02953d5936fea88f483f7eaead8f2510e9e --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/externalvideo/StopExternalVideoPubMsgHdlr.scala @@ -0,0 +1,27 @@ +package org.bigbluebutton.core.apps.externalvideo + +import org.bigbluebutton.common2.msgs._ +import org.bigbluebutton.core.bus.MessageBus +import org.bigbluebutton.core.running.{ LiveMeeting } + +trait StopExternalVideoPubMsgHdlr { + this: ExternalVideoApp2x => + + def handle(msg: StopExternalVideoPubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = { + log.info("Received StopExternalVideoPubMsgr meetingId={}", liveMeeting.props.meetingProp.intId) + + def broadcastEvent() { + + val routing = Routing.addMsgToClientRouting(MessageTypes.DIRECT, liveMeeting.props.meetingProp.intId, "nodeJSapp") + val envelope = BbbCoreEnvelope(StopExternalVideoEvtMsg.NAME, routing) + val header = BbbClientMsgHeader(StopExternalVideoEvtMsg.NAME, liveMeeting.props.meetingProp.intId, msg.header.userId) + + val body = StopExternalVideoEvtMsgBody() + val event = StopExternalVideoEvtMsg(header, body) + val msgEvent = BbbCommonEnvCoreMsg(envelope, event) + bus.outGW.send(msgEvent) + } + + broadcastEvent() + } +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/externalvideo/UpdateExternalVideoPubMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/externalvideo/UpdateExternalVideoPubMsgHdlr.scala new file mode 100644 index 0000000000000000000000000000000000000000..e343f5fa3a26e2ac8c99e91e45de82f8487ab68d --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/externalvideo/UpdateExternalVideoPubMsgHdlr.scala @@ -0,0 +1,23 @@ +package org.bigbluebutton.core.apps.externalvideo + +import org.bigbluebutton.common2.msgs._ +import org.bigbluebutton.core.bus.MessageBus +import org.bigbluebutton.core.running.{ LiveMeeting } + +trait UpdateExternalVideoPubMsgHdlr { + + def handle(msg: UpdateExternalVideoPubMsg, liveMeeting: LiveMeeting, bus: MessageBus): Unit = { + def broadcastEvent(msg: UpdateExternalVideoPubMsg) { + val routing = Routing.addMsgToClientRouting(MessageTypes.DIRECT, liveMeeting.props.meetingProp.intId, "nodeJSapp") + val envelope = BbbCoreEnvelope(UpdateExternalVideoEvtMsg.NAME, routing) + val header = BbbClientMsgHeader(UpdateExternalVideoEvtMsg.NAME, liveMeeting.props.meetingProp.intId, msg.header.userId) + + val body = UpdateExternalVideoEvtMsgBody(msg.body.status, msg.body.rate, msg.body.time, msg.body.state) + val event = UpdateExternalVideoEvtMsg(header, body) + val msgEvent = BbbCommonEnvCoreMsg(envelope, event) + bus.outGW.send(msgEvent) + } + + broadcastEvent(msg) + } +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala index f39fcea50fb454d87e16dbc651a7536ad66458f1..4313ed5242a60b9bf908c21baa26113506044d1a 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala @@ -319,6 +319,14 @@ class ReceivedJsonMsgHandlerActor( case CreateGroupChatReqMsg.NAME => routeGenericMsg[CreateGroupChatReqMsg](envelope, jsonNode) + // ExternalVideo + case StartExternalVideoPubMsg.NAME => + routeGenericMsg[StartExternalVideoPubMsg](envelope, jsonNode) + case UpdateExternalVideoPubMsg.NAME => + routeGenericMsg[UpdateExternalVideoPubMsg](envelope, jsonNode) + case StopExternalVideoPubMsg.NAME => + routeGenericMsg[StopExternalVideoPubMsg](envelope, jsonNode) + case _ => log.error("Cannot route envelope name " + envelope.name) // do nothing diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/AbsractExternalVideoRecordEvent.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/AbsractExternalVideoRecordEvent.scala new file mode 100644 index 0000000000000000000000000000000000000000..66aefb0cf6e47f3deff4ecab774710930bd5ce92 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/AbsractExternalVideoRecordEvent.scala @@ -0,0 +1,24 @@ +/** + * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ + * + * Copyright (c) 2019 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. + * + */ + +package org.bigbluebutton.core.record.events + +trait AbstractExternalVideoRecordEvent extends RecordEvent { + setModule("EXTERNAL-VIDEO") +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/StartExternalVideoRecordEvent.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/StartExternalVideoRecordEvent.scala new file mode 100644 index 0000000000000000000000000000000000000000..1c1e33992980e6a99ceb1d306bd805358b6f0e83 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/StartExternalVideoRecordEvent.scala @@ -0,0 +1,34 @@ +/** + * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ + * + * Copyright (c) 2019 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. + * + */ + +package org.bigbluebutton.core.record.events + +class StartExternalVideoRecordEvent extends AbstractExternalVideoRecordEvent { + import StartExternalVideoRecordEvent._ + + setEvent("StartExternalVideoRecordEvent") + + def setExternalVideoUrl(externalVideoUrl: String) { + eventMap.put(EXTERNAL_VIDEO_URL, externalVideoUrl) + } +} + +object StartExternalVideoRecordEvent { + protected final val EXTERNAL_VIDEO_URL = "externalVideoUrl" +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/StopExternalVideoRecordEvent.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/StopExternalVideoRecordEvent.scala new file mode 100644 index 0000000000000000000000000000000000000000..789251bb99203e003225c687dfe1c2233ccd7e02 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/StopExternalVideoRecordEvent.scala @@ -0,0 +1,24 @@ +/** + * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ + * + * Copyright (c) 2019 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. + * + */ + +package org.bigbluebutton.core.record.events + +class StopExternalVideoRecordEvent extends AbstractExternalVideoRecordEvent { + setEvent("StopExternalVideoRecordEvent") +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/UpdateExternalVideoRecordEvent.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/UpdateExternalVideoRecordEvent.scala new file mode 100644 index 0000000000000000000000000000000000000000..983ab26be60b22ad3f6623b356baadba38e8f518 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/UpdateExternalVideoRecordEvent.scala @@ -0,0 +1,49 @@ +/** + * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ + * + * Copyright (c) 2019 BigBlueButton Inc. and by respective authors (see below). + * + * This program is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation; either version 3.0 of the License, or (at your option) any later + * version. + * + * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. + * + */ + +package org.bigbluebutton.core.record.events + +class UpdateExternalVideoRecordEvent extends AbstractExternalVideoRecordEvent { + import UpdateExternalVideoRecordEvent._ + + setEvent("UpdateExternalVideoRecordEvent") + + def setStatus(status: String) { + eventMap.put(STATUS, status) + } + + def setRate(rate: Double) { + eventMap.put(RATE, rate.toString) + } + + def setTime(time: Double) { + eventMap.put(TIME, time.toString) + } + + def setState(state: Boolean) { + eventMap.put(STATE, state.toString) + } +} + +object UpdateExternalVideoRecordEvent { + protected final val STATUS = "status" + protected final val RATE = "rate" + protected final val TIME = "time" + protected final val STATE = "state" +} diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala index 4a37e15d130c5aee82b1c4486b2e5a2a0480ee0b..cb01e1dbb437e06461245297e5d168bacc16ff41 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala @@ -16,6 +16,7 @@ import org.bigbluebutton.core.api._ import org.bigbluebutton.core.apps._ import org.bigbluebutton.core.apps.caption.CaptionApp2x import org.bigbluebutton.core.apps.chat.ChatApp2x +import org.bigbluebutton.core.apps.externalvideo.ExternalVideoApp2x import org.bigbluebutton.core.apps.screenshare.ScreenshareApp2x import org.bigbluebutton.core.apps.presentation.PresentationApp2x import org.bigbluebutton.core.apps.users.UsersApp2x @@ -113,6 +114,7 @@ class MeetingActor( val screenshareApp2x = new ScreenshareApp2x val captionApp2x = new CaptionApp2x val chatApp2x = new ChatApp2x + val externalVideoApp2x = new ExternalVideoApp2x val usersApp = new UsersApp(liveMeeting, outGW, eventBus) val groupChatApp = new GroupChatHdlrs val presentationPodsApp = new PresentationPodHdlrs @@ -460,6 +462,11 @@ class MeetingActor( state = groupChatApp.handle(m, state, liveMeeting, msgBus) updateUserLastActivity(m.body.msg.sender.id) + // ExternalVideo + case m: StartExternalVideoPubMsg => externalVideoApp2x.handle(m, liveMeeting, msgBus) + case m: UpdateExternalVideoPubMsg => externalVideoApp2x.handle(m, liveMeeting, msgBus) + case m: StopExternalVideoPubMsg => externalVideoApp2x.handle(m, liveMeeting, msgBus) + case m: ValidateConnAuthTokenSysMsg => handleValidateConnAuthTokenSysMsg(m) case m: UserActivitySignCmdMsg => handleUserActivitySignCmdMsg(m) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/FromAkkaAppsMsgSenderActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/FromAkkaAppsMsgSenderActor.scala index 37062c3978dd7b566b112f04d0023b466fc91fb2..165d9262fbaa9df54e8e0b80d33a24b3fef12ca0 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/FromAkkaAppsMsgSenderActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/FromAkkaAppsMsgSenderActor.scala @@ -119,7 +119,7 @@ class FromAkkaAppsMsgSenderActor(msgSender: MessageSender) //================================================================== case ValidateAuthTokenRespMsg.NAME => - msgSender.send(fromAkkaAppsRedisChannel, json) // needed for cases when single nodejs process is running (like in development) + msgSender.send(fromAkkaAppsRedisChannel, json) // needed for cases when single nodejs process is running (like in development) msgSender.send("from-akka-apps-frontend-redis-channel", json) // Message duplicated for frontend and backend processes @@ -143,6 +143,9 @@ class FromAkkaAppsMsgSenderActor(msgSender: MessageSender) msgSender.send(fromAkkaAppsRedisChannel, json) msgSender.send("from-akka-apps-frontend-redis-channel", json) + case UpdateExternalVideoEvtMsg.NAME => + msgSender.send("from-akka-apps-frontend-redis-channel", json) + case _ => msgSender.send(fromAkkaAppsRedisChannel, json) } diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisRecorderActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisRecorderActor.scala index 3aee1d95028a9d06a5b26b1a70d17fa0da6a3e8d..3469157c086c2e12684888bddc240d942b287d49 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisRecorderActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/endpoint/redis/RedisRecorderActor.scala @@ -108,6 +108,11 @@ class RedisRecorderActor( case m: PollStoppedEvtMsg => handlePollStoppedEvtMsg(m) case m: PollShowResultEvtMsg => handlePollShowResultEvtMsg(m) + // ExternalVideo + case m: StartExternalVideoEvtMsg => handleStartExternalVideoEvtMsg(m) + case m: UpdateExternalVideoEvtMsg => handleUpdateExternalVideoEvtMsg(m) + case m: StopExternalVideoEvtMsg => handleStopExternalVideoEvtMsg(m) + case _ => // message not to be recorded. } } @@ -456,6 +461,32 @@ class RedisRecorderActor( } */ + private def handleStartExternalVideoEvtMsg(msg: StartExternalVideoEvtMsg) { + val ev = new StartExternalVideoRecordEvent() + ev.setMeetingId(msg.header.meetingId) + ev.setExternalVideoUrl(msg.body.externalVideoUrl) + + record(msg.header.meetingId, ev.toMap.asJava) + } + + private def handleUpdateExternalVideoEvtMsg(msg: UpdateExternalVideoEvtMsg) { + val ev = new UpdateExternalVideoRecordEvent() + ev.setMeetingId(msg.header.meetingId) + ev.setStatus(msg.body.status) + ev.setRate(msg.body.rate) + ev.setTime(msg.body.time) + ev.setState(msg.body.state) + + record(msg.header.meetingId, ev.toMap.asJava) + } + + private def handleStopExternalVideoEvtMsg(msg: StopExternalVideoEvtMsg) { + val ev = new StopExternalVideoRecordEvent() + ev.setMeetingId(msg.header.meetingId) + + record(msg.header.meetingId, ev.toMap.asJava) + } + private def handleRecordingStatusChangedEvtMsg(msg: RecordingStatusChangedEvtMsg) { val ev = new RecordStatusRecordEvent() ev.setMeetingId(msg.header.meetingId) diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/ExternalVideoMsgs.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/ExternalVideoMsgs.scala new file mode 100644 index 0000000000000000000000000000000000000000..7a66abd7e74828afd2e11092893e7c11129630d0 --- /dev/null +++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/ExternalVideoMsgs.scala @@ -0,0 +1,27 @@ +package org.bigbluebutton.common2.msgs + +// In messages +object StartExternalVideoPubMsg { val NAME = "StartExternalVideoPubMsg" } +case class StartExternalVideoPubMsg(header: BbbClientMsgHeader, body: StartExternalVideoPubMsgBody) extends StandardMsg +case class StartExternalVideoPubMsgBody(externalVideoUrl: String) + +object UpdateExternalVideoPubMsg { val NAME = "UpdateExternalVideoPubMsg" } +case class UpdateExternalVideoPubMsg(header: BbbClientMsgHeader, body: UpdateExternalVideoPubMsgBody) extends StandardMsg +case class UpdateExternalVideoPubMsgBody(status: String, rate: Double, time: Double, state: Boolean) + +object StopExternalVideoPubMsg { val NAME = "StopExternalVideoPubMsg" } +case class StopExternalVideoPubMsg(header: BbbClientMsgHeader, body: StopExternalVideoPubMsgBody) extends StandardMsg +case class StopExternalVideoPubMsgBody() + +// Out messages +object StartExternalVideoEvtMsg { val NAME = "StartExternalVideoEvtMsg" } +case class StartExternalVideoEvtMsg(header: BbbClientMsgHeader, body: StartExternalVideoEvtMsgBody) extends BbbCoreMsg +case class StartExternalVideoEvtMsgBody(externalVideoUrl: String) + +object UpdateExternalVideoEvtMsg { val NAME = "UpdateExternalVideoEvtMsg" } +case class UpdateExternalVideoEvtMsg(header: BbbClientMsgHeader, body: UpdateExternalVideoEvtMsgBody) extends BbbCoreMsg +case class UpdateExternalVideoEvtMsgBody(status: String, rate: Double, time: Double, state: Boolean) + +object StopExternalVideoEvtMsg { val NAME = "StopExternalVideoEvtMsg" } +case class StopExternalVideoEvtMsg(header: BbbClientMsgHeader, body: StopExternalVideoEvtMsgBody) extends BbbCoreMsg +case class StopExternalVideoEvtMsgBody() diff --git a/bigbluebutton-html5/imports/api/external-videos/index.js b/bigbluebutton-html5/imports/api/external-videos/index.js index d4ef796968d67e052deb80e275a7b72b577359c0..64ffab0d0f715cd5c4573b598bcba266ff79e5e1 100644 --- a/bigbluebutton-html5/imports/api/external-videos/index.js +++ b/bigbluebutton-html5/imports/api/external-videos/index.js @@ -1,11 +1,9 @@ import { Meteor } from 'meteor/meteor'; -import { makeCall } from '/imports/ui/services/api'; let streamer = null; const getStreamer = (meetingID) => { if (!streamer) { streamer = new Meteor.Streamer(`external-videos-${meetingID}`); - makeCall('initializeExternalVideo'); } return streamer; }; diff --git a/bigbluebutton-html5/imports/api/external-videos/server/eventHandlers.js b/bigbluebutton-html5/imports/api/external-videos/server/eventHandlers.js new file mode 100644 index 0000000000000000000000000000000000000000..2cd4077869200dfe86e8ce0edcc9986aa76b7418 --- /dev/null +++ b/bigbluebutton-html5/imports/api/external-videos/server/eventHandlers.js @@ -0,0 +1,8 @@ +import RedisPubSub from '/imports/startup/server/redis'; +import handleStartExternalVideo from './handlers/startExternalVideo'; +import handleStopExternalVideo from './handlers/stopExternalVideo'; +import handleUpdateExternalVideo from './handlers/updateExternalVideo'; + +RedisPubSub.on('StartExternalVideoEvtMsg', handleStartExternalVideo); +RedisPubSub.on('StopExternalVideoEvtMsg', handleStopExternalVideo); +RedisPubSub.on('UpdateExternalVideoEvtMsg', handleUpdateExternalVideo); diff --git a/bigbluebutton-html5/imports/api/external-videos/server/handlers/startExternalVideo.js b/bigbluebutton-html5/imports/api/external-videos/server/handlers/startExternalVideo.js new file mode 100644 index 0000000000000000000000000000000000000000..1e84b493c7fc66db50a2b1495bf934e8f79161ea --- /dev/null +++ b/bigbluebutton-html5/imports/api/external-videos/server/handlers/startExternalVideo.js @@ -0,0 +1,23 @@ +import { check } from 'meteor/check'; +import Logger from '/imports/startup/server/logger'; +import Users from '/imports/api/users'; +import Meetings from '/imports/api/meetings'; + +export default function handleStartExternalVideo({ header, body }, meetingId) { + const { userId } = header; + check(body, Object); + check(meetingId, String); + check(userId, String); + + const externalVideoUrl = body.externalVideoUrl; + const user = Users.findOne({ meetingId: meetingId, userId: userId }) + + if (user && user.presenter) { + try { + Meetings.update({ meetingId }, { $set: { externalVideoUrl } }); + Logger.info(`User id=${userId} sharing an external video: ${externalVideoUrl} for meeting ${meetingId}`); + } catch (err) { + Logger.error(`Error on setting shared external video start in Meetings collection: ${err}`); + } + } +} diff --git a/bigbluebutton-html5/imports/api/external-videos/server/handlers/stopExternalVideo.js b/bigbluebutton-html5/imports/api/external-videos/server/handlers/stopExternalVideo.js new file mode 100644 index 0000000000000000000000000000000000000000..06e22da1f417f2354b7a801279cfdc1496d905c3 --- /dev/null +++ b/bigbluebutton-html5/imports/api/external-videos/server/handlers/stopExternalVideo.js @@ -0,0 +1,18 @@ +import { check } from 'meteor/check'; +import Logger from '/imports/startup/server/logger'; +import Meetings from '/imports/api/meetings'; + +export default function handleStopExternalVideo({ header, body }, meetingId) { + const { userId } = header; + check(body, Object); + check(meetingId, String); + check(userId, String); + + try { + Logger.info(`External video stop sharing was initiated by:[${userId}] for meeting ${meetingId}`); + Meetings.update({ meetingId }, { $set: { externalVideoUrl: null } }); + } catch (err) { + Logger.error(`Error on setting shared external video stop in Meetings collection: ${err}`); + } + +} diff --git a/bigbluebutton-html5/imports/api/external-videos/server/handlers/updateExternalVideo.js b/bigbluebutton-html5/imports/api/external-videos/server/handlers/updateExternalVideo.js new file mode 100644 index 0000000000000000000000000000000000000000..295171def7cf4574a32adb960c067b7c86cf3e11 --- /dev/null +++ b/bigbluebutton-html5/imports/api/external-videos/server/handlers/updateExternalVideo.js @@ -0,0 +1,24 @@ +import { check } from 'meteor/check'; +import Logger from '/imports/startup/server/logger'; +import Users from '/imports/api/users'; +import ExternalVideoStreamer from '/imports/api/external-videos/server/streamer'; + +export default function handleUpdateExternalVideo({ header, body }, meetingId) { + const { userId } = header; + check(body, Object); + check(meetingId, String); + check(userId, String); + + const user = Users.findOne({ meetingId: meetingId, userId: userId }) + + if (user && user.presenter) { + try { + Logger.info(`UpdateExternalVideoEvtMsg received for user ${userId} and meeting ${meetingId} event:${body.status}`); + ExternalVideoStreamer(meetingId).emit(body.status, { ...body, meetingId: meetingId, userId: userId }); + } catch (err) { + Logger.error(`Error on setting shared external video update in Meetings collection: ${err}`); + } + + } + +} diff --git a/bigbluebutton-html5/imports/api/external-videos/server/index.js b/bigbluebutton-html5/imports/api/external-videos/server/index.js index 2e0f48d559b9bc87827266a1d1225cc2af4c156f..b0d5d3295b0d8f62cda43093cb867e79f59ca357 100644 --- a/bigbluebutton-html5/imports/api/external-videos/server/index.js +++ b/bigbluebutton-html5/imports/api/external-videos/server/index.js @@ -1,2 +1,2 @@ import './methods'; - +import './eventHandlers'; diff --git a/bigbluebutton-html5/imports/api/external-videos/server/methods.js b/bigbluebutton-html5/imports/api/external-videos/server/methods.js index 7df620cb7a18089285bfccefa51d2aaffbde4e50..10c056a2a9fe61561eb1cf896afcfacaf6ee6b71 100644 --- a/bigbluebutton-html5/imports/api/external-videos/server/methods.js +++ b/bigbluebutton-html5/imports/api/external-videos/server/methods.js @@ -1,11 +1,9 @@ import { Meteor } from 'meteor/meteor'; import startWatchingExternalVideo from './methods/startWatchingExternalVideo'; import stopWatchingExternalVideo from './methods/stopWatchingExternalVideo'; -import initializeExternalVideo from './methods/initializeExternalVideo'; import emitExternalVideoEvent from './methods/emitExternalVideoEvent'; Meteor.methods({ - initializeExternalVideo, startWatchingExternalVideo, stopWatchingExternalVideo, emitExternalVideoEvent, diff --git a/bigbluebutton-html5/imports/api/external-videos/server/methods/destroyExternalVideo.js b/bigbluebutton-html5/imports/api/external-videos/server/methods/destroyExternalVideo.js deleted file mode 100644 index 0be97c31985c1188cec4c5a9c228ed4eaf9a0352..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/imports/api/external-videos/server/methods/destroyExternalVideo.js +++ /dev/null @@ -1,11 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import Logger from '/imports/startup/server/logger'; - -export default function destroyExternalVideo(meetingId) { - const streamName = `external-videos-${meetingId}`; - - if (Meteor.StreamerCentral.instances[streamName]) { - Logger.info(`Destroying External Video streamer object for ${streamName}`); - delete Meteor.StreamerCentral.instances[streamName]; - } -} diff --git a/bigbluebutton-html5/imports/api/external-videos/server/methods/emitExternalVideoEvent.js b/bigbluebutton-html5/imports/api/external-videos/server/methods/emitExternalVideoEvent.js index 8c5d1535b8a926cf274e8d783769e4d069df5a58..29123dbd8628a0d914f54dd9290e8c5a1b055c3e 100644 --- a/bigbluebutton-html5/imports/api/external-videos/server/methods/emitExternalVideoEvent.js +++ b/bigbluebutton-html5/imports/api/external-videos/server/methods/emitExternalVideoEvent.js @@ -1,20 +1,36 @@ -import Users from '/imports/api/users'; +import { check } from 'meteor/check'; import Logger from '/imports/startup/server/logger'; +import Users from '/imports/api/users'; +import RedisPubSub from '/imports/startup/server/redis'; import { extractCredentials } from '/imports/api/common/server/helpers'; -export default function emitExternalVideoEvent(messageName, ...rest) { - const { meetingId, requesterUserId: userId } = extractCredentials(this.userId); +export default function emitExternalVideoEvent(options) { + const REDIS_CONFIG = Meteor.settings.private.redis; + const CHANNEL = REDIS_CONFIG.channels.toAkkaApps; + const EVENT_NAME = 'UpdateExternalVideoPubMsg'; + + const { meetingId, requesterUserId } = extractCredentials(this.userId); + + const { status, playerStatus } = options; - const user = Users.findOne({ userId, meetingId }); + const user = Users.findOne({ meetingId, userId: requesterUserId }) if (user && user.presenter) { - const streamerName = `external-videos-${meetingId}`; - const streamer = Meteor.StreamerCentral.instances[streamerName]; - - if (streamer) { - streamer.emit(messageName, ...rest); - } else { - Logger.error(`External Video Streamer not found for meetingId: ${meetingId} userId: ${userId}`); - } + + check(status, String); + check(playerStatus, { + rate: Match.Maybe(Number), + time: Match.Maybe(Number), + state: Match.Maybe(Boolean), + }); + + let rate = playerStatus.rate || 0; + let time = playerStatus.time || 0; + let state = playerStatus.state || 0; + const payload = { status, rate, time, state }; + + Logger.debug(`User id=${requesterUserId} sending ${EVENT_NAME} event:${state} for meeting ${meetingId}`); + return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload); + } } diff --git a/bigbluebutton-html5/imports/api/external-videos/server/methods/initializeExternalVideo.js b/bigbluebutton-html5/imports/api/external-videos/server/methods/initializeExternalVideo.js deleted file mode 100644 index 2106862339e5af945a28132c02ce05fb56c4d4e2..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/imports/api/external-videos/server/methods/initializeExternalVideo.js +++ /dev/null @@ -1,32 +0,0 @@ -import { extractCredentials } from '/imports/api/common/server/helpers'; -import Logger from '/imports/startup/server/logger'; - -const allowRecentMessages = (eventName, message) => { - const { - userId, - meetingId, - time, - rate, - state, - } = message; - - Logger.debug('ExternalVideo Streamer auth allowed', { - userId, meetingId, eventName, time, rate, state, - }); - return true; -}; - -export default function initializeExternalVideo() { - const { meetingId } = extractCredentials(this.userId); - - const streamName = `external-videos-${meetingId}`; - if (!Meteor.StreamerCentral.instances[streamName]) { - const streamer = new Meteor.Streamer(streamName); - streamer.allowRead('all'); - streamer.allowWrite('none'); - streamer.allowEmit(allowRecentMessages); - Logger.info(`Created External Video streamer for ${streamName}`); - } else { - Logger.debug('External Video streamer is already created', { streamName }); - } -} diff --git a/bigbluebutton-html5/imports/api/external-videos/server/methods/startWatchingExternalVideo.js b/bigbluebutton-html5/imports/api/external-videos/server/methods/startWatchingExternalVideo.js index df2b88abe3fc2d0ee78002adc9cc560aa6d15388..c33a42fd955b4e23f18b97e40521eb3ea13baa67 100644 --- a/bigbluebutton-html5/imports/api/external-videos/server/methods/startWatchingExternalVideo.js +++ b/bigbluebutton-html5/imports/api/external-videos/server/methods/startWatchingExternalVideo.js @@ -1,7 +1,5 @@ -import { Meteor } from 'meteor/meteor'; import { check } from 'meteor/check'; import Logger from '/imports/startup/server/logger'; -import Meetings from '/imports/api/meetings'; import Users from '/imports/api/users'; import RedisPubSub from '/imports/startup/server/redis'; import { extractCredentials } from '/imports/api/common/server/helpers'; @@ -9,7 +7,7 @@ import { extractCredentials } from '/imports/api/common/server/helpers'; export default function startWatchingExternalVideo(options) { const REDIS_CONFIG = Meteor.settings.private.redis; const CHANNEL = REDIS_CONFIG.channels.toAkkaApps; - const EVENT_NAME = 'StartExternalVideoMsg'; + const EVENT_NAME = 'StartExternalVideoPubMsg'; const { meetingId, requesterUserId: userId } = extractCredentials(this.userId); const { externalVideoUrl } = options; @@ -19,20 +17,15 @@ export default function startWatchingExternalVideo(options) { check(userId, String); check(externalVideoUrl, String); - const user = Users.findOne({ meetingId, userId, presenter: true }, { presenter: 1 }); + const user = Users.findOne({ meetingId, userId }, { presenter: 1 }); - if (!user) { - Logger.error(`Only presenters are allowed to start external video for a meeting. meeting=${meetingId} userId=${userId}`); - return; + if (user && user.presenter) { + check(externalVideoUrl, String); + const payload = { externalVideoUrl }; + Logger.debug(`User id=${userId} sending ${EVENT_NAME} url:${externalVideoUrl} for meeting ${meetingId}`); + return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, userId, payload); } - - Meetings.update({ meetingId }, { $set: { externalVideoUrl } }); - - const payload = { externalVideoUrl }; - - Logger.info(`User id=${userId} sharing an external video: ${externalVideoUrl} for meeting ${meetingId}`); - - return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, userId, payload); + Logger.error(`Only presenters are allowed to start external video for a meeting. meeting=${meetingId} userId=${userId}`); } catch (error) { Logger.error(`Error on sharing an external video: ${externalVideoUrl} ${error}`); } diff --git a/bigbluebutton-html5/imports/api/external-videos/server/methods/stopWatchingExternalVideo.js b/bigbluebutton-html5/imports/api/external-videos/server/methods/stopWatchingExternalVideo.js index c1fe37b6c7378c69f1bd747e6a28c4a8326e4d59..fba0d10e0cea2f8f519581c6396a0d26a42f5aa5 100644 --- a/bigbluebutton-html5/imports/api/external-videos/server/methods/stopWatchingExternalVideo.js +++ b/bigbluebutton-html5/imports/api/external-videos/server/methods/stopWatchingExternalVideo.js @@ -1,41 +1,22 @@ -import { Meteor } from 'meteor/meteor'; +import { check } from 'meteor/check'; import Logger from '/imports/startup/server/logger'; -import Meetings from '/imports/api/meetings'; import Users from '/imports/api/users'; -import RedisPubSub from '/imports/startup/server/redis'; +import stopWatchingExternalVideoSystemCall from '/imports/api/external-videos/server/methods/stopWatchingExternalVideoSystemCall'; import { extractCredentials } from '/imports/api/common/server/helpers'; -export default function stopWatchingExternalVideo(options) { - const REDIS_CONFIG = Meteor.settings.private.redis; - const CHANNEL = REDIS_CONFIG.channels.toAkkaApps; - const EVENT_NAME = 'StopExternalVideoMsg'; - - const { meetingId, requesterUserId } = this.userId ? extractCredentials(this.userId) : options; +export default function stopWatchingExternalVideo() { + const { meetingId, requesterUserId } = extractCredentials(this.userId); try { check(meetingId, String); check(requesterUserId, String); - const user = Users.findOne({ - meetingId, - userId: requesterUserId, - presenter: true, - }, { presenter: 1 }); + const user = Users.findOne({ meetingId, userId: requesterUserId }); - if (this.userId && !user) { - Logger.error(`Only presenters are allowed to stop external video for a meeting. meeting=${meetingId} userId=${requesterUserId}`); - return; + if (user && user.presenter) { + // proceed and publish the event + stopWatchingExternalVideoSystemCall({ meetingId, requesterUserId }); } - - const meeting = Meetings.findOne({ meetingId }); - if (!meeting || meeting.externalVideoUrl === null) return; - - Meetings.update({ meetingId }, { $set: { externalVideoUrl: null } }); - const payload = {}; - - Logger.info(`User id=${requesterUserId} stopped sharing an external video for meeting=${meetingId}`); - - RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload); } catch (error) { Logger.error(`Error on stop sharing an external video for meeting=${meetingId} ${error}`); } diff --git a/bigbluebutton-html5/imports/api/external-videos/server/methods/stopWatchingExternalVideoSystemCall.js b/bigbluebutton-html5/imports/api/external-videos/server/methods/stopWatchingExternalVideoSystemCall.js new file mode 100644 index 0000000000000000000000000000000000000000..70d5a6561ba5d6555071451d6f79daa96352a99d --- /dev/null +++ b/bigbluebutton-html5/imports/api/external-videos/server/methods/stopWatchingExternalVideoSystemCall.js @@ -0,0 +1,26 @@ +import { check } from 'meteor/check'; +import Logger from '/imports/startup/server/logger'; +import Meetings from '/imports/api/meetings'; +import RedisPubSub from '/imports/startup/server/redis'; + +export default function stopWatchingExternalVideoSystemCall({ meetingId, requesterUserId }) { + const REDIS_CONFIG = Meteor.settings.private.redis; + const CHANNEL = REDIS_CONFIG.channels.toAkkaApps; + const EVENT_NAME = 'StopExternalVideoPubMsg'; + + try { + check(meetingId, String); + check(requesterUserId, String); + + // check if there is ongoing video shared + const meeting = Meetings.findOne({ meetingId }); + if (!meeting || meeting.externalVideoUrl === null) return; + + Logger.info('ExternalVideo::stopWatchingExternalVideo was triggered ', { meetingId, requesterUserId }); + + const payload = { }; + return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload); + } catch (error) { + Logger.error(`Error on stop sharing an external video for meeting=${meetingId} ${error}`); + } +} diff --git a/bigbluebutton-html5/imports/api/external-videos/server/streamer.js b/bigbluebutton-html5/imports/api/external-videos/server/streamer.js new file mode 100644 index 0000000000000000000000000000000000000000..fbb34bf112b6f4241b9b4f130d86ac05cb1273fe --- /dev/null +++ b/bigbluebutton-html5/imports/api/external-videos/server/streamer.js @@ -0,0 +1,45 @@ +import { Meteor } from 'meteor/meteor'; +import Logger from '/imports/startup/server/logger'; + +const allowRecentMessages = (eventName, message) => { + + const { + userId, + meetingId, + time, + rate, + state, + } = message; + + Logger.debug(`ExternalVideo Streamer auth allowed userId: ${userId}, meetingId: ${meetingId}, event: ${eventName}, time: ${time} rate: ${rate}, state: ${state}`); + return true; +}; + +export function removeExternalVideoStreamer(meetingId) { + const streamName = `external-videos-${meetingId}`; + + if (Meteor.StreamerCentral.instances[streamName]) { + Logger.info(`Destroying External Video streamer object for ${streamName}`); + delete Meteor.StreamerCentral.instances[streamName]; + } +} + +export function addExternalVideoStreamer(meetingId) { + + const streamName = `external-videos-${meetingId}`; + if (!Meteor.StreamerCentral.instances[streamName]) { + + const streamer = new Meteor.Streamer(streamName); + streamer.allowRead('all'); + streamer.allowWrite('none'); + streamer.allowEmit(allowRecentMessages); + Logger.info(`Created External Video streamer for ${streamName}`); + } else { + Logger.debug(`External Video streamer is already created for ${streamName}`); + } +} + +export default function get(meetingId) { + const streamName = `external-videos-${meetingId}`; + return Meteor.StreamerCentral.instances[streamName]; +} diff --git a/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingDestruction.js b/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingDestruction.js index 31559458d55553e4c72e5bb77be1ad136ea1256a..a090f4d14f0f99d7f9c0044ccaa0b8f7fa06f45c 100644 --- a/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingDestruction.js +++ b/bigbluebutton-html5/imports/api/meetings/server/handlers/meetingDestruction.js @@ -1,9 +1,9 @@ import RedisPubSub from '/imports/startup/server/redis'; import { check } from 'meteor/check'; -import destroyExternalVideo from '/imports/api/external-videos/server/methods/destroyExternalVideo'; import { removeAnnotationsStreamer } from '/imports/api/annotations/server/streamer'; import { removeCursorStreamer } from '/imports/api/cursor/server/streamer'; +import { removeExternalVideoStreamer } from '/imports/api/external-videos/server/streamer'; export default function handleMeetingDestruction({ body }) { check(body, Object); @@ -11,9 +11,9 @@ export default function handleMeetingDestruction({ body }) { check(meetingId, String); if (!process.env.BBB_HTML5_ROLE || process.env.BBB_HTML5_ROLE === 'frontend') { - destroyExternalVideo(meetingId); removeAnnotationsStreamer(meetingId); removeCursorStreamer(meetingId); + removeExternalVideoStreamer(meetingId); } return RedisPubSub.destroyMeetingQueue(meetingId); diff --git a/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js b/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js index 48fad9cb24dfa93aaa5d12e66db3f0d5585a9ced..a17bec63f2b851c3e0b2c3305371cda8fff4ce4d 100755 --- a/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js +++ b/bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js @@ -10,6 +10,7 @@ import createNote from '/imports/api/note/server/methods/createNote'; import createCaptions from '/imports/api/captions/server/methods/createCaptions'; import { addAnnotationsStreamer } from '/imports/api/annotations/server/streamer'; import { addCursorStreamer } from '/imports/api/cursor/server/streamer'; +import { addExternalVideoStreamer } from '/imports/api/external-videos/server/streamer'; import BannedUsers from '/imports/api/users/server/store/bannedUsers'; export default function addMeeting(meeting) { @@ -156,7 +157,7 @@ export default function addMeeting(meeting) { if (!process.env.BBB_HTML5_ROLE || process.env.BBB_HTML5_ROLE === 'frontend') { addAnnotationsStreamer(meetingId); addCursorStreamer(meetingId); - // TODO add addExternalVideoStreamer(meetingId); + addExternalVideoStreamer(meetingId); // we don't want to fully process the create meeting message in frontend since it can lead to duplication of meetings in mongo. if (process.env.BBB_HTML5_ROLE === 'frontend') { diff --git a/bigbluebutton-html5/imports/api/meetings/server/modifiers/meetingHasEnded.js b/bigbluebutton-html5/imports/api/meetings/server/modifiers/meetingHasEnded.js index 4d916a4b363840068c07a11157a48819c6a8a944..4448dc1908b13e6b6023d0faedbaa3f1b5d27dd6 100755 --- a/bigbluebutton-html5/imports/api/meetings/server/modifiers/meetingHasEnded.js +++ b/bigbluebutton-html5/imports/api/meetings/server/modifiers/meetingHasEnded.js @@ -4,6 +4,7 @@ import Logger from '/imports/startup/server/logger'; import BannedUsers from '/imports/api/users/server/store/bannedUsers'; import { removeAnnotationsStreamer } from '/imports/api/annotations/server/streamer'; import { removeCursorStreamer } from '/imports/api/cursor/server/streamer'; +import { removeExternalVideoStreamer } from '/imports/api/external-videos/server/streamer'; import clearUsers from '/imports/api/users/server/modifiers/clearUsers'; import clearUsersSettings from '/imports/api/users-settings/server/modifiers/clearUsersSettings'; @@ -34,7 +35,7 @@ export default function meetingHasEnded(meetingId) { if (!process.env.BBB_HTML5_ROLE || process.env.BBB_HTML5_ROLE === 'frontend') { removeAnnotationsStreamer(meetingId); removeCursorStreamer(meetingId); - // TODO add removeExternalVideoStreamer(meetingId); + removeExternalVideoStreamer(meetingId); } return Meetings.remove({ meetingId }, () => { diff --git a/bigbluebutton-html5/imports/api/screenshare/server/handlers/screenshareStarted.js b/bigbluebutton-html5/imports/api/screenshare/server/handlers/screenshareStarted.js index 503020326345ff4987d48745cf0f184fadab5ec3..09b45e4be0b83470988a06cb43e5e3818c7ab7d2 100644 --- a/bigbluebutton-html5/imports/api/screenshare/server/handlers/screenshareStarted.js +++ b/bigbluebutton-html5/imports/api/screenshare/server/handlers/screenshareStarted.js @@ -1,20 +1,17 @@ import { check } from 'meteor/check'; import Meetings from '/imports/api/meetings'; -import Users from '/imports/api/users'; import addScreenshare from '../modifiers/addScreenshare'; import Logger from '/imports/startup/server/logger'; -import stopWatchingExternalVideo from '/imports/api/external-videos/server/methods/stopWatchingExternalVideo'; +import stopWatchingExternalVideoSystemCall from '/imports/api/external-videos/server/methods/stopWatchingExternalVideoSystemCall'; export default function handleScreenshareStarted({ body }, meetingId) { check(meetingId, String); check(body, Object); const meeting = Meetings.findOne({ meetingId }); - const presenter = Users.findOne({ meetingId, presenter: true }); - const presenterId = presenter && presenter.userId ? presenter.userId : 'system-screenshare-starting'; if (meeting && meeting.externalVideoUrl) { Logger.info(`ScreenshareStarted: There is external video being shared. Stopping it due to presenter change, ${meeting.externalVideoUrl}`); - stopWatchingExternalVideo({ meetingId, requesterUserId: presenterId }); + stopWatchingExternalVideoSystemCall({ meetingId, requesterUserId: 'system-screenshare-starting' }); } return addScreenshare(meetingId, body); } diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/changePresenter.js b/bigbluebutton-html5/imports/api/users/server/modifiers/changePresenter.js index dcfe69f36a2ee951340ac0e242b945c7887e2583..baeaadbce4e20fa8353ed26572b50d7fb78bccbb 100755 --- a/bigbluebutton-html5/imports/api/users/server/modifiers/changePresenter.js +++ b/bigbluebutton-html5/imports/api/users/server/modifiers/changePresenter.js @@ -1,7 +1,7 @@ import Logger from '/imports/startup/server/logger'; import Users from '/imports/api/users'; import Meetings from '/imports/api/meetings'; -import stopWatchingExternalVideo from '/imports/api/external-videos/server/methods/stopWatchingExternalVideo'; +import stopWatchingExternalVideoSystemCall from '/imports/api/external-videos/server/methods/stopWatchingExternalVideoSystemCall'; export default function changePresenter(presenter, userId, meetingId, changedBy) { const selector = { @@ -19,7 +19,7 @@ export default function changePresenter(presenter, userId, meetingId, changedBy) const meeting = Meetings.findOne({ meetingId }); if (meeting && meeting.externalVideoUrl) { Logger.info(`ChangePresenter:There is external video being shared. Stopping it due to presenter change, ${meeting.externalVideoUrl}`); - stopWatchingExternalVideo({ meetingId, requesterUserId: userId }); + stopWatchingExternalVideoSystemCall({ meetingId, requesterUserId: 'system-presenter-changed' }); } const numberAffected = Users.update(selector, modifier); diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/removeUser.js b/bigbluebutton-html5/imports/api/users/server/modifiers/removeUser.js index ead54a6ae451dfc05f2b293d04a1878cc28bfe25..48e005873d09cb61a4126f9de45e1b1b48f0c3f3 100755 --- a/bigbluebutton-html5/imports/api/users/server/modifiers/removeUser.js +++ b/bigbluebutton-html5/imports/api/users/server/modifiers/removeUser.js @@ -2,7 +2,7 @@ import { check } from 'meteor/check'; import Users from '/imports/api/users'; import VideoStreams from '/imports/api/video-streams'; import Logger from '/imports/startup/server/logger'; -import stopWatchingExternalVideo from '/imports/api/external-videos/server/methods/stopWatchingExternalVideo'; +import stopWatchingExternalVideoSystemCall from '/imports/api/external-videos/server/methods/stopWatchingExternalVideoSystemCall'; import clearUserInfoForRequester from '/imports/api/users-infos/server/modifiers/clearUserInfoForRequester'; import ClientConnections from '/imports/startup/server/ClientConnections'; @@ -22,7 +22,7 @@ export default function removeUser(meetingId, userId) { if (userToRemove) { const { presenter } = userToRemove; if (presenter) { - stopWatchingExternalVideo({ meetingId, requesterUserId: userId }); + stopWatchingExternalVideoSystemCall({ meetingId, requesterUserId: 'system-presenter-was-removed' }); } } diff --git a/bigbluebutton-html5/imports/api/users/server/store/bannedUsers.js b/bigbluebutton-html5/imports/api/users/server/store/bannedUsers.js index 30c7d8f792f62913deb63fa2534983482c82f74e..fff7e6e422e1dc6c162abcc903c3e76ec440d518 100644 --- a/bigbluebutton-html5/imports/api/users/server/store/bannedUsers.js +++ b/bigbluebutton-html5/imports/api/users/server/store/bannedUsers.js @@ -1,4 +1,4 @@ -import {check} from 'meteor/check'; +import { check } from 'meteor/check'; import Logger from '/imports/startup/server/logger'; class BannedUsers { @@ -10,12 +10,12 @@ class BannedUsers { // types of queries for the users: // 1. meetingId // 2. meetingId, userId - this.store._ensureIndex({meetingId: 1, userId: 1}); + this.store._ensureIndex({ meetingId: 1, userId: 1 }); } } init(meetingId) { - Logger.debug('BannedUsers :: init', {meetingId}); + Logger.debug('BannedUsers :: init', { meetingId }); // if (!this.store[meetingId]) this.store[meetingId] = new Set(); } @@ -24,7 +24,7 @@ class BannedUsers { check(meetingId, String); check(externalId, String); - Logger.debug('BannedUsers :: add', {meetingId, externalId}); + Logger.debug('BannedUsers :: add', { meetingId, externalId }); const selector = { meetingId, @@ -32,18 +32,18 @@ class BannedUsers { }; const modifier = Object.assign( // TODO - {meetingId}, - {externalId}, + { meetingId }, + { externalId }, ); try { const insertedId = this.store.upsert(selector, modifier); if (insertedId) { - Logger.info('BannedUsers :: Added to BannedUsers collection', {meetingId, externalId}); + Logger.info('BannedUsers :: Added to BannedUsers collection', { meetingId, externalId }); } } catch (err) { - Logger.error('BannedUsers :: Error on adding to BannedUsers collection', {meetingId, externalId, err}); + Logger.error('BannedUsers :: Error on adding to BannedUsers collection', { meetingId, externalId, err }); } } @@ -56,9 +56,9 @@ class BannedUsers { try { this.store.remove(selector); - Logger.info('BannedUsers :: Removed meeting', {meetingId}); + Logger.info('BannedUsers :: Removed meeting', { meetingId }); } catch (err) { - Logger.error('BannedUsers :: Removing from collection', {err}); + Logger.error('BannedUsers :: Removing from collection', { err }); } } @@ -66,9 +66,9 @@ class BannedUsers { check(meetingId, String); check(externalId, String); - Logger.info('BannedUsers :: has', {meetingId, externalId}); + Logger.info('BannedUsers :: has', { meetingId, externalId }); - return this.store.findOne({meetingId, externalId}); + return this.store.findOne({ meetingId, externalId }); } } diff --git a/bigbluebutton-html5/imports/ui/components/external-video-player/service.js b/bigbluebutton-html5/imports/ui/components/external-video-player/service.js index 9de4de3c7aa4f426542756442ce902a89c1335ec..153ba4e8047d727b56f0178e60dc123db5a265a7 100644 --- a/bigbluebutton-html5/imports/ui/components/external-video-player/service.js +++ b/bigbluebutton-html5/imports/ui/components/external-video-player/service.js @@ -1,7 +1,5 @@ import Meetings from '/imports/api/meetings'; -import Users from '/imports/api/users'; import Auth from '/imports/ui/services/auth'; -import Logger from '/imports/startup/client/logger'; import { getStreamer } from '/imports/api/external-videos'; import { makeCall } from '/imports/ui/services/api'; @@ -28,11 +26,24 @@ const stopWatching = () => { makeCall('stopWatchingExternalVideo'); }; +let lastMessage = null; + const sendMessage = (event, data) => { - const meetingId = Auth.meetingID; - const userId = Auth.userID; - makeCall('emitExternalVideoEvent', event, { ...data, meetingId, userId }); + // don't re-send repeated update messages + if (lastMessage && lastMessage.event === event + && event === 'playerUpdate' && lastMessage.time === data.time) { + return; + } + + // don't register to redis a viewer joined message + if (event === 'viewerJoined') { + return; + } + + lastMessage = { ...data, event }; + + makeCall('emitExternalVideoEvent', { status: event, playerStatus: data }); }; const onMessage = (message, func) => {