Merge branch 'ritzalam-work-on-meeting-lifcycle-2' into bbb-2x-mconf
This commit is contained in:
commit
d1cc692791
@ -59,21 +59,21 @@ class BigBlueButtonActor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
def receive = {
|
def receive = {
|
||||||
// 2x messages
|
// Internal messages
|
||||||
case msg: BbbCommonEnvCoreMsg => handleBbbCommonEnvCoreMsg(msg)
|
case msg: DestroyMeetingInternalMsg => handleDestroyMeeting(msg)
|
||||||
|
|
||||||
case msg: ValidateAuthToken => handleValidateAuthToken(msg)
|
// 2x messages
|
||||||
case _ => // do nothing
|
case msg: BbbCommonEnvCoreMsg => handleBbbCommonEnvCoreMsg(msg)
|
||||||
|
case _ => // do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
private def handleBbbCommonEnvCoreMsg(msg: BbbCommonEnvCoreMsg): Unit = {
|
private def handleBbbCommonEnvCoreMsg(msg: BbbCommonEnvCoreMsg): Unit = {
|
||||||
msg.core match {
|
msg.core match {
|
||||||
case m: CreateMeetingReqMsg => handleCreateMeetingReqMsg(m)
|
case m: CreateMeetingReqMsg => handleCreateMeetingReqMsg(m)
|
||||||
case m: RegisterUserReqMsg => handleRegisterUserReqMsg(m)
|
case m: RegisterUserReqMsg => handleRegisterUserReqMsg(m)
|
||||||
case m: GetAllMeetingsReqMsg => handleGetAllMeetingsReqMsg(m)
|
case m: GetAllMeetingsReqMsg => handleGetAllMeetingsReqMsg(m)
|
||||||
case m: PubSubPingSysReqMsg => handlePubSubPingSysReqMsg(m)
|
case m: PubSubPingSysReqMsg => handlePubSubPingSysReqMsg(m)
|
||||||
case m: DestroyMeetingSysCmdMsg => handleDestroyMeeting(m)
|
case _ => log.warning("Cannot handle " + msg.envelope.name)
|
||||||
case _ => log.warning("Cannot handle " + msg.envelope.name)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,68 +125,38 @@ class BigBlueButtonActor(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private def handleValidateAuthToken(msg: ValidateAuthToken) {
|
|
||||||
for {
|
|
||||||
m <- RunningMeetings.findWithId(meetings, msg.meetingID)
|
|
||||||
} yield {
|
|
||||||
m.actorRef forward (msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
//meetings.get(msg.meetingID) foreach { m =>
|
|
||||||
// m.actorRef ! msg
|
|
||||||
|
|
||||||
// val future = m.actorRef.ask(msg)(5 seconds)
|
|
||||||
// future onComplete {
|
|
||||||
// case Success(result) => {
|
|
||||||
// log.info("Validate auth token response. meetingId=" + msg.meetingID + " userId=" + msg.userId + " token=" + msg.token)
|
|
||||||
// /**
|
|
||||||
// * Received a reply from MeetingActor which means hasn't hung!
|
|
||||||
// * Sometimes, the actor seems to hang and doesn't anymore accept messages. This is a simple
|
|
||||||
// * audit to check whether the actor is still alive. (ralam feb 25, 2015)
|
|
||||||
// */
|
|
||||||
// }
|
|
||||||
// case Failure(failure) => {
|
|
||||||
// log.warning("Validate auth token timeout. meetingId=" + msg.meetingID + " userId=" + msg.userId + " token=" + msg.token)
|
|
||||||
// outGW.send(new ValidateAuthTokenTimedOut(msg.meetingID, msg.userId, msg.token, false, msg.correlationId))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
private def handlePubSubPingSysReqMsg(msg: PubSubPingSysReqMsg): Unit = {
|
private def handlePubSubPingSysReqMsg(msg: PubSubPingSysReqMsg): Unit = {
|
||||||
val event = MsgBuilder.buildPubSubPongSysRespMsg(msg.body.system, msg.body.timestamp)
|
val event = MsgBuilder.buildPubSubPongSysRespMsg(msg.body.system, msg.body.timestamp)
|
||||||
outGW.send(event)
|
outGW.send(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def handleDestroyMeeting(msg: DestroyMeetingSysCmdMsg): Unit = {
|
private def handleDestroyMeeting(msg: DestroyMeetingInternalMsg): Unit = {
|
||||||
|
|
||||||
for {
|
for {
|
||||||
m <- RunningMeetings.findWithId(meetings, msg.body.meetingId)
|
m <- RunningMeetings.findWithId(meetings, msg.meetingId)
|
||||||
m2 <- RunningMeetings.remove(meetings, msg.body.meetingId)
|
m2 <- RunningMeetings.remove(meetings, msg.meetingId)
|
||||||
} yield {
|
} yield {
|
||||||
// send the message for MeetingActor to handle too
|
/** Unsubscribe to meeting and voice events. **/
|
||||||
m.actorRef ! msg
|
eventBus.unsubscribe(m.actorRef, m.props.meetingProp.intId)
|
||||||
|
eventBus.unsubscribe(m.actorRef, m.props.voiceProp.voiceConf)
|
||||||
|
eventBus.unsubscribe(m.actorRef, m.props.screenshareProps.screenshareConf)
|
||||||
|
|
||||||
// Delay sending DisconnectAllUsers because of RTMPT connection being dropped before UserEject message arrives to the client
|
bbbMsgBus.unsubscribe(m.actorRef, m.props.meetingProp.intId)
|
||||||
|
bbbMsgBus.unsubscribe(m.actorRef, m.props.voiceProp.voiceConf)
|
||||||
|
bbbMsgBus.unsubscribe(m.actorRef, m.props.screenshareProps.screenshareConf)
|
||||||
|
|
||||||
|
// Delay sending DisconnectAllUsers to allow messages to reach the client
|
||||||
|
// before the connections are closed.
|
||||||
context.system.scheduler.scheduleOnce(Duration.create(2500, TimeUnit.MILLISECONDS)) {
|
context.system.scheduler.scheduleOnce(Duration.create(2500, TimeUnit.MILLISECONDS)) {
|
||||||
// Disconnect all clients
|
// Disconnect all clients
|
||||||
|
|
||||||
val disconnectEvnt = MsgBuilder.buildDisconnectAllClientsSysMsg(msg.body.meetingId)
|
val disconnectEvnt = MsgBuilder.buildDisconnectAllClientsSysMsg(msg.meetingId)
|
||||||
outGW.send(disconnectEvnt)
|
outGW.send(disconnectEvnt)
|
||||||
|
|
||||||
log.info("Destroyed meetingId={}", msg.body.meetingId)
|
log.info("Destroyed meetingId={}", msg.meetingId)
|
||||||
val destroyedEvent = MsgBuilder.buildMeetingDestroyedEvtMsg(msg.body.meetingId)
|
val destroyedEvent = MsgBuilder.buildMeetingDestroyedEvtMsg(msg.meetingId)
|
||||||
outGW.send(destroyedEvent)
|
outGW.send(destroyedEvent)
|
||||||
|
|
||||||
/** Unsubscribe to meeting and voice events. **/
|
|
||||||
eventBus.unsubscribe(m.actorRef, m.props.meetingProp.intId)
|
|
||||||
eventBus.unsubscribe(m.actorRef, m.props.voiceProp.voiceConf)
|
|
||||||
eventBus.unsubscribe(m.actorRef, m.props.screenshareProps.screenshareConf)
|
|
||||||
|
|
||||||
bbbMsgBus.unsubscribe(m.actorRef, m.props.meetingProp.intId)
|
|
||||||
bbbMsgBus.unsubscribe(m.actorRef, m.props.voiceProp.voiceConf)
|
|
||||||
bbbMsgBus.unsubscribe(m.actorRef, m.props.screenshareProps.screenshareConf)
|
|
||||||
|
|
||||||
// Stop the meeting actor.
|
// Stop the meeting actor.
|
||||||
context.stop(m.actorRef)
|
context.stop(m.actorRef)
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ class BigBlueButtonInGW(
|
|||||||
eventBus.publish(
|
eventBus.publish(
|
||||||
BigBlueButtonEvent(
|
BigBlueButtonEvent(
|
||||||
"meeting-manager",
|
"meeting-manager",
|
||||||
new DestroyMeeting(
|
new DestroyMeetingInternalMsg(
|
||||||
meetingID
|
meetingID
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -18,13 +18,18 @@ case class IsMeetingActorAliveMessage(meetingId: String) extends InMessage
|
|||||||
case class KeepAliveMessage(aliveID: String) extends InMessage
|
case class KeepAliveMessage(aliveID: String) extends InMessage
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// Meeting
|
// Internal Messages
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
case class MonitorNumberOfUsers(meetingID: String) extends InMessage
|
case class MonitorNumberOfUsersInternalMsg(meetingID: String) extends InMessage
|
||||||
case class SendTimeRemainingUpdate(meetingId: String) extends InMessage
|
case class SendTimeRemainingUpdate(meetingId: String) extends InMessage
|
||||||
case class ExtendMeetingDuration(meetingId: String, userId: String) extends InMessage
|
case class ExtendMeetingDuration(meetingId: String, userId: String) extends InMessage
|
||||||
case class DestroyMeeting(meetingID: String) extends InMessage
|
case class DestroyMeetingInternalMsg(meetingId: String) extends InMessage
|
||||||
|
case class BreakoutRoomEndedInternalMsg(meetingId: String) extends InMessage
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Meeting
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
case class StartMeeting(meetingID: String) extends InMessage
|
case class StartMeeting(meetingID: String) extends InMessage
|
||||||
case class EndMeeting(meetingId: String) extends InMessage
|
case class EndMeeting(meetingId: String) extends InMessage
|
||||||
case class LockSetting(meetingID: String, locked: Boolean, settings: Map[String, Boolean]) extends InMessage
|
case class LockSetting(meetingID: String, locked: Boolean, settings: Map[String, Boolean]) extends InMessage
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package org.bigbluebutton.core.apps
|
package org.bigbluebutton.core.apps
|
||||||
|
|
||||||
import org.bigbluebutton.core.running.MeetingActor
|
import org.bigbluebutton.core.running.MeetingActor
|
||||||
import org.bigbluebutton.core2.message.handlers.guests.{ GetGuestsWaitingApprovalReqMsgHdlr, GuestsWaitingApprovedMsgHdlr, SetGuestPolicyMsgHdlr }
|
import org.bigbluebutton.core2.message.handlers.guests.{ GetGuestPolicyReqMsgHdlr, GetGuestsWaitingApprovalReqMsgHdlr, GuestsWaitingApprovedMsgHdlr, SetGuestPolicyMsgHdlr }
|
||||||
|
|
||||||
trait GuestsApp extends GetGuestsWaitingApprovalReqMsgHdlr
|
trait GuestsApp extends GetGuestsWaitingApprovalReqMsgHdlr
|
||||||
with GuestsWaitingApprovedMsgHdlr
|
with GuestsWaitingApprovedMsgHdlr
|
||||||
with SetGuestPolicyMsgHdlr {
|
with SetGuestPolicyMsgHdlr
|
||||||
|
with GetGuestPolicyReqMsgHdlr {
|
||||||
|
|
||||||
this: MeetingActor =>
|
this: MeetingActor =>
|
||||||
|
|
||||||
|
@ -11,8 +11,6 @@ trait PresentationConversionCompletedPubMsgHdlr {
|
|||||||
val outGW: OutMessageGateway
|
val outGW: OutMessageGateway
|
||||||
|
|
||||||
def handlePresentationConversionCompletedPubMsg(msg: PresentationConversionCompletedSysPubMsg): Unit = {
|
def handlePresentationConversionCompletedPubMsg(msg: PresentationConversionCompletedSysPubMsg): Unit = {
|
||||||
log.debug("**************** !!!!!PresentationConversionCompletedPubMsg ")
|
|
||||||
|
|
||||||
def broadcastEvent(msg: PresentationConversionCompletedSysPubMsg): Unit = {
|
def broadcastEvent(msg: PresentationConversionCompletedSysPubMsg): Unit = {
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, msg.header.userId)
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, msg.header.userId)
|
||||||
val envelope = BbbCoreEnvelope(PresentationConversionCompletedEvtMsg.NAME, routing)
|
val envelope = BbbCoreEnvelope(PresentationConversionCompletedEvtMsg.NAME, routing)
|
||||||
|
@ -9,7 +9,7 @@ trait PresentationConversionUpdatePubMsgHdlr {
|
|||||||
val outGW: OutMessageGateway
|
val outGW: OutMessageGateway
|
||||||
|
|
||||||
def handlePresentationConversionUpdatePubMsg(msg: PresentationConversionUpdateSysPubMsg): Unit = {
|
def handlePresentationConversionUpdatePubMsg(msg: PresentationConversionUpdateSysPubMsg): Unit = {
|
||||||
log.debug("**************** !!!!!PresentationConversionUpdateSysPubMsg " + msg.body.messageKey)
|
|
||||||
def broadcastEvent(msg: PresentationConversionUpdateSysPubMsg): Unit = {
|
def broadcastEvent(msg: PresentationConversionUpdateSysPubMsg): Unit = {
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, msg.header.userId)
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, msg.header.userId)
|
||||||
val envelope = BbbCoreEnvelope(PresentationConversionUpdateEvtMsg.NAME, routing)
|
val envelope = BbbCoreEnvelope(PresentationConversionUpdateEvtMsg.NAME, routing)
|
||||||
|
@ -9,7 +9,6 @@ trait PresentationPageGeneratedPubMsgHdlr {
|
|||||||
val outGW: OutMessageGateway
|
val outGW: OutMessageGateway
|
||||||
|
|
||||||
def handlePresentationPageGeneratedPubMsg(msg: PresentationPageGeneratedSysPubMsg): Unit = {
|
def handlePresentationPageGeneratedPubMsg(msg: PresentationPageGeneratedSysPubMsg): Unit = {
|
||||||
log.debug("**************** !!!!!PresentationPageGeneratedSysPubMsg " + msg.body.messageKey)
|
|
||||||
|
|
||||||
def broadcastEvent(msg: PresentationPageGeneratedSysPubMsg): Unit = {
|
def broadcastEvent(msg: PresentationPageGeneratedSysPubMsg): Unit = {
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, msg.header.userId)
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, msg.header.userId)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package org.bigbluebutton.core2.message.handlers.users
|
package org.bigbluebutton.core.apps.users
|
||||||
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
import org.bigbluebutton.core.models.Users2x
|
import org.bigbluebutton.core.models.Users2x
|
||||||
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, MeetingActor }
|
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting }
|
||||||
|
|
||||||
trait ChangeUserEmojiCmdMsgHdlr {
|
trait ChangeUserEmojiCmdMsgHdlr {
|
||||||
this: BaseMeetingActor =>
|
this: BaseMeetingActor =>
|
@ -11,8 +11,8 @@ trait GetUsersMeetingReqMsgHdlr extends HandlerHelpers {
|
|||||||
val outGW: OutMessageGateway
|
val outGW: OutMessageGateway
|
||||||
|
|
||||||
def handleGetUsersMeetingReqMsg(msg: GetUsersMeetingReqMsg): Unit = {
|
def handleGetUsersMeetingReqMsg(msg: GetUsersMeetingReqMsg): Unit = {
|
||||||
sendAllUsersInMeeting(outGW, msg.body.userId, liveMeeting)
|
sendAllUsersInMeeting(msg.body.userId)
|
||||||
sendAllVoiceUsersInMeeting(outGW, msg.body.userId, liveMeeting.voiceUsers, liveMeeting.props.meetingProp.intId)
|
sendAllVoiceUsersInMeeting(msg.body.userId, liveMeeting.voiceUsers, liveMeeting.props.meetingProp.intId)
|
||||||
sendAllWebcamStreams(outGW, msg.body.userId, liveMeeting.webcams, liveMeeting.props.meetingProp.intId)
|
sendAllWebcamStreams(outGW, msg.body.userId, liveMeeting.webcams, liveMeeting.props.meetingProp.intId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package org.bigbluebutton.core2.message.handlers.users
|
package org.bigbluebutton.core.apps.users
|
||||||
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
@ -2,56 +2,25 @@ package org.bigbluebutton.core.apps.users
|
|||||||
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
import org.bigbluebutton.core.api.{ EndMeeting, LogoutEndMeeting }
|
import org.bigbluebutton.core.bus.IncomingEventBus
|
||||||
|
import org.bigbluebutton.core.domain.MeetingEndReason
|
||||||
import org.bigbluebutton.core.models.{ Roles, Users2x }
|
import org.bigbluebutton.core.models.{ Roles, Users2x }
|
||||||
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting }
|
import org.bigbluebutton.core.running.LiveMeeting
|
||||||
import org.bigbluebutton.core2.MeetingStatus2x
|
|
||||||
|
|
||||||
trait LogoutAndEndMeetingCmdMsgHdlr {
|
trait LogoutAndEndMeetingCmdMsgHdlr {
|
||||||
this: UsersApp =>
|
this: UsersApp =>
|
||||||
|
|
||||||
val liveMeeting: LiveMeeting
|
val liveMeeting: LiveMeeting
|
||||||
val outGW: OutMessageGateway
|
val outGW: OutMessageGateway
|
||||||
|
val eventBus: IncomingEventBus
|
||||||
|
|
||||||
def handleLogoutAndEndMeetingCmdMsg(msg: LogoutAndEndMeetingCmdMsg) {
|
def handleLogoutAndEndMeetingCmdMsg(msg: LogoutAndEndMeetingCmdMsg) {
|
||||||
for {
|
for {
|
||||||
u <- Users2x.findWithIntId(liveMeeting.users2x, msg.body.userId)
|
u <- Users2x.findWithIntId(liveMeeting.users2x, msg.body.userId)
|
||||||
} yield {
|
} yield {
|
||||||
if (u.role == Roles.MODERATOR_ROLE) {
|
if (u.role == Roles.MODERATOR_ROLE) {
|
||||||
endMeeting()
|
sendEndMeetingDueToExpiry(MeetingEndReason.ENDED_AFTER_USER_LOGGED_OUT, eventBus, outGW, liveMeeting)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def endMeeting(): Unit = {
|
|
||||||
def buildMeetingEndingEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
|
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
|
||||||
val envelope = BbbCoreEnvelope(MeetingEndingEvtMsg.NAME, routing)
|
|
||||||
val body = MeetingEndingEvtMsgBody(meetingId)
|
|
||||||
val header = BbbClientMsgHeader(MeetingEndingEvtMsg.NAME, meetingId, "not-used")
|
|
||||||
val event = MeetingEndingEvtMsg(header, body)
|
|
||||||
|
|
||||||
BbbCommonEnvCoreMsg(envelope, event)
|
|
||||||
}
|
|
||||||
|
|
||||||
val endingEvent = buildMeetingEndingEvtMsg(liveMeeting.props.meetingProp.intId)
|
|
||||||
|
|
||||||
// Broadcast users the meeting will end
|
|
||||||
outGW.send(endingEvent)
|
|
||||||
|
|
||||||
MeetingStatus2x.meetingHasEnded(liveMeeting.status)
|
|
||||||
|
|
||||||
def buildMeetingEndedEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
|
|
||||||
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
|
|
||||||
val envelope = BbbCoreEnvelope(MeetingEndedEvtMsg.NAME, routing)
|
|
||||||
val body = MeetingEndedEvtMsgBody(meetingId)
|
|
||||||
val header = BbbCoreBaseHeader(MeetingEndedEvtMsg.NAME)
|
|
||||||
val event = MeetingEndedEvtMsg(header, body)
|
|
||||||
|
|
||||||
BbbCommonEnvCoreMsg(envelope, event)
|
|
||||||
}
|
|
||||||
|
|
||||||
val endedEvnt = buildMeetingEndedEvtMsg(liveMeeting.props.meetingProp.intId)
|
|
||||||
outGW.send(endedEvnt)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package org.bigbluebutton.core.apps.users
|
package org.bigbluebutton.core.apps.users
|
||||||
|
|
||||||
|
import org.bigbluebutton.common2.domain.DefaultProps
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
import org.bigbluebutton.core.domain.MeetingInactivityTracker
|
import org.bigbluebutton.core.domain.{ MeetingInactivityTracker, MeetingState2x }
|
||||||
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, MeetingInactivityTrackerHelper }
|
import org.bigbluebutton.core.running.{ LiveMeeting }
|
||||||
|
|
||||||
trait MeetingActivityResponseCmdMsgHdlr {
|
trait MeetingActivityResponseCmdMsgHdlr {
|
||||||
this: UsersApp =>
|
this: UsersApp =>
|
||||||
@ -12,14 +13,31 @@ trait MeetingActivityResponseCmdMsgHdlr {
|
|||||||
val outGW: OutMessageGateway
|
val outGW: OutMessageGateway
|
||||||
|
|
||||||
def handleMeetingActivityResponseCmdMsg(
|
def handleMeetingActivityResponseCmdMsg(
|
||||||
msg: MeetingActivityResponseCmdMsg,
|
msg: MeetingActivityResponseCmdMsg,
|
||||||
tracker: MeetingInactivityTracker
|
state: MeetingState2x
|
||||||
): MeetingInactivityTracker = {
|
): MeetingState2x = {
|
||||||
MeetingInactivityTrackerHelper.processMeetingActivityResponse(
|
processMeetingActivityResponse(liveMeeting.props, outGW, msg)
|
||||||
props = liveMeeting.props,
|
MeetingInactivityTracker.resetWarningSentAndTimestamp(state)
|
||||||
outGW,
|
}
|
||||||
msg,
|
|
||||||
tracker
|
def processMeetingActivityResponse(
|
||||||
)
|
props: DefaultProps,
|
||||||
|
outGW: OutMessageGateway,
|
||||||
|
msg: MeetingActivityResponseCmdMsg
|
||||||
|
): Unit = {
|
||||||
|
|
||||||
|
def buildMeetingIsActiveEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
|
||||||
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
||||||
|
val envelope = BbbCoreEnvelope(MeetingIsActiveEvtMsg.NAME, routing)
|
||||||
|
val body = MeetingIsActiveEvtMsgBody(meetingId)
|
||||||
|
val header = BbbClientMsgHeader(MeetingIsActiveEvtMsg.NAME, meetingId, "not-used")
|
||||||
|
val event = MeetingIsActiveEvtMsg(header, body)
|
||||||
|
|
||||||
|
BbbCommonEnvCoreMsg(envelope, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
val event = buildMeetingIsActiveEvtMsg(props.meetingProp.intId)
|
||||||
|
outGW.send(event)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package org.bigbluebutton.core2.message.handlers.users
|
package org.bigbluebutton.core.apps.users
|
||||||
|
|
||||||
import org.bigbluebutton.common2.msgs.MuteUserCmdMsg
|
import org.bigbluebutton.common2.msgs.MuteUserCmdMsg
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
@ -13,22 +13,7 @@ trait RegisterUserReqMsgHdlr {
|
|||||||
val outGW: OutMessageGateway
|
val outGW: OutMessageGateway
|
||||||
|
|
||||||
def handleRegisterUserReqMsg(msg: RegisterUserReqMsg): Unit = {
|
def handleRegisterUserReqMsg(msg: RegisterUserReqMsg): Unit = {
|
||||||
log.debug("****** RECEIVED RegisterUserReqMsg msg {}", msg)
|
log.debug("RECEIVED RegisterUserReqMsg msg {}", msg)
|
||||||
if (MeetingStatus2x.hasMeetingEnded(liveMeeting.status)) {
|
|
||||||
// Check first if the meeting has ended and the user refreshed the client to re-connect.
|
|
||||||
log.info("Register user failed. Mmeeting has ended. meetingId=" + liveMeeting.props.meetingProp.intId +
|
|
||||||
" userId=" + msg.body.intUserId)
|
|
||||||
} else {
|
|
||||||
val regUser = RegisteredUsers.create(msg.body.intUserId, msg.body.extUserId,
|
|
||||||
msg.body.name, msg.body.role, msg.body.authToken,
|
|
||||||
msg.body.avatarURL, msg.body.guest, msg.body.authed, msg.body.guest, liveMeeting.registeredUsers)
|
|
||||||
|
|
||||||
log.info("Register user success. meetingId=" + liveMeeting.props.meetingProp.intId
|
|
||||||
+ " userId=" + msg.body.extUserId + " user=" + regUser)
|
|
||||||
|
|
||||||
val event = buildUserRegisteredRespMsg(liveMeeting.props.meetingProp.intId, regUser.id, regUser.name, regUser.role)
|
|
||||||
outGW.send(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
def buildUserRegisteredRespMsg(meetingId: String, userId: String, name: String, role: String): BbbCommonEnvCoreMsg = {
|
def buildUserRegisteredRespMsg(meetingId: String, userId: String, name: String, role: String): BbbCommonEnvCoreMsg = {
|
||||||
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
|
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
|
||||||
@ -38,5 +23,18 @@ trait RegisterUserReqMsgHdlr {
|
|||||||
val event = UserRegisteredRespMsg(header, body)
|
val event = UserRegisteredRespMsg(header, body)
|
||||||
BbbCommonEnvCoreMsg(envelope, event)
|
BbbCommonEnvCoreMsg(envelope, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val regUser = RegisteredUsers.create(msg.body.intUserId, msg.body.extUserId,
|
||||||
|
msg.body.name, msg.body.role, msg.body.authToken,
|
||||||
|
msg.body.avatarURL, msg.body.guest, msg.body.authed, msg.body.guest)
|
||||||
|
|
||||||
|
RegisteredUsers.add(liveMeeting.registeredUsers, regUser)
|
||||||
|
|
||||||
|
log.info("Register user success. meetingId=" + liveMeeting.props.meetingProp.intId
|
||||||
|
+ " userId=" + msg.body.extUserId + " user=" + regUser)
|
||||||
|
|
||||||
|
val event = buildUserRegisteredRespMsg(liveMeeting.props.meetingProp.intId, regUser.id, regUser.name, regUser.role)
|
||||||
|
outGW.send(event)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package org.bigbluebutton.core2.message.handlers.users
|
package org.bigbluebutton.core.apps.users
|
||||||
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
@ -1,4 +1,4 @@
|
|||||||
package org.bigbluebutton.core2.message.handlers.users
|
package org.bigbluebutton.core.apps.users
|
||||||
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
@ -1,4 +1,4 @@
|
|||||||
package org.bigbluebutton.core2.message.handlers.users
|
package org.bigbluebutton.core.apps.users
|
||||||
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
@ -1,4 +1,4 @@
|
|||||||
package org.bigbluebutton.core2.message.handlers.users
|
package org.bigbluebutton.core.apps.users
|
||||||
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
@ -0,0 +1,19 @@
|
|||||||
|
package org.bigbluebutton.core.apps.users
|
||||||
|
|
||||||
|
import org.bigbluebutton.common2.msgs.UserJoinMeetingReqMsg
|
||||||
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
|
import org.bigbluebutton.core.domain.MeetingState2x
|
||||||
|
import org.bigbluebutton.core.running.{ BaseMeetingActor, HandlerHelpers, LiveMeeting }
|
||||||
|
|
||||||
|
trait UserJoinMeetingReqMsgHdlr extends HandlerHelpers {
|
||||||
|
this: BaseMeetingActor =>
|
||||||
|
|
||||||
|
val liveMeeting: LiveMeeting
|
||||||
|
val outGW: OutMessageGateway
|
||||||
|
|
||||||
|
def handleUserJoinMeetingReqMsg(msg: UserJoinMeetingReqMsg, state: MeetingState2x): MeetingState2x = {
|
||||||
|
userJoinMeeting(outGW, msg.body.authToken, liveMeeting, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,10 @@ package org.bigbluebutton.core.apps.users
|
|||||||
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
|
import org.bigbluebutton.core.domain.{ MeetingExpiryTracker, MeetingState2x }
|
||||||
import org.bigbluebutton.core.models.Users2x
|
import org.bigbluebutton.core.models.Users2x
|
||||||
import org.bigbluebutton.core.running.MeetingActor
|
import org.bigbluebutton.core.running.MeetingActor
|
||||||
|
import org.bigbluebutton.core.util.TimeUtil
|
||||||
import org.bigbluebutton.core2.message.senders.MsgBuilder
|
import org.bigbluebutton.core2.message.senders.MsgBuilder
|
||||||
|
|
||||||
trait UserLeaveReqMsgHdlr {
|
trait UserLeaveReqMsgHdlr {
|
||||||
@ -11,20 +13,26 @@ trait UserLeaveReqMsgHdlr {
|
|||||||
|
|
||||||
val outGW: OutMessageGateway
|
val outGW: OutMessageGateway
|
||||||
|
|
||||||
def handleUserLeaveReqMsg(msg: UserLeaveReqMsg): Unit = {
|
def handleUserLeaveReqMsg(msg: UserLeaveReqMsg, state: MeetingState2x): MeetingState2x = {
|
||||||
for {
|
for {
|
||||||
u <- Users2x.remove(liveMeeting.users2x, msg.body.userId)
|
u <- Users2x.remove(liveMeeting.users2x, msg.body.userId)
|
||||||
} yield {
|
} yield {
|
||||||
log.info("User left meeting. meetingId=" + props.meetingProp.intId + " userId=" + u.intId + " user=" + u)
|
log.info("User left meeting. meetingId=" + props.meetingProp.intId + " userId=" + u.intId + " user=" + u)
|
||||||
|
|
||||||
captionApp2x.handleUserLeavingMsg(msg.body.userId)
|
captionApp2x.handleUserLeavingMsg(msg.body.userId)
|
||||||
liveMeeting.startCheckingIfWeNeedToEndVoiceConf()
|
|
||||||
stopAutoStartedRecording()
|
stopAutoStartedRecording()
|
||||||
|
|
||||||
// send a user left event for the clients to update
|
// send a user left event for the clients to update
|
||||||
val userLeftMeetingEvent = MsgBuilder.buildUserLeftMeetingEvtMsg(liveMeeting.props.meetingProp.intId, u.intId)
|
val userLeftMeetingEvent = MsgBuilder.buildUserLeftMeetingEvtMsg(liveMeeting.props.meetingProp.intId, u.intId)
|
||||||
outGW.send(userLeftMeetingEvent)
|
outGW.send(userLeftMeetingEvent)
|
||||||
log.info("User left meetingId=" + liveMeeting.props.meetingProp.intId + " userId=" + msg.body.userId)
|
log.info("User left meetingId=" + liveMeeting.props.meetingProp.intId + " userId=" + msg.body.userId)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Users2x.numUsers(liveMeeting.users2x) == 0) {
|
||||||
|
MeetingExpiryTracker.setLastUserLeftOn(state, TimeUtil.timeNowInSeconds())
|
||||||
|
} else {
|
||||||
|
state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,12 +3,13 @@ package org.bigbluebutton.core.apps.users
|
|||||||
import akka.actor.ActorContext
|
import akka.actor.ActorContext
|
||||||
import akka.event.Logging
|
import akka.event.Logging
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
|
import org.bigbluebutton.core.bus.IncomingEventBus
|
||||||
import org.bigbluebutton.core.running.LiveMeeting
|
import org.bigbluebutton.core.running.LiveMeeting
|
||||||
import org.bigbluebutton.core2.message.handlers.users.ValidateAuthTokenReqMsgHdlr
|
|
||||||
|
|
||||||
class UsersApp(
|
class UsersApp(
|
||||||
val liveMeeting: LiveMeeting,
|
val liveMeeting: LiveMeeting,
|
||||||
val outGW: OutMessageGateway
|
val outGW: OutMessageGateway,
|
||||||
|
val eventBus: IncomingEventBus
|
||||||
)(implicit val context: ActorContext)
|
)(implicit val context: ActorContext)
|
||||||
|
|
||||||
extends ValidateAuthTokenReqMsgHdlr
|
extends ValidateAuthTokenReqMsgHdlr
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package org.bigbluebutton.core.apps.users
|
package org.bigbluebutton.core.apps.users
|
||||||
|
|
||||||
import org.bigbluebutton.core.running.MeetingActor
|
import org.bigbluebutton.core.running.MeetingActor
|
||||||
import org.bigbluebutton.core2.message.handlers.users.{ ChangeUserEmojiCmdMsgHdlr, ValidateAuthTokenReqMsgHdlr }
|
|
||||||
|
|
||||||
trait UsersApp2x
|
trait UsersApp2x
|
||||||
extends UserLeaveReqMsgHdlr
|
extends UserLeaveReqMsgHdlr
|
||||||
|
@ -0,0 +1,135 @@
|
|||||||
|
package org.bigbluebutton.core.apps.users
|
||||||
|
|
||||||
|
import org.bigbluebutton.common2.msgs._
|
||||||
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
|
import org.bigbluebutton.core.bus.IncomingEventBus
|
||||||
|
import org.bigbluebutton.core.domain.MeetingState2x
|
||||||
|
import org.bigbluebutton.core.models._
|
||||||
|
import org.bigbluebutton.core.running.{ HandlerHelpers, LiveMeeting }
|
||||||
|
import org.bigbluebutton.core2.message.senders.{ MsgBuilder, Sender }
|
||||||
|
|
||||||
|
trait ValidateAuthTokenReqMsgHdlr extends HandlerHelpers {
|
||||||
|
this: UsersApp =>
|
||||||
|
|
||||||
|
val liveMeeting: LiveMeeting
|
||||||
|
val outGW: OutMessageGateway
|
||||||
|
val eventBus: IncomingEventBus
|
||||||
|
|
||||||
|
def handleValidateAuthTokenReqMsg(msg: ValidateAuthTokenReqMsg, state: MeetingState2x): MeetingState2x = {
|
||||||
|
log.debug("RECEIVED ValidateAuthTokenReqMsg msg {}", msg)
|
||||||
|
|
||||||
|
val regUser = RegisteredUsers.getRegisteredUserWithToken(msg.body.authToken, msg.body.userId, liveMeeting.registeredUsers)
|
||||||
|
|
||||||
|
regUser match {
|
||||||
|
case Some(u) =>
|
||||||
|
if (noNeedForApproval(u)) {
|
||||||
|
userValidatedAndNoNeedToWaitForApproval(u, state)
|
||||||
|
} else {
|
||||||
|
goThroughGuestPolicy(liveMeeting.guestsWaiting, u, state)
|
||||||
|
}
|
||||||
|
case None =>
|
||||||
|
validateTokenFailed(outGW, meetingId = liveMeeting.props.meetingProp.intId,
|
||||||
|
userId = msg.body.userId, authToken = msg.body.authToken, valid = false, waitForApproval = false, state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def noNeedForApproval(user: RegisteredUser): Boolean = {
|
||||||
|
!user.guest || (user.guest && !user.waitingForAcceptance)
|
||||||
|
}
|
||||||
|
|
||||||
|
def goThroughGuestPolicy(guestsWaiting: GuestsWaiting, user: RegisteredUser, state: MeetingState2x): MeetingState2x = {
|
||||||
|
if (doesNotHaveToWaitForApproval(guestsWaiting, user)) {
|
||||||
|
userValidatedAndNoNeedToWaitForApproval(user, state)
|
||||||
|
} else {
|
||||||
|
userValidatedButNeedToWaitForApproval(user, state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def doesNotHaveToWaitForApproval(guestsWaiting: GuestsWaiting, user: RegisteredUser): Boolean = {
|
||||||
|
val guestPolicyType = GuestsWaiting.getGuestPolicy(guestsWaiting).policy
|
||||||
|
(guestPolicyType == GuestPolicyType.ALWAYS_ACCEPT) ||
|
||||||
|
(guestPolicyType == GuestPolicyType.ASK_MODERATOR && user.guest && !user.waitingForAcceptance)
|
||||||
|
}
|
||||||
|
|
||||||
|
def validateTokenFailed(outGW: OutMessageGateway, meetingId: String, userId: String, authToken: String,
|
||||||
|
valid: Boolean, waitForApproval: Boolean, state: MeetingState2x): MeetingState2x = {
|
||||||
|
val event = MsgBuilder.buildValidateAuthTokenRespMsg(meetingId, userId, authToken, valid, waitForApproval)
|
||||||
|
Sender.send(outGW, event)
|
||||||
|
|
||||||
|
// TODO: Should disconnect user here.
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
|
def sendValidateAuthTokenRespMsg(meetingId: String, userId: String, authToken: String,
|
||||||
|
valid: Boolean, waitForApproval: Boolean): Unit = {
|
||||||
|
val event = MsgBuilder.buildValidateAuthTokenRespMsg(meetingId, userId, authToken, valid, waitForApproval)
|
||||||
|
Sender.send(outGW, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
def userValidatedButNeedToWaitForApproval(user: RegisteredUser, state: MeetingState2x): MeetingState2x = {
|
||||||
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
|
sendValidateAuthTokenRespMsg(meetingId, user.id, user.authToken, valid = true, waitForApproval = false)
|
||||||
|
|
||||||
|
val guest = GuestWaiting(user.id, user.name, user.role)
|
||||||
|
addGuestToWaitingForApproval(guest, liveMeeting.guestsWaiting)
|
||||||
|
notifyModeratorsOfGuestWaiting(Vector(guest), liveMeeting.users2x, meetingId)
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
|
def addGuestToWaitingForApproval(guest: GuestWaiting, guestsWaitingList: GuestsWaiting): Unit = {
|
||||||
|
GuestsWaiting.add(guestsWaitingList, guest)
|
||||||
|
}
|
||||||
|
|
||||||
|
def userValidatedAndNoNeedToWaitForApproval(user: RegisteredUser, state: MeetingState2x): MeetingState2x = {
|
||||||
|
|
||||||
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
|
sendValidateAuthTokenRespMsg(
|
||||||
|
meetingId,
|
||||||
|
userId = user.id, authToken = user.authToken, valid = true, waitForApproval = false
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: REMOVE Temp only so we can implement user handling in client. (ralam june 21, 2017)
|
||||||
|
|
||||||
|
sendAllUsersInMeeting(user.id)
|
||||||
|
sendAllVoiceUsersInMeeting(user.id, liveMeeting.voiceUsers, meetingId)
|
||||||
|
sendAllWebcamStreams(outGW, user.id, liveMeeting.webcams, meetingId)
|
||||||
|
val newState = userJoinMeeting(outGW, user.authToken, liveMeeting, state)
|
||||||
|
if (!Users2x.hasPresenter(liveMeeting.users2x)) {
|
||||||
|
automaticallyAssignPresenter(outGW, liveMeeting)
|
||||||
|
}
|
||||||
|
newState
|
||||||
|
}
|
||||||
|
|
||||||
|
def sendAllUsersInMeeting(requesterId: String): Unit = {
|
||||||
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
|
val users = Users2x.findAll(liveMeeting.users2x)
|
||||||
|
val webUsers = users.map { u =>
|
||||||
|
WebUser(intId = u.intId, extId = u.extId, name = u.name, role = u.role,
|
||||||
|
guest = u.guest, authed = u.authed, waitingForAcceptance = u.waitingForAcceptance, emoji = u.emoji,
|
||||||
|
locked = u.locked, presenter = u.presenter, avatar = u.avatar)
|
||||||
|
}
|
||||||
|
|
||||||
|
val event = MsgBuilder.buildGetUsersMeetingRespMsg(meetingId, requesterId, webUsers)
|
||||||
|
Sender.send(outGW, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
def sendAllVoiceUsersInMeeting(requesterId: String, voiceUsers: VoiceUsers, meetingId: String): Unit = {
|
||||||
|
val vu = VoiceUsers.findAll(voiceUsers).map { u =>
|
||||||
|
VoiceConfUser(intId = u.intId, voiceUserId = u.voiceUserId, callingWith = u.callingWith, callerName = u.callerName,
|
||||||
|
callerNum = u.callerNum, muted = u.muted, talking = u.talking, listenOnly = u.listenOnly)
|
||||||
|
}
|
||||||
|
|
||||||
|
val event = MsgBuilder.buildGetVoiceUsersMeetingRespMsg(meetingId, requesterId, vu)
|
||||||
|
Sender.send(outGW, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
def notifyModeratorsOfGuestWaiting(guests: Vector[GuestWaiting], users: Users2x, meetingId: String): Unit = {
|
||||||
|
val mods = Users2x.findAll(users).filter(p => p.role == Roles.MODERATOR_ROLE)
|
||||||
|
mods foreach { m =>
|
||||||
|
val event = MsgBuilder.buildGuestsWaitingForApprovalEvtMsg(meetingId, m.intId, guests)
|
||||||
|
Sender.send(outGW, event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,122 @@
|
|||||||
package org.bigbluebutton.core.domain
|
package org.bigbluebutton.core.domain
|
||||||
|
|
||||||
|
import com.softwaremill.quicklens._
|
||||||
|
import org.bigbluebutton.core.util.TimeUtil
|
||||||
|
|
||||||
case class MeetingInactivityTracker(
|
case class MeetingInactivityTracker(
|
||||||
maxInactivityTimeoutMinutes: Int,
|
val maxInactivityTimeoutMinutes: Int,
|
||||||
warningMinutesBeforeMax: Int,
|
val warningMinutesBeforeMax: Int,
|
||||||
lastActivityTimeInMinutes: Long,
|
lastActivityTimestamp: Long,
|
||||||
warningSent: Boolean,
|
warningSent: Boolean,
|
||||||
warningSentOnTimeInMinutes: Long
|
warningSentOnTimestamp: Long
|
||||||
)
|
)
|
||||||
|
|
||||||
case class MeetingExpiryTracker(startedOnInMinutes: Long, meetingJoined: Boolean, lastUserLeftOn: Long)
|
object MeetingInactivityTracker {
|
||||||
|
|
||||||
|
def warningHasBeenSent(state: MeetingState2x): Boolean = {
|
||||||
|
state.inactivityTracker.warningSent
|
||||||
|
}
|
||||||
|
|
||||||
|
def setWarningSentAndTimestamp(state: MeetingState2x, nowInSeconds: Long): MeetingState2x = {
|
||||||
|
val tracker = state.inactivityTracker.modify(_.warningSent).setTo(true)
|
||||||
|
.modify(_.warningSentOnTimestamp).setTo(nowInSeconds)
|
||||||
|
state.modify(_.inactivityTracker).setTo(tracker)
|
||||||
|
}
|
||||||
|
|
||||||
|
def resetWarningSentAndTimestamp(state: MeetingState2x): MeetingState2x = {
|
||||||
|
val tracker = state.inactivityTracker.modify(_.warningSent).setTo(false)
|
||||||
|
.modify(_.warningSentOnTimestamp).setTo(0L)
|
||||||
|
state.modify(_.inactivityTracker).setTo(tracker)
|
||||||
|
}
|
||||||
|
|
||||||
|
def updateLastActivityTimestamp(state: MeetingState2x, nowInSeconds: Long): MeetingState2x = {
|
||||||
|
val tracker = state.inactivityTracker.modify(_.lastActivityTimestamp).setTo(nowInSeconds)
|
||||||
|
state.modify(_.inactivityTracker).setTo(tracker)
|
||||||
|
}
|
||||||
|
|
||||||
|
def hasRecentActivity(state: MeetingState2x, nowInSeconds: Long): Boolean = {
|
||||||
|
nowInSeconds - state.inactivityTracker.lastActivityTimestamp <
|
||||||
|
TimeUtil.minutesToSeconds(state.inactivityTracker.maxInactivityTimeoutMinutes) -
|
||||||
|
TimeUtil.minutesToSeconds(state.inactivityTracker.warningMinutesBeforeMax)
|
||||||
|
}
|
||||||
|
|
||||||
|
def isMeetingInactive(state: MeetingState2x, nowInSeconds: Long): Boolean = {
|
||||||
|
state.inactivityTracker.warningSent &&
|
||||||
|
(nowInSeconds - state.inactivityTracker.lastActivityTimestamp) >
|
||||||
|
TimeUtil.minutesToSeconds(state.inactivityTracker.maxInactivityTimeoutMinutes)
|
||||||
|
}
|
||||||
|
|
||||||
|
def timeLeftInSeconds(state: MeetingState2x, nowInSeconds: Long): Long = {
|
||||||
|
state.inactivityTracker.lastActivityTimestamp +
|
||||||
|
TimeUtil.minutesToSeconds(state.inactivityTracker.maxInactivityTimeoutMinutes) - nowInSeconds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case class MeetingExpiryTracker(
|
||||||
|
startedOn: Long,
|
||||||
|
userHasJoined: Boolean,
|
||||||
|
lastUserLeftOn: Option[Long],
|
||||||
|
durationInMinutes: Int,
|
||||||
|
meetingExpireIfNoUserJoinedInMinutes: Int,
|
||||||
|
meetingExpireWhenLastUserLeftInMinutes: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
object MeetingExpiryTracker {
|
||||||
|
def setMeetingStartedOn(state: MeetingState2x, timestampInSeconds: Long): MeetingState2x = {
|
||||||
|
val tracker = state.expiryTracker.modify(_.startedOn).setTo(timestampInSeconds)
|
||||||
|
state.modify(_.expiryTracker).setTo(tracker)
|
||||||
|
}
|
||||||
|
|
||||||
|
def setUserHasJoined(state: MeetingState2x): MeetingState2x = {
|
||||||
|
val tracker = state.expiryTracker.modify(_.userHasJoined).setTo(true)
|
||||||
|
.modify(_.lastUserLeftOn).setTo(None)
|
||||||
|
state.modify(_.expiryTracker).setTo(tracker)
|
||||||
|
}
|
||||||
|
|
||||||
|
def hasMeetingExpiredAfterLastUserLeft(state: MeetingState2x, timestampInSeconds: Long): Boolean = {
|
||||||
|
val expire = for {
|
||||||
|
lastUserLeftOn <- state.expiryTracker.lastUserLeftOn
|
||||||
|
} yield {
|
||||||
|
timestampInSeconds - lastUserLeftOn >
|
||||||
|
TimeUtil.minutesToSeconds(state.expiryTracker.meetingExpireWhenLastUserLeftInMinutes)
|
||||||
|
}
|
||||||
|
|
||||||
|
expire.getOrElse(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
def setLastUserLeftOn(state: MeetingState2x, timestampInSeconds: Long): MeetingState2x = {
|
||||||
|
val tracker = state.expiryTracker.modify(_.lastUserLeftOn).setTo(Some(timestampInSeconds))
|
||||||
|
state.modify(_.expiryTracker).setTo(tracker)
|
||||||
|
}
|
||||||
|
|
||||||
|
def hasMeetingExpired(state: MeetingState2x, timestampInSeconds: Long): (Boolean, Option[String]) = {
|
||||||
|
if (MeetingExpiryTracker.hasMeetingExpiredNeverBeenJoined(state, timestampInSeconds)) {
|
||||||
|
(true, Some(MeetingEndReason.ENDED_WHEN_NOT_JOINED))
|
||||||
|
} else if (MeetingExpiryTracker.meetingOverDuration(state, timestampInSeconds)) {
|
||||||
|
(true, Some(MeetingEndReason.ENDED_AFTER_EXCEEDING_DURATION))
|
||||||
|
} else if (MeetingExpiryTracker.hasMeetingExpiredAfterLastUserLeft(state, timestampInSeconds)) {
|
||||||
|
(true, Some(MeetingEndReason.ENDED_WHEN_LAST_USER_LEFT))
|
||||||
|
} else {
|
||||||
|
(false, None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def hasMeetingExpiredNeverBeenJoined(state: MeetingState2x, nowInSeconds: Long): Boolean = {
|
||||||
|
!state.expiryTracker.userHasJoined &&
|
||||||
|
(nowInSeconds - state.expiryTracker.startedOn >
|
||||||
|
TimeUtil.minutesToSeconds(state.expiryTracker.meetingExpireIfNoUserJoinedInMinutes))
|
||||||
|
}
|
||||||
|
|
||||||
|
def meetingOverDuration(state: MeetingState2x, nowInSeconds: Long): Boolean = {
|
||||||
|
if (state.expiryTracker.durationInMinutes == 0) {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
nowInSeconds > state.expiryTracker.startedOn + TimeUtil.minutesToSeconds(state.expiryTracker.durationInMinutes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def endMeetingTime(state: MeetingState2x): Int = {
|
||||||
|
(state.expiryTracker.startedOn + TimeUtil.minutesToSeconds(state.expiryTracker.durationInMinutes)).toInt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package org.bigbluebutton.core.domain
|
||||||
|
|
||||||
|
object MeetingState2x {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
case class MeetingState2x(
|
||||||
|
inactivityTracker: MeetingInactivityTracker,
|
||||||
|
expiryTracker: MeetingExpiryTracker
|
||||||
|
)
|
||||||
|
|
||||||
|
object MeetingEndReason {
|
||||||
|
val ENDED_FROM_API = "ENDED_FROM_API"
|
||||||
|
val ENDED_DUE_TO_INACTIVITY = "ENDED_DUE_TO_ACTIVITY"
|
||||||
|
val ENDED_WHEN_NOT_JOINED = "ENDED_WHEN_NOT_JOINED"
|
||||||
|
val ENDED_WHEN_LAST_USER_LEFT = "ENDED_WHEN_LAST_USER_LEFT"
|
||||||
|
val ENDED_AFTER_USER_LOGGED_OUT = "ENDED_AFTER_USER_LOGGED_OUT"
|
||||||
|
val ENDED_AFTER_EXCEEDING_DURATION = "ENDED_AFTER_USER_LOGGED_OUT"
|
||||||
|
}
|
@ -6,10 +6,8 @@ import com.softwaremill.quicklens._
|
|||||||
object RegisteredUsers {
|
object RegisteredUsers {
|
||||||
def create(userId: String, extId: String, name: String, roles: String,
|
def create(userId: String, extId: String, name: String, roles: String,
|
||||||
token: String, avatar: String, guest: Boolean, authenticated: Boolean,
|
token: String, avatar: String, guest: Boolean, authenticated: Boolean,
|
||||||
waitingForAcceptance: Boolean, users: RegisteredUsers): RegisteredUser = {
|
waitingForAcceptance: Boolean): RegisteredUser = {
|
||||||
val ru = new RegisteredUser(userId, extId, name, roles, token, avatar, guest, authenticated, waitingForAcceptance)
|
new RegisteredUser(userId, extId, name, roles, token, avatar, guest, authenticated, waitingForAcceptance)
|
||||||
users.save(ru)
|
|
||||||
ru
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def findWithToken(token: String, users: RegisteredUsers): Option[RegisteredUser] = {
|
def findWithToken(token: String, users: RegisteredUsers): Option[RegisteredUser] = {
|
||||||
@ -43,6 +41,10 @@ object RegisteredUsers {
|
|||||||
} yield users.save(regUser)
|
} yield users.save(regUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def add(users: RegisteredUsers, user: RegisteredUser): Vector[RegisteredUser] = {
|
||||||
|
users.save(user)
|
||||||
|
}
|
||||||
|
|
||||||
def remove(id: String, users: RegisteredUsers): Option[RegisteredUser] = {
|
def remove(id: String, users: RegisteredUsers): Option[RegisteredUser] = {
|
||||||
users.delete(id)
|
users.delete(id)
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,16 @@ class ReceivedJsonMsgHandlerActor(
|
|||||||
case DestroyMeetingSysCmdMsg.NAME =>
|
case DestroyMeetingSysCmdMsg.NAME =>
|
||||||
route[DestroyMeetingSysCmdMsg](meetingManagerChannel, envelope, jsonNode)
|
route[DestroyMeetingSysCmdMsg](meetingManagerChannel, envelope, jsonNode)
|
||||||
|
|
||||||
|
// Guests
|
||||||
|
case GetGuestsWaitingApprovalReqMsg.NAME =>
|
||||||
|
routeGenericMsg[GetGuestsWaitingApprovalReqMsg](envelope, jsonNode)
|
||||||
|
case GuestsWaitingApprovedMsg.NAME =>
|
||||||
|
routeGenericMsg[GuestsWaitingApprovedMsg](envelope, jsonNode)
|
||||||
|
case SetGuestPolicyCmdMsg.NAME =>
|
||||||
|
routeGenericMsg[SetGuestPolicyCmdMsg](envelope, jsonNode)
|
||||||
|
case GetGuestPolicyReqMsg.NAME =>
|
||||||
|
routeGenericMsg[GetGuestPolicyReqMsg](envelope, jsonNode)
|
||||||
|
|
||||||
// Users
|
// Users
|
||||||
case GetUsersMeetingReqMsg.NAME =>
|
case GetUsersMeetingReqMsg.NAME =>
|
||||||
routeGenericMsg[GetUsersMeetingReqMsg](envelope, jsonNode)
|
routeGenericMsg[GetUsersMeetingReqMsg](envelope, jsonNode)
|
||||||
|
@ -1,168 +1,192 @@
|
|||||||
package org.bigbluebutton.core.running
|
package org.bigbluebutton.core.running
|
||||||
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.SystemConfiguration
|
||||||
import org.bigbluebutton.core.api.RecordingStatusChanged
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.{ MessageRecorder, OutMessageGateway }
|
import org.bigbluebutton.core.api.{ BreakoutRoomEndedInternalMsg, DestroyMeetingInternalMsg, RecordingStatusChanged }
|
||||||
import org.bigbluebutton.core.models._
|
import org.bigbluebutton.core.bus.{ BigBlueButtonEvent, IncomingEventBus }
|
||||||
import org.bigbluebutton.core2.MeetingStatus2x
|
import org.bigbluebutton.core.domain.{ MeetingExpiryTracker, MeetingState2x }
|
||||||
import org.bigbluebutton.core2.message.senders.{ MsgBuilder, Sender, UserJoinedMeetingEvtMsgBuilder }
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
|
import org.bigbluebutton.core.models._
|
||||||
trait HandlerHelpers {
|
import org.bigbluebutton.core2.MeetingStatus2x
|
||||||
|
import org.bigbluebutton.core2.message.senders.{ MsgBuilder, Sender, UserJoinedMeetingEvtMsgBuilder }
|
||||||
def validateTokenFailed(outGW: OutMessageGateway, meetingId: String, userId: String, authToken: String,
|
|
||||||
valid: Boolean, waitForApproval: Boolean): Unit = {
|
trait HandlerHelpers extends SystemConfiguration {
|
||||||
val event = MsgBuilder.buildValidateAuthTokenRespMsg(
|
|
||||||
meetingId,
|
def sendAllWebcamStreams(outGW: OutMessageGateway, requesterId: String, webcams: Webcams, meetingId: String): Unit = {
|
||||||
userId, authToken, valid, waitForApproval
|
val streams = org.bigbluebutton.core.models.Webcams.findAll(webcams)
|
||||||
)
|
val webcamStreams = streams.map { u =>
|
||||||
Sender.send(outGW, event)
|
val msVO = MediaStreamVO(id = u.stream.id, url = u.stream.url, userId = u.stream.userId,
|
||||||
|
attributes = u.stream.attributes, viewers = u.stream.viewers)
|
||||||
// TODO: Should disconnect user here.
|
|
||||||
}
|
WebcamStreamVO(streamId = msVO.id, stream = msVO)
|
||||||
|
}
|
||||||
def sendValidateAuthTokenRespMsg(outGW: OutMessageGateway, meetingId: String, userId: String, authToken: String,
|
|
||||||
valid: Boolean, waitForApproval: Boolean): Unit = {
|
val event = MsgBuilder.buildGetWebcamStreamsMeetingRespMsg(meetingId, requesterId, webcamStreams)
|
||||||
val event = MsgBuilder.buildValidateAuthTokenRespMsg(
|
Sender.send(outGW, event)
|
||||||
meetingId,
|
}
|
||||||
userId, authToken, valid, waitForApproval
|
|
||||||
)
|
def userJoinMeeting(outGW: OutMessageGateway, authToken: String,
|
||||||
Sender.send(outGW, event)
|
liveMeeting: LiveMeeting, state: MeetingState2x): MeetingState2x = {
|
||||||
}
|
val nu = for {
|
||||||
|
regUser <- RegisteredUsers.findWithToken(authToken, liveMeeting.registeredUsers)
|
||||||
def userValidatedButNeedToWaitForApproval(outGW: OutMessageGateway, liveMeeting: LiveMeeting,
|
} yield {
|
||||||
user: RegisteredUser): Unit = {
|
UserState(
|
||||||
val meetingId = liveMeeting.props.meetingProp.intId
|
intId = regUser.id,
|
||||||
sendValidateAuthTokenRespMsg(outGW, meetingId, user.id, user.authToken, valid = true, waitForApproval = false)
|
extId = regUser.externId,
|
||||||
|
name = regUser.name,
|
||||||
val guest = GuestWaiting(user.id, user.name, user.role)
|
role = regUser.role,
|
||||||
addGuestToWaitingForApproval(guest, liveMeeting.guestsWaiting)
|
guest = regUser.guest,
|
||||||
notifyModeratorsOfGuestWaiting(outGW, Vector(guest), liveMeeting.users2x, meetingId)
|
authed = regUser.authed,
|
||||||
}
|
waitingForAcceptance = regUser.waitingForAcceptance,
|
||||||
|
emoji = "none",
|
||||||
def addGuestToWaitingForApproval(guest: GuestWaiting, guestsWaitingList: GuestsWaiting): Unit = {
|
presenter = false,
|
||||||
GuestsWaiting.add(guestsWaitingList, guest)
|
locked = false,
|
||||||
}
|
avatar = regUser.avatarURL
|
||||||
|
)
|
||||||
def userValidatedAndNoNeedToWaitForApproval(
|
}
|
||||||
outGW: OutMessageGateway,
|
|
||||||
liveMeeting: LiveMeeting,
|
nu match {
|
||||||
user: RegisteredUser
|
case Some(newUser) =>
|
||||||
): Unit = {
|
Users2x.add(liveMeeting.users2x, newUser)
|
||||||
|
|
||||||
println("**************** userValidatedAndNoNeedToWaitForApproval")
|
val event = UserJoinedMeetingEvtMsgBuilder.build(liveMeeting.props.meetingProp.intId, newUser)
|
||||||
|
Sender.send(outGW, event)
|
||||||
val meetingId = liveMeeting.props.meetingProp.intId
|
startRecordingIfAutoStart2x(liveMeeting)
|
||||||
sendValidateAuthTokenRespMsg(outGW, meetingId,
|
|
||||||
userId = user.id, authToken = user.authToken, valid = true, waitForApproval = false)
|
if (!state.expiryTracker.userHasJoined) {
|
||||||
|
MeetingExpiryTracker.setUserHasJoined(state)
|
||||||
// TODO: REMOVE Temp only so we can implement user handling in client. (ralam june 21, 2017)
|
} else {
|
||||||
|
state
|
||||||
sendAllUsersInMeeting(outGW, user.id, liveMeeting)
|
}
|
||||||
sendAllVoiceUsersInMeeting(outGW, user.id, liveMeeting.voiceUsers, meetingId)
|
|
||||||
sendAllWebcamStreams(outGW, user.id, liveMeeting.webcams, meetingId)
|
case None =>
|
||||||
userJoinMeeting(outGW, user.authToken, liveMeeting)
|
state
|
||||||
if (!Users2x.hasPresenter(liveMeeting.users2x)) {
|
}
|
||||||
automaticallyAssignPresenter(outGW, liveMeeting)
|
}
|
||||||
}
|
|
||||||
}
|
def startRecordingIfAutoStart2x(liveMeeting: LiveMeeting): Unit = {
|
||||||
|
if (liveMeeting.props.recordProp.record && !MeetingStatus2x.isRecording(liveMeeting.status) &&
|
||||||
def notifyModeratorsOfGuestWaiting(outGW: OutMessageGateway, guests: Vector[GuestWaiting], users: Users2x, meetingId: String): Unit = {
|
liveMeeting.props.recordProp.autoStartRecording && Users2x.numUsers(liveMeeting.users2x) == 1) {
|
||||||
val mods = Users2x.findAll(users).filter(p => p.role == Roles.MODERATOR_ROLE)
|
|
||||||
mods foreach { m =>
|
MeetingStatus2x.recordingStarted(liveMeeting.status)
|
||||||
val event = MsgBuilder.buildGuestsWaitingForApprovalEvtMsg(meetingId, m.intId, guests)
|
// outGW.send(new RecordingStatusChanged(props.meetingProp.intId, props.recordProp.record,
|
||||||
Sender.send(outGW, event)
|
// "system", MeetingStatus2x.isRecording(liveMeeting.status)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendAllUsersInMeeting(outGW: OutMessageGateway, requesterId: String, liveMeeting: LiveMeeting): Unit = {
|
def automaticallyAssignPresenter(outGW: OutMessageGateway, liveMeeting: LiveMeeting): Unit = {
|
||||||
val meetingId = liveMeeting.props.meetingProp.intId
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
val users = Users2x.findAll(liveMeeting.users2x)
|
for {
|
||||||
val webUsers = users.map { u =>
|
moderator <- Users2x.findModerator(liveMeeting.users2x)
|
||||||
WebUser(intId = u.intId, extId = u.extId, name = u.name, role = u.role,
|
newPresenter <- Users2x.makePresenter(liveMeeting.users2x, moderator.intId)
|
||||||
guest = u.guest, authed = u.authed, waitingForAcceptance = u.waitingForAcceptance, emoji = u.emoji,
|
} yield {
|
||||||
locked = u.locked, presenter = u.presenter, avatar = u.avatar)
|
sendPresenterAssigned(outGW, meetingId, newPresenter.intId, newPresenter.name, newPresenter.name)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
val event = MsgBuilder.buildGetUsersMeetingRespMsg(meetingId, requesterId, webUsers)
|
|
||||||
Sender.send(outGW, event)
|
def sendPresenterAssigned(outGW: OutMessageGateway, meetingId: String, intId: String, name: String, assignedBy: String): Unit = {
|
||||||
}
|
def event = MsgBuilder.buildPresenterAssignedEvtMsg(meetingId, intId, name, assignedBy)
|
||||||
|
outGW.send(event)
|
||||||
def sendAllWebcamStreams(outGW: OutMessageGateway, requesterId: String, webcams: Webcams, meetingId: String): Unit = {
|
}
|
||||||
val streams = org.bigbluebutton.core.models.Webcams.findAll(webcams)
|
|
||||||
val webcamStreams = streams.map { u =>
|
def endMeeting(outGW: OutMessageGateway, liveMeeting: LiveMeeting, reason: String): Unit = {
|
||||||
val msVO = MediaStreamVO(id = u.stream.id, url = u.stream.url, userId = u.stream.userId,
|
def buildMeetingEndingEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
|
||||||
attributes = u.stream.attributes, viewers = u.stream.viewers)
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
||||||
|
val envelope = BbbCoreEnvelope(MeetingEndingEvtMsg.NAME, routing)
|
||||||
WebcamStreamVO(streamId = msVO.id, stream = msVO)
|
val body = MeetingEndingEvtMsgBody(meetingId, reason)
|
||||||
}
|
val header = BbbClientMsgHeader(MeetingEndingEvtMsg.NAME, meetingId, "not-used")
|
||||||
|
val event = MeetingEndingEvtMsg(header, body)
|
||||||
val event = MsgBuilder.buildGetWebcamStreamsMeetingRespMsg(meetingId, requesterId, webcamStreams)
|
|
||||||
Sender.send(outGW, event)
|
BbbCommonEnvCoreMsg(envelope, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendAllVoiceUsersInMeeting(outGW: OutMessageGateway, requesterId: String,
|
val endingEvent = buildMeetingEndingEvtMsg(liveMeeting.props.meetingProp.intId)
|
||||||
voiceUsers: VoiceUsers,
|
|
||||||
meetingId: String): Unit = {
|
// Broadcast users the meeting will end
|
||||||
|
outGW.send(endingEvent)
|
||||||
val vu = VoiceUsers.findAll(voiceUsers).map { u =>
|
|
||||||
VoiceConfUser(intId = u.intId, voiceUserId = u.voiceUserId, callingWith = u.callingWith, callerName = u.callerName,
|
MeetingStatus2x.meetingHasEnded(liveMeeting.status)
|
||||||
callerNum = u.callerNum, muted = u.muted, talking = u.talking, listenOnly = u.listenOnly)
|
|
||||||
}
|
def buildMeetingEndedEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
|
||||||
|
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
|
||||||
val event = MsgBuilder.buildGetVoiceUsersMeetingRespMsg(meetingId, requesterId, vu)
|
val envelope = BbbCoreEnvelope(MeetingEndedEvtMsg.NAME, routing)
|
||||||
Sender.send(outGW, event)
|
val body = MeetingEndedEvtMsgBody(meetingId)
|
||||||
}
|
val header = BbbCoreBaseHeader(MeetingEndedEvtMsg.NAME)
|
||||||
|
val event = MeetingEndedEvtMsg(header, body)
|
||||||
def userJoinMeeting(outGW: OutMessageGateway, authToken: String, liveMeeting: LiveMeeting): Unit = {
|
|
||||||
for {
|
BbbCommonEnvCoreMsg(envelope, event)
|
||||||
regUser <- RegisteredUsers.findWithToken(authToken, liveMeeting.registeredUsers)
|
}
|
||||||
} yield {
|
|
||||||
val userState = UserState(
|
val endedEvnt = buildMeetingEndedEvtMsg(liveMeeting.props.meetingProp.intId)
|
||||||
intId = regUser.id,
|
outGW.send(endedEvnt)
|
||||||
extId = regUser.externId,
|
}
|
||||||
name = regUser.name,
|
|
||||||
role = regUser.role,
|
def destroyMeeting(eventBus: IncomingEventBus, meetingId: String): Unit = {
|
||||||
guest = regUser.guest,
|
eventBus.publish(BigBlueButtonEvent(meetingManagerChannel, new DestroyMeetingInternalMsg(meetingId)))
|
||||||
authed = regUser.authed,
|
}
|
||||||
waitingForAcceptance = regUser.waitingForAcceptance,
|
|
||||||
emoji = "none",
|
def notifyParentThatBreakoutEnded(eventBus: IncomingEventBus, liveMeeting: LiveMeeting): Unit = {
|
||||||
presenter = false,
|
if (liveMeeting.props.meetingProp.isBreakout) {
|
||||||
locked = false,
|
eventBus.publish(BigBlueButtonEvent(
|
||||||
avatar = regUser.avatarURL
|
liveMeeting.props.breakoutProps.parentId,
|
||||||
)
|
new BreakoutRoomEndedInternalMsg(liveMeeting.props.meetingProp.intId)
|
||||||
|
))
|
||||||
Users2x.add(liveMeeting.users2x, userState)
|
}
|
||||||
|
}
|
||||||
val event = UserJoinedMeetingEvtMsgBuilder.build(liveMeeting.props.meetingProp.intId, userState)
|
|
||||||
Sender.send(outGW, event)
|
def ejectAllUsersFromVoiceConf(outGW: OutMessageGateway, liveMeeting: LiveMeeting): Unit = {
|
||||||
|
val event = MsgBuilder.buildEjectAllFromVoiceConfMsg(liveMeeting.props.meetingProp.intId, liveMeeting.props.voiceProp.voiceConf)
|
||||||
MessageRecorder.record(outGW, liveMeeting.props.recordProp.record, event.core)
|
outGW.send(event)
|
||||||
startRecordingIfAutoStart2x(liveMeeting)
|
}
|
||||||
}
|
|
||||||
}
|
def sendEndMeetingDueToExpiry(reason: String, eventBus: IncomingEventBus, outGW: OutMessageGateway, liveMeeting: LiveMeeting): Unit = {
|
||||||
|
endMeeting(outGW, liveMeeting, reason)
|
||||||
def startRecordingIfAutoStart2x(liveMeeting: LiveMeeting): Unit = {
|
notifyParentThatBreakoutEnded(eventBus, liveMeeting)
|
||||||
if (liveMeeting.props.recordProp.record && !MeetingStatus2x.isRecording(liveMeeting.status) &&
|
ejectAllUsersFromVoiceConf(outGW, liveMeeting)
|
||||||
liveMeeting.props.recordProp.autoStartRecording && Users2x.numUsers(liveMeeting.users2x) == 1) {
|
destroyMeeting(eventBus, liveMeeting.props.meetingProp.intId)
|
||||||
|
}
|
||||||
MeetingStatus2x.recordingStarted(liveMeeting.status)
|
|
||||||
// outGW.send(new RecordingStatusChanged(props.meetingProp.intId, props.recordProp.record,
|
def sendEndMeetingDueToExpiry2(reason: String, eventBus: IncomingEventBus, outGW: OutMessageGateway, liveMeeting: LiveMeeting): Unit = {
|
||||||
// "system", MeetingStatus2x.isRecording(liveMeeting.status)))
|
val meetingId = liveMeeting.props.meetingProp.intId
|
||||||
}
|
|
||||||
}
|
val endMeetingEvt = buildMeetingEndingEvtMsg(reason, meetingId)
|
||||||
|
outGW.send(endMeetingEvt)
|
||||||
def automaticallyAssignPresenter(outGW: OutMessageGateway, liveMeeting: LiveMeeting): Unit = {
|
|
||||||
val meetingId = liveMeeting.props.meetingProp.intId
|
val endedEvt = buildMeetingEndedEvtMsg(meetingId)
|
||||||
for {
|
outGW.send(endedEvt)
|
||||||
moderator <- Users2x.findModerator(liveMeeting.users2x)
|
|
||||||
newPresenter <- Users2x.makePresenter(liveMeeting.users2x, moderator.intId)
|
if (liveMeeting.props.meetingProp.isBreakout) {
|
||||||
} yield {
|
eventBus.publish(BigBlueButtonEvent(
|
||||||
sendPresenterAssigned(outGW, meetingId, newPresenter.intId, newPresenter.name, newPresenter.name)
|
liveMeeting.props.breakoutProps.parentId,
|
||||||
}
|
new BreakoutRoomEndedInternalMsg(meetingId)
|
||||||
}
|
))
|
||||||
|
}
|
||||||
def sendPresenterAssigned(outGW: OutMessageGateway, meetingId: String, intId: String, name: String, assignedBy: String): Unit = {
|
|
||||||
def event = MsgBuilder.buildPresenterAssignedEvtMsg(meetingId, intId, name, assignedBy)
|
val event = MsgBuilder.buildEjectAllFromVoiceConfMsg(meetingId, liveMeeting.props.voiceProp.voiceConf)
|
||||||
outGW.send(event)
|
outGW.send(event)
|
||||||
}
|
|
||||||
}
|
eventBus.publish(BigBlueButtonEvent(meetingManagerChannel, new DestroyMeetingInternalMsg(meetingId)))
|
||||||
|
|
||||||
|
MeetingStatus2x.meetingHasEnded(liveMeeting.status)
|
||||||
|
}
|
||||||
|
|
||||||
|
def buildMeetingEndingEvtMsg(reason: String, meetingId: String): BbbCommonEnvCoreMsg = {
|
||||||
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
||||||
|
val envelope = BbbCoreEnvelope(MeetingEndingEvtMsg.NAME, routing)
|
||||||
|
val body = MeetingEndingEvtMsgBody(meetingId, reason)
|
||||||
|
val header = BbbClientMsgHeader(MeetingEndingEvtMsg.NAME, meetingId, "not-used")
|
||||||
|
val event = MeetingEndingEvtMsg(header, body)
|
||||||
|
|
||||||
|
BbbCommonEnvCoreMsg(envelope, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
def buildMeetingEndedEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
|
||||||
|
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
|
||||||
|
val envelope = BbbCoreEnvelope(MeetingEndedEvtMsg.NAME, routing)
|
||||||
|
val body = MeetingEndedEvtMsgBody(meetingId)
|
||||||
|
val header = BbbCoreBaseHeader(MeetingEndedEvtMsg.NAME)
|
||||||
|
val event = MeetingEndedEvtMsg(header, body)
|
||||||
|
|
||||||
|
BbbCommonEnvCoreMsg(envelope, event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
package org.bigbluebutton.core.running
|
package org.bigbluebutton.core.running
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
import org.bigbluebutton.common2.domain.DefaultProps
|
import org.bigbluebutton.common2.domain.DefaultProps
|
||||||
import org.bigbluebutton.core.api._
|
import org.bigbluebutton.core.api._
|
||||||
import org.bigbluebutton.core.apps._
|
import org.bigbluebutton.core.apps._
|
||||||
import org.bigbluebutton.core.domain.Meeting3x
|
|
||||||
import org.bigbluebutton.core.models._
|
import org.bigbluebutton.core.models._
|
||||||
import org.bigbluebutton.core2.MeetingStatus2x
|
import org.bigbluebutton.core2.MeetingStatus2x
|
||||||
|
|
||||||
@ -29,32 +26,6 @@ class LiveMeeting(
|
|||||||
val guestsWaiting: GuestsWaiting
|
val guestsWaiting: GuestsWaiting
|
||||||
) {
|
) {
|
||||||
|
|
||||||
def hasMeetingEnded(): Boolean = {
|
|
||||||
MeetingStatus2x.hasMeetingEnded(status)
|
|
||||||
}
|
|
||||||
|
|
||||||
def startCheckingIfWeNeedToEndVoiceConf() {
|
|
||||||
if (Users2x.numUsers(users2x) == 0 && !props.meetingProp.isBreakout) {
|
|
||||||
MeetingStatus2x.lastWebUserLeft(status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def sendTimeRemainingNotice() {
|
|
||||||
val now = timeNowInSeconds
|
|
||||||
|
|
||||||
if (props.durationProps.duration > 0 && (((MeetingStatus2x.startedOn(status) + props.durationProps.duration) - now) < 15)) {
|
|
||||||
// log.warning("MEETING WILL END IN 15 MINUTES!!!!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def timeNowInMinutes(): Long = {
|
|
||||||
TimeUnit.NANOSECONDS.toMinutes(System.nanoTime())
|
|
||||||
}
|
|
||||||
|
|
||||||
def timeNowInSeconds(): Long = {
|
|
||||||
TimeUnit.NANOSECONDS.toSeconds(System.nanoTime())
|
|
||||||
}
|
|
||||||
|
|
||||||
def lockLayout(lock: Boolean) {
|
def lockLayout(lock: Boolean) {
|
||||||
MeetingStatus2x.lockLayout(status, lock)
|
MeetingStatus2x.lockLayout(status, lock)
|
||||||
}
|
}
|
||||||
|
@ -1,434 +1,394 @@
|
|||||||
package org.bigbluebutton.core.running
|
package org.bigbluebutton.core.running
|
||||||
|
|
||||||
import java.io.{ PrintWriter, StringWriter }
|
import java.io.{ PrintWriter, StringWriter }
|
||||||
|
|
||||||
import org.bigbluebutton.core.apps.users.UsersApp
|
import org.bigbluebutton.core.apps.users._
|
||||||
import org.bigbluebutton.core.domain.{ MeetingExpiryTracker, MeetingInactivityTracker }
|
import org.bigbluebutton.core.domain.{ MeetingExpiryTracker, MeetingInactivityTracker, MeetingState2x }
|
||||||
import org.bigbluebutton.core.util.TimeUtil
|
import org.bigbluebutton.core.util.TimeUtil
|
||||||
//import java.util.concurrent.TimeUnit
|
//import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
import akka.actor._
|
import akka.actor._
|
||||||
import akka.actor.SupervisorStrategy.Resume
|
import akka.actor.SupervisorStrategy.Resume
|
||||||
import org.bigbluebutton.common2.domain.DefaultProps
|
import org.bigbluebutton.common2.domain.DefaultProps
|
||||||
import org.bigbluebutton.core._
|
import org.bigbluebutton.core._
|
||||||
import org.bigbluebutton.core.api._
|
import org.bigbluebutton.core.api._
|
||||||
import org.bigbluebutton.core.apps._
|
import org.bigbluebutton.core.apps._
|
||||||
import org.bigbluebutton.core.apps.caption.CaptionApp2x
|
import org.bigbluebutton.core.apps.caption.CaptionApp2x
|
||||||
import org.bigbluebutton.core.apps.chat.ChatApp2x
|
import org.bigbluebutton.core.apps.chat.ChatApp2x
|
||||||
import org.bigbluebutton.core.apps.screenshare.ScreenshareApp2x
|
import org.bigbluebutton.core.apps.screenshare.ScreenshareApp2x
|
||||||
import org.bigbluebutton.core.apps.presentation.PresentationApp2x
|
import org.bigbluebutton.core.apps.presentation.PresentationApp2x
|
||||||
import org.bigbluebutton.core.apps.meeting._
|
import org.bigbluebutton.core.apps.meeting._
|
||||||
import org.bigbluebutton.core.apps.users.UsersApp2x
|
import org.bigbluebutton.core.apps.users.UsersApp2x
|
||||||
import org.bigbluebutton.core.apps.sharednotes.SharedNotesApp2x
|
import org.bigbluebutton.core.apps.sharednotes.SharedNotesApp2x
|
||||||
import org.bigbluebutton.core.apps.whiteboard.WhiteboardApp2x
|
import org.bigbluebutton.core.apps.whiteboard.WhiteboardApp2x
|
||||||
import org.bigbluebutton.core.bus._
|
import org.bigbluebutton.core.bus._
|
||||||
import org.bigbluebutton.core.models._
|
import org.bigbluebutton.core.models._
|
||||||
import org.bigbluebutton.core2.MeetingStatus2x
|
import org.bigbluebutton.core2.MeetingStatus2x
|
||||||
import org.bigbluebutton.core2.message.handlers._
|
import org.bigbluebutton.core2.message.handlers._
|
||||||
import org.bigbluebutton.core2.message.handlers.users._
|
import org.bigbluebutton.core2.message.handlers.users._
|
||||||
import org.bigbluebutton.core2.message.handlers.meeting._
|
import org.bigbluebutton.core2.message.handlers.meeting._
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.apps.breakout._
|
import org.bigbluebutton.core.apps.breakout._
|
||||||
import org.bigbluebutton.core.apps.polls._
|
import org.bigbluebutton.core.apps.polls._
|
||||||
import org.bigbluebutton.core.apps.voice._
|
import org.bigbluebutton.core.apps.voice._
|
||||||
|
import com.softwaremill.quicklens._
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import org.bigbluebutton.core2.testdata.FakeTestData
|
import org.bigbluebutton.core2.testdata.FakeTestData
|
||||||
import org.bigbluebutton.core.apps.layout.LayoutApp2x
|
import org.bigbluebutton.core.apps.layout.LayoutApp2x
|
||||||
import org.bigbluebutton.core.apps.meeting.SyncGetMeetingInfoRespMsgHdlr
|
import org.bigbluebutton.core.apps.meeting.SyncGetMeetingInfoRespMsgHdlr
|
||||||
|
|
||||||
object MeetingActor {
|
object MeetingActor {
|
||||||
def props(
|
def props(
|
||||||
props: DefaultProps,
|
props: DefaultProps,
|
||||||
eventBus: IncomingEventBus,
|
eventBus: IncomingEventBus,
|
||||||
outGW: OutMessageGateway,
|
outGW: OutMessageGateway,
|
||||||
liveMeeting: LiveMeeting
|
liveMeeting: LiveMeeting
|
||||||
): Props =
|
): Props =
|
||||||
Props(classOf[MeetingActor], props, eventBus, outGW, liveMeeting)
|
Props(classOf[MeetingActor], props, eventBus, outGW, liveMeeting)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MeetingActor(
|
class MeetingActor(
|
||||||
val props: DefaultProps,
|
val props: DefaultProps,
|
||||||
val eventBus: IncomingEventBus,
|
val eventBus: IncomingEventBus,
|
||||||
val outGW: OutMessageGateway,
|
val outGW: OutMessageGateway,
|
||||||
val liveMeeting: LiveMeeting
|
val liveMeeting: LiveMeeting
|
||||||
)
|
)
|
||||||
extends BaseMeetingActor
|
extends BaseMeetingActor
|
||||||
with GuestsApp
|
with GuestsApp
|
||||||
with LayoutApp2x
|
with LayoutApp2x
|
||||||
with VoiceApp2x
|
with VoiceApp2x
|
||||||
with PollApp2x
|
with PollApp2x
|
||||||
with BreakoutApp2x
|
with BreakoutApp2x
|
||||||
with UsersApp2x
|
with UsersApp2x
|
||||||
with WhiteboardApp2x
|
with WhiteboardApp2x
|
||||||
|
|
||||||
with PermisssionCheck
|
with PermisssionCheck
|
||||||
with UserBroadcastCamStartMsgHdlr
|
with UserBroadcastCamStartMsgHdlr
|
||||||
with UserJoinMeetingReqMsgHdlr
|
with UserJoinMeetingReqMsgHdlr
|
||||||
with UserBroadcastCamStopMsgHdlr
|
with UserBroadcastCamStopMsgHdlr
|
||||||
with UserConnectedToGlobalAudioMsgHdlr
|
with UserConnectedToGlobalAudioMsgHdlr
|
||||||
with UserDisconnectedFromGlobalAudioMsgHdlr
|
with UserDisconnectedFromGlobalAudioMsgHdlr
|
||||||
with MuteAllExceptPresentersCmdMsgHdlr
|
with MuteAllExceptPresentersCmdMsgHdlr
|
||||||
with MuteMeetingCmdMsgHdlr
|
with MuteMeetingCmdMsgHdlr
|
||||||
with IsMeetingMutedReqMsgHdlr
|
with IsMeetingMutedReqMsgHdlr
|
||||||
with MuteUserCmdMsgHdlr
|
with MuteUserCmdMsgHdlr
|
||||||
with EjectUserFromVoiceCmdMsgHdlr
|
with EjectUserFromVoiceCmdMsgHdlr
|
||||||
with EndMeetingSysCmdMsgHdlr
|
with EndMeetingSysCmdMsgHdlr
|
||||||
with DestroyMeetingSysCmdMsgHdlr
|
with DestroyMeetingSysCmdMsgHdlr
|
||||||
with SendTimeRemainingUpdateHdlr
|
with SendTimeRemainingUpdateHdlr
|
||||||
with SyncGetMeetingInfoRespMsgHdlr {
|
with SyncGetMeetingInfoRespMsgHdlr {
|
||||||
|
|
||||||
override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
|
override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
|
||||||
case e: Exception => {
|
case e: Exception => {
|
||||||
val sw: StringWriter = new StringWriter()
|
val sw: StringWriter = new StringWriter()
|
||||||
sw.write("An exception has been thrown on MeetingActor, exception message [" + e.getMessage() + "] (full stacktrace below)\n")
|
sw.write("An exception has been thrown on MeetingActor, exception message [" + e.getMessage() + "] (full stacktrace below)\n")
|
||||||
e.printStackTrace(new PrintWriter(sw))
|
e.printStackTrace(new PrintWriter(sw))
|
||||||
log.error(sw.toString())
|
log.error(sw.toString())
|
||||||
Resume
|
Resume
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Put the internal message injector into another actor so this
|
* Put the internal message injector into another actor so this
|
||||||
* actor is easy to test.
|
* actor is easy to test.
|
||||||
*/
|
*/
|
||||||
var actorMonitor = context.actorOf(
|
var actorMonitor = context.actorOf(
|
||||||
MeetingActorAudit.props(props, eventBus, outGW),
|
MeetingActorAudit.props(props, eventBus, outGW),
|
||||||
"actorMonitor-" + props.meetingProp.intId
|
"actorMonitor-" + props.meetingProp.intId
|
||||||
)
|
)
|
||||||
|
|
||||||
val presentationApp2x = new PresentationApp2x(liveMeeting, outGW)
|
val presentationApp2x = new PresentationApp2x(liveMeeting, outGW)
|
||||||
val screenshareApp2x = new ScreenshareApp2x(liveMeeting, outGW)
|
val screenshareApp2x = new ScreenshareApp2x(liveMeeting, outGW)
|
||||||
val captionApp2x = new CaptionApp2x(liveMeeting, outGW)
|
val captionApp2x = new CaptionApp2x(liveMeeting, outGW)
|
||||||
val sharedNotesApp2x = new SharedNotesApp2x(liveMeeting, outGW)
|
val sharedNotesApp2x = new SharedNotesApp2x(liveMeeting, outGW)
|
||||||
val chatApp2x = new ChatApp2x(liveMeeting, outGW)
|
val chatApp2x = new ChatApp2x(liveMeeting, outGW)
|
||||||
val usersApp = new UsersApp(liveMeeting, outGW)
|
val usersApp = new UsersApp(liveMeeting, outGW, eventBus)
|
||||||
|
|
||||||
var inactivityTracker = new MeetingInactivityTracker(
|
val expiryTrackerHelper = new MeetingExpiryTrackerHelper(liveMeeting, outGW, eventBus)
|
||||||
liveMeeting.props.durationProps.maxInactivityTimeoutMinutes,
|
|
||||||
liveMeeting.props.durationProps.warnMinutesBeforeMax,
|
val inactivityTracker = new MeetingInactivityTracker(
|
||||||
TimeUtil.millisToMinutes(System.currentTimeMillis()), false, 0L
|
props.durationProps.maxInactivityTimeoutMinutes,
|
||||||
)
|
props.durationProps.warnMinutesBeforeMax,
|
||||||
|
lastActivityTimestamp = TimeUtil.timeNowInSeconds(),
|
||||||
var expiryTracker = new MeetingExpiryTracker(
|
warningSent = false,
|
||||||
TimeUtil.millisToMinutes(System.currentTimeMillis()),
|
warningSentOnTimestamp = 0L
|
||||||
false, 0L
|
)
|
||||||
)
|
|
||||||
|
val expiryTracker = new MeetingExpiryTracker(
|
||||||
/*******************************************************************/
|
startedOn = TimeUtil.timeNowInSeconds(),
|
||||||
//object FakeTestData extends FakeTestData
|
userHasJoined = false,
|
||||||
//FakeTestData.createFakeUsers(liveMeeting)
|
lastUserLeftOn = None,
|
||||||
/*******************************************************************/
|
durationInMinutes = props.durationProps.duration,
|
||||||
|
meetingExpireIfNoUserJoinedInMinutes = props.durationProps.meetingExpireIfNoUserJoinedInMinutes,
|
||||||
def receive = {
|
meetingExpireWhenLastUserLeftInMinutes = props.durationProps.meetingExpireWhenLastUserLeftInMinutes
|
||||||
//=============================
|
)
|
||||||
// 2x messages
|
|
||||||
case msg: BbbCommonEnvCoreMsg => handleBbbCommonEnvCoreMsg(msg)
|
var state = new MeetingState2x(inactivityTracker, expiryTracker)
|
||||||
|
|
||||||
// Handling RegisterUserReqMsg as it is forwarded from BBBActor and
|
/*******************************************************************/
|
||||||
// its type is not BbbCommonEnvCoreMsg
|
//object FakeTestData extends FakeTestData
|
||||||
case m: RegisterUserReqMsg => usersApp.handleRegisterUserReqMsg(m)
|
//FakeTestData.createFakeUsers(liveMeeting)
|
||||||
case m: GetAllMeetingsReqMsg => handleGetAllMeetingsReqMsg(m)
|
/*******************************************************************/
|
||||||
|
|
||||||
// Meeting
|
def receive = {
|
||||||
case m: DestroyMeetingSysCmdMsg => handleDestroyMeetingSysCmdMsg(m)
|
//=============================
|
||||||
|
// 2x messages
|
||||||
//======================================
|
case msg: BbbCommonEnvCoreMsg => handleBbbCommonEnvCoreMsg(msg)
|
||||||
|
|
||||||
//=======================================
|
// Handling RegisterUserReqMsg as it is forwarded from BBBActor and
|
||||||
// old messages
|
// its type is not BbbCommonEnvCoreMsg
|
||||||
case msg: MonitorNumberOfUsers => handleMonitorNumberOfUsers(msg)
|
case m: RegisterUserReqMsg => usersApp.handleRegisterUserReqMsg(m)
|
||||||
|
case m: GetAllMeetingsReqMsg => handleGetAllMeetingsReqMsg(m)
|
||||||
case msg: AllowUserToShareDesktop => handleAllowUserToShareDesktop(msg)
|
|
||||||
case msg: ExtendMeetingDuration => handleExtendMeetingDuration(msg)
|
// Meeting
|
||||||
case msg: SendTimeRemainingUpdate => handleSendTimeRemainingUpdate(msg)
|
case m: DestroyMeetingSysCmdMsg => handleDestroyMeetingSysCmdMsg(m)
|
||||||
|
|
||||||
// Screenshare
|
//======================================
|
||||||
case msg: DeskShareGetDeskShareInfoRequest => handleDeskShareGetDeskShareInfoRequest(msg)
|
|
||||||
|
//=======================================
|
||||||
// Guest
|
// old messages
|
||||||
case msg: GetGuestPolicy => handleGetGuestPolicy(msg)
|
case msg: MonitorNumberOfUsersInternalMsg => handleMonitorNumberOfUsers(msg)
|
||||||
case msg: SetGuestPolicy => handleSetGuestPolicy(msg)
|
|
||||||
|
case msg: AllowUserToShareDesktop => handleAllowUserToShareDesktop(msg)
|
||||||
case _ => // do nothing
|
case msg: ExtendMeetingDuration => handleExtendMeetingDuration(msg)
|
||||||
}
|
case msg: SendTimeRemainingUpdate => state = handleSendTimeRemainingUpdate(msg, state)
|
||||||
|
|
||||||
private def handleBbbCommonEnvCoreMsg(msg: BbbCommonEnvCoreMsg): Unit = {
|
// Screenshare
|
||||||
// TODO: Update meeting activity status here
|
case msg: DeskShareGetDeskShareInfoRequest => handleDeskShareGetDeskShareInfoRequest(msg)
|
||||||
// updateActivityStatus(msg)
|
|
||||||
|
case _ => // do nothing
|
||||||
msg.core match {
|
}
|
||||||
// Users
|
|
||||||
case m: ValidateAuthTokenReqMsg => usersApp.handleValidateAuthTokenReqMsg(m)
|
private def handleBbbCommonEnvCoreMsg(msg: BbbCommonEnvCoreMsg): Unit = {
|
||||||
case m: UserJoinMeetingReqMsg => handleUserJoinMeetingReqMsg(m)
|
state = MeetingInactivityTracker.updateLastActivityTimestamp(state, TimeUtil.timeNowInSeconds())
|
||||||
case m: UserLeaveReqMsg => handleUserLeaveReqMsg(m)
|
|
||||||
case m: UserBroadcastCamStartMsg => handleUserBroadcastCamStartMsg(m)
|
msg.core match {
|
||||||
case m: UserBroadcastCamStopMsg => handleUserBroadcastCamStopMsg(m)
|
// Users
|
||||||
case m: UserJoinedVoiceConfEvtMsg => handleUserJoinedVoiceConfEvtMsg(m)
|
case m: ValidateAuthTokenReqMsg =>
|
||||||
case m: MeetingActivityResponseCmdMsg => inactivityTracker = usersApp.handleMeetingActivityResponseCmdMsg(m, inactivityTracker)
|
state = usersApp.handleValidateAuthTokenReqMsg(m, state)
|
||||||
case m: LogoutAndEndMeetingCmdMsg => usersApp.handleLogoutAndEndMeetingCmdMsg(m)
|
case m: UserJoinMeetingReqMsg =>
|
||||||
case m: SetRecordingStatusCmdMsg => usersApp.handleSetRecordingStatusCmdMsg(m)
|
state = handleUserJoinMeetingReqMsg(m, state)
|
||||||
case m: GetRecordingStatusReqMsg => usersApp.handleGetRecordingStatusReqMsg(m)
|
case m: UserLeaveReqMsg =>
|
||||||
case m: ChangeUserEmojiCmdMsg => handleChangeUserEmojiCmdMsg(m)
|
state = handleUserLeaveReqMsg(m, state)
|
||||||
case m: EjectUserFromMeetingCmdMsg => usersApp.handleEjectUserFromMeetingCmdMsg(m)
|
case m: UserBroadcastCamStartMsg => handleUserBroadcastCamStartMsg(m)
|
||||||
case m: GetUsersMeetingReqMsg => usersApp.handleGetUsersMeetingReqMsg(m)
|
case m: UserBroadcastCamStopMsg => handleUserBroadcastCamStopMsg(m)
|
||||||
|
case m: UserJoinedVoiceConfEvtMsg => handleUserJoinedVoiceConfEvtMsg(m)
|
||||||
// Whiteboard
|
case m: MeetingActivityResponseCmdMsg =>
|
||||||
case m: SendCursorPositionPubMsg => handleSendCursorPositionPubMsg(m)
|
state = usersApp.handleMeetingActivityResponseCmdMsg(m, state)
|
||||||
case m: ClearWhiteboardPubMsg => handleClearWhiteboardPubMsg(m)
|
case m: LogoutAndEndMeetingCmdMsg => usersApp.handleLogoutAndEndMeetingCmdMsg(m)
|
||||||
case m: UndoWhiteboardPubMsg => handleUndoWhiteboardPubMsg(m)
|
case m: SetRecordingStatusCmdMsg => usersApp.handleSetRecordingStatusCmdMsg(m)
|
||||||
case m: ModifyWhiteboardAccessPubMsg => handleModifyWhiteboardAccessPubMsg(m)
|
case m: GetRecordingStatusReqMsg => usersApp.handleGetRecordingStatusReqMsg(m)
|
||||||
case m: GetWhiteboardAccessReqMsg => handleGetWhiteboardAccessReqMsg(m)
|
case m: ChangeUserEmojiCmdMsg => handleChangeUserEmojiCmdMsg(m)
|
||||||
case m: SendWhiteboardAnnotationPubMsg => handleSendWhiteboardAnnotationPubMsg(m)
|
case m: EjectUserFromMeetingCmdMsg => usersApp.handleEjectUserFromMeetingCmdMsg(m)
|
||||||
case m: GetWhiteboardAnnotationsReqMsg => handleGetWhiteboardAnnotationsReqMsg(m)
|
case m: GetUsersMeetingReqMsg => usersApp.handleGetUsersMeetingReqMsg(m)
|
||||||
|
|
||||||
// Poll
|
// Whiteboard
|
||||||
case m: StartPollReqMsg => handleStartPollReqMsg(m)
|
case m: SendCursorPositionPubMsg => handleSendCursorPositionPubMsg(m)
|
||||||
case m: StartCustomPollReqMsg => handleStartCustomPollReqMsg(m)
|
case m: ClearWhiteboardPubMsg => handleClearWhiteboardPubMsg(m)
|
||||||
case m: StopPollReqMsg => handleStopPollReqMsg(m)
|
case m: UndoWhiteboardPubMsg => handleUndoWhiteboardPubMsg(m)
|
||||||
case m: ShowPollResultReqMsg => handleShowPollResultReqMsg(m)
|
case m: ModifyWhiteboardAccessPubMsg => handleModifyWhiteboardAccessPubMsg(m)
|
||||||
case m: HidePollResultReqMsg => handleHidePollResultReqMsg(m)
|
case m: GetWhiteboardAccessReqMsg => handleGetWhiteboardAccessReqMsg(m)
|
||||||
case m: GetCurrentPollReqMsg => handleGetCurrentPollReqMsg(m)
|
case m: SendWhiteboardAnnotationPubMsg => handleSendWhiteboardAnnotationPubMsg(m)
|
||||||
case m: RespondToPollReqMsg => handleRespondToPollReqMsg(m)
|
case m: GetWhiteboardAnnotationsReqMsg => handleGetWhiteboardAnnotationsReqMsg(m)
|
||||||
|
|
||||||
// Breakout
|
// Poll
|
||||||
case m: BreakoutRoomsListMsg => handleBreakoutRoomsListMsg(m)
|
case m: StartPollReqMsg => handleStartPollReqMsg(m)
|
||||||
case m: CreateBreakoutRoomsCmdMsg => handleCreateBreakoutRoomsCmdMsg(m)
|
case m: StartCustomPollReqMsg => handleStartCustomPollReqMsg(m)
|
||||||
case m: EndAllBreakoutRoomsMsg => handleEndAllBreakoutRoomsMsg(m)
|
case m: StopPollReqMsg => handleStopPollReqMsg(m)
|
||||||
case m: RequestBreakoutJoinURLReqMsg => handleRequestBreakoutJoinURLReqMsg(m)
|
case m: ShowPollResultReqMsg => handleShowPollResultReqMsg(m)
|
||||||
case m: BreakoutRoomCreatedMsg => handleBreakoutRoomCreatedMsg(m)
|
case m: HidePollResultReqMsg => handleHidePollResultReqMsg(m)
|
||||||
case m: BreakoutRoomEndedMsg => handleBreakoutRoomEndedMsg(m)
|
case m: GetCurrentPollReqMsg => handleGetCurrentPollReqMsg(m)
|
||||||
case m: BreakoutRoomUsersUpdateMsg => handleBreakoutRoomUsersUpdateMsg(m)
|
case m: RespondToPollReqMsg => handleRespondToPollReqMsg(m)
|
||||||
case m: SendBreakoutUsersUpdateMsg => handleSendBreakoutUsersUpdateMsg(m)
|
|
||||||
case m: TransferUserToMeetingRequestMsg => handleTransferUserToMeetingRequestMsg(m)
|
// Breakout
|
||||||
|
case m: BreakoutRoomsListMsg => handleBreakoutRoomsListMsg(m)
|
||||||
// Voice
|
case m: CreateBreakoutRoomsCmdMsg => handleCreateBreakoutRoomsCmdMsg(m)
|
||||||
case m: UserLeftVoiceConfEvtMsg => handleUserLeftVoiceConfEvtMsg(m)
|
case m: EndAllBreakoutRoomsMsg => handleEndAllBreakoutRoomsMsg(m)
|
||||||
case m: UserMutedInVoiceConfEvtMsg => handleUserMutedInVoiceConfEvtMsg(m)
|
case m: RequestBreakoutJoinURLReqMsg => handleRequestBreakoutJoinURLReqMsg(m)
|
||||||
case m: UserTalkingInVoiceConfEvtMsg => handleUserTalkingInVoiceConfEvtMsg(m)
|
case m: BreakoutRoomCreatedMsg => handleBreakoutRoomCreatedMsg(m)
|
||||||
case m: RecordingStartedVoiceConfEvtMsg => handleRecordingStartedVoiceConfEvtMsg(m)
|
case m: BreakoutRoomEndedMsg => handleBreakoutRoomEndedMsg(m)
|
||||||
case m: MuteUserCmdMsg => handleMuteUserCmdMsg(m)
|
case m: BreakoutRoomUsersUpdateMsg => handleBreakoutRoomUsersUpdateMsg(m)
|
||||||
case m: MuteAllExceptPresentersCmdMsg => handleMuteAllExceptPresentersCmdMsg(m)
|
case m: SendBreakoutUsersUpdateMsg => handleSendBreakoutUsersUpdateMsg(m)
|
||||||
case m: EjectUserFromVoiceCmdMsg => handleEjectUserFromVoiceCmdMsg(m)
|
case m: TransferUserToMeetingRequestMsg => handleTransferUserToMeetingRequestMsg(m)
|
||||||
case m: IsMeetingMutedReqMsg => handleIsMeetingMutedReqMsg(m)
|
|
||||||
case m: MuteMeetingCmdMsg => handleMuteMeetingCmdMsg(m)
|
// Voice
|
||||||
case m: UserConnectedToGlobalAudioMsg => handleUserConnectedToGlobalAudioMsg(m)
|
case m: UserLeftVoiceConfEvtMsg => handleUserLeftVoiceConfEvtMsg(m)
|
||||||
case m: UserDisconnectedFromGlobalAudioMsg => handleUserDisconnectedFromGlobalAudioMsg(m)
|
case m: UserMutedInVoiceConfEvtMsg => handleUserMutedInVoiceConfEvtMsg(m)
|
||||||
|
case m: UserTalkingInVoiceConfEvtMsg => handleUserTalkingInVoiceConfEvtMsg(m)
|
||||||
// Layout
|
case m: RecordingStartedVoiceConfEvtMsg => handleRecordingStartedVoiceConfEvtMsg(m)
|
||||||
case m: GetCurrentLayoutReqMsg => handleGetCurrentLayoutReqMsg(m)
|
case m: MuteUserCmdMsg => handleMuteUserCmdMsg(m)
|
||||||
case m: LockLayoutMsg => handleLockLayoutMsg(m)
|
case m: MuteAllExceptPresentersCmdMsg => handleMuteAllExceptPresentersCmdMsg(m)
|
||||||
case m: BroadcastLayoutMsg => handleBroadcastLayoutMsg(m)
|
case m: EjectUserFromVoiceCmdMsg => handleEjectUserFromVoiceCmdMsg(m)
|
||||||
|
case m: IsMeetingMutedReqMsg => handleIsMeetingMutedReqMsg(m)
|
||||||
// Presentation
|
case m: MuteMeetingCmdMsg => handleMuteMeetingCmdMsg(m)
|
||||||
case m: SetCurrentPresentationPubMsg => presentationApp2x.handleSetCurrentPresentationPubMsg(m)
|
case m: UserConnectedToGlobalAudioMsg => handleUserConnectedToGlobalAudioMsg(m)
|
||||||
case m: GetPresentationInfoReqMsg => presentationApp2x.handleGetPresentationInfoReqMsg(m)
|
case m: UserDisconnectedFromGlobalAudioMsg => handleUserDisconnectedFromGlobalAudioMsg(m)
|
||||||
case m: SetCurrentPagePubMsg => presentationApp2x.handleSetCurrentPagePubMsg(m)
|
|
||||||
case m: ResizeAndMovePagePubMsg => presentationApp2x.handleResizeAndMovePagePubMsg(m)
|
// Layout
|
||||||
case m: RemovePresentationPubMsg => presentationApp2x.handleRemovePresentationPubMsg(m)
|
case m: GetCurrentLayoutReqMsg => handleGetCurrentLayoutReqMsg(m)
|
||||||
case m: PreuploadedPresentationsSysPubMsg => presentationApp2x.handlePreuploadedPresentationsPubMsg(m)
|
case m: LockLayoutMsg => handleLockLayoutMsg(m)
|
||||||
case m: PresentationConversionUpdateSysPubMsg => presentationApp2x.handlePresentationConversionUpdatePubMsg(m)
|
case m: BroadcastLayoutMsg => handleBroadcastLayoutMsg(m)
|
||||||
case m: PresentationPageCountErrorSysPubMsg => presentationApp2x.handlePresentationPageCountErrorPubMsg(m)
|
|
||||||
case m: PresentationPageGeneratedSysPubMsg => presentationApp2x.handlePresentationPageGeneratedPubMsg(m)
|
// Presentation
|
||||||
case m: PresentationConversionCompletedSysPubMsg => presentationApp2x.handlePresentationConversionCompletedPubMsg(m)
|
case m: SetCurrentPresentationPubMsg => presentationApp2x.handleSetCurrentPresentationPubMsg(m)
|
||||||
case m: AssignPresenterReqMsg => handlePresenterChange(m)
|
case m: GetPresentationInfoReqMsg => presentationApp2x.handleGetPresentationInfoReqMsg(m)
|
||||||
|
case m: SetCurrentPagePubMsg => presentationApp2x.handleSetCurrentPagePubMsg(m)
|
||||||
// Caption
|
case m: ResizeAndMovePagePubMsg => presentationApp2x.handleResizeAndMovePagePubMsg(m)
|
||||||
case m: EditCaptionHistoryPubMsg => captionApp2x.handleEditCaptionHistoryPubMsg(m)
|
case m: RemovePresentationPubMsg => presentationApp2x.handleRemovePresentationPubMsg(m)
|
||||||
case m: UpdateCaptionOwnerPubMsg => captionApp2x.handleUpdateCaptionOwnerPubMsg(m)
|
case m: PreuploadedPresentationsSysPubMsg => presentationApp2x.handlePreuploadedPresentationsPubMsg(m)
|
||||||
case m: SendCaptionHistoryReqMsg => captionApp2x.handleSendCaptionHistoryReqMsg(m)
|
case m: PresentationConversionUpdateSysPubMsg => presentationApp2x.handlePresentationConversionUpdatePubMsg(m)
|
||||||
|
case m: PresentationPageCountErrorSysPubMsg => presentationApp2x.handlePresentationPageCountErrorPubMsg(m)
|
||||||
// SharedNotes
|
case m: PresentationPageGeneratedSysPubMsg => presentationApp2x.handlePresentationPageGeneratedPubMsg(m)
|
||||||
case m: GetSharedNotesPubMsg => sharedNotesApp2x.handleGetSharedNotesPubMsg(m)
|
case m: PresentationConversionCompletedSysPubMsg => presentationApp2x.handlePresentationConversionCompletedPubMsg(m)
|
||||||
case m: SyncSharedNotePubMsg => sharedNotesApp2x.handleSyncSharedNotePubMsg(m)
|
case m: AssignPresenterReqMsg => handlePresenterChange(m)
|
||||||
case m: UpdateSharedNoteReqMsg => sharedNotesApp2x.handleUpdateSharedNoteReqMsg(m)
|
|
||||||
case m: CreateSharedNoteReqMsg => sharedNotesApp2x.handleCreateSharedNoteReqMsg(m)
|
// Caption
|
||||||
case m: DestroySharedNoteReqMsg => sharedNotesApp2x.handleDestroySharedNoteReqMsg(m)
|
case m: EditCaptionHistoryPubMsg => captionApp2x.handleEditCaptionHistoryPubMsg(m)
|
||||||
|
case m: UpdateCaptionOwnerPubMsg => captionApp2x.handleUpdateCaptionOwnerPubMsg(m)
|
||||||
// Guests
|
case m: SendCaptionHistoryReqMsg => captionApp2x.handleSendCaptionHistoryReqMsg(m)
|
||||||
case m: GetGuestsWaitingApprovalReqMsg => handleGetGuestsWaitingApprovalReqMsg(m)
|
|
||||||
case m: SetGuestPolicyMsg => handleSetGuestPolicyMsg(m)
|
// SharedNotes
|
||||||
case m: GuestsWaitingApprovedMsg => handleGuestsWaitingApprovedMsg(m)
|
case m: GetSharedNotesPubMsg => sharedNotesApp2x.handleGetSharedNotesPubMsg(m)
|
||||||
|
case m: SyncSharedNotePubMsg => sharedNotesApp2x.handleSyncSharedNotePubMsg(m)
|
||||||
// Chat
|
case m: UpdateSharedNoteReqMsg => sharedNotesApp2x.handleUpdateSharedNoteReqMsg(m)
|
||||||
case m: GetChatHistoryReqMsg => chatApp2x.handleGetChatHistoryReqMsg(m)
|
case m: CreateSharedNoteReqMsg => sharedNotesApp2x.handleCreateSharedNoteReqMsg(m)
|
||||||
case m: SendPublicMessagePubMsg => chatApp2x.handleSendPublicMessagePubMsg(m)
|
case m: DestroySharedNoteReqMsg => sharedNotesApp2x.handleDestroySharedNoteReqMsg(m)
|
||||||
case m: SendPrivateMessagePubMsg => chatApp2x.handleSendPrivateMessagePubMsg(m)
|
|
||||||
case m: ClearPublicChatHistoryPubMsg => chatApp2x.handleClearPublicChatHistoryPubMsg(m)
|
// Guests
|
||||||
|
case m: GetGuestsWaitingApprovalReqMsg => handleGetGuestsWaitingApprovalReqMsg(m)
|
||||||
// Screenshare
|
case m: SetGuestPolicyCmdMsg => handleSetGuestPolicyMsg(m)
|
||||||
case m: ScreenshareStartedVoiceConfEvtMsg => screenshareApp2x.handleScreenshareStartedVoiceConfEvtMsg(m)
|
case m: GuestsWaitingApprovedMsg => handleGuestsWaitingApprovedMsg(m)
|
||||||
case m: ScreenshareStoppedVoiceConfEvtMsg => screenshareApp2x.handleScreenshareStoppedVoiceConfEvtMsg(m)
|
case m: GetGuestPolicyReqMsg => handleGetGuestPolicyReqMsg(m)
|
||||||
case m: ScreenshareRtmpBroadcastStartedVoiceConfEvtMsg => screenshareApp2x.handleScreenshareRtmpBroadcastStartedVoiceConfEvtMsg(m)
|
// Chat
|
||||||
case m: ScreenshareRtmpBroadcastStoppedVoiceConfEvtMsg => screenshareApp2x.handleScreenshareRtmpBroadcastStoppedVoiceConfEvtMsg(m)
|
case m: GetChatHistoryReqMsg => chatApp2x.handleGetChatHistoryReqMsg(m)
|
||||||
case m: GetScreenshareStatusReqMsg => screenshareApp2x.handleGetScreenshareStatusReqMsg(m)
|
case m: SendPublicMessagePubMsg => chatApp2x.handleSendPublicMessagePubMsg(m)
|
||||||
|
case m: SendPrivateMessagePubMsg => chatApp2x.handleSendPrivateMessagePubMsg(m)
|
||||||
case _ => log.warning("***** Cannot handle " + msg.envelope.name)
|
case m: ClearPublicChatHistoryPubMsg => chatApp2x.handleClearPublicChatHistoryPubMsg(m)
|
||||||
}
|
|
||||||
}
|
// Screenshare
|
||||||
|
case m: ScreenshareStartedVoiceConfEvtMsg => screenshareApp2x.handleScreenshareStartedVoiceConfEvtMsg(m)
|
||||||
def handleGetAllMeetingsReqMsg(msg: GetAllMeetingsReqMsg): Unit = {
|
case m: ScreenshareStoppedVoiceConfEvtMsg => screenshareApp2x.handleScreenshareStoppedVoiceConfEvtMsg(m)
|
||||||
// sync all meetings
|
case m: ScreenshareRtmpBroadcastStartedVoiceConfEvtMsg => screenshareApp2x.handleScreenshareRtmpBroadcastStartedVoiceConfEvtMsg(m)
|
||||||
handleSyncGetMeetingInfoRespMsg(liveMeeting.props)
|
case m: ScreenshareRtmpBroadcastStoppedVoiceConfEvtMsg => screenshareApp2x.handleScreenshareRtmpBroadcastStoppedVoiceConfEvtMsg(m)
|
||||||
|
case m: GetScreenshareStatusReqMsg => screenshareApp2x.handleGetScreenshareStatusReqMsg(m)
|
||||||
// sync all users
|
|
||||||
usersApp.handleSyncGetUsersMeetingRespMsg()
|
case _ => log.warning("***** Cannot handle " + msg.envelope.name)
|
||||||
|
}
|
||||||
// sync all presentations
|
}
|
||||||
presentationApp2x.handleSyncGetPresentationInfoRespMsg()
|
|
||||||
|
def handleGetAllMeetingsReqMsg(msg: GetAllMeetingsReqMsg): Unit = {
|
||||||
// TODO send all chat
|
// sync all meetings
|
||||||
// TODO send all lock settings
|
handleSyncGetMeetingInfoRespMsg(liveMeeting.props)
|
||||||
// TODO send all screen sharing info
|
|
||||||
}
|
// sync all users
|
||||||
|
usersApp.handleSyncGetUsersMeetingRespMsg()
|
||||||
def handlePresenterChange(msg: AssignPresenterReqMsg): Unit = {
|
|
||||||
// Stop poll if one is running as presenter left
|
// sync all presentations
|
||||||
handleStopPollReqMsg(msg.header.userId)
|
presentationApp2x.handleSyncGetPresentationInfoRespMsg()
|
||||||
|
|
||||||
// switch user presenter status for old and new presenter
|
// TODO send all chat
|
||||||
usersApp.handleAssignPresenterReqMsg(msg)
|
// TODO send all lock settings
|
||||||
|
// TODO send all screen sharing info
|
||||||
// TODO stop current screen sharing session (initiated by the old presenter)
|
}
|
||||||
|
|
||||||
}
|
def handlePresenterChange(msg: AssignPresenterReqMsg): Unit = {
|
||||||
|
// Stop poll if one is running as presenter left
|
||||||
def handleDeskShareGetDeskShareInfoRequest(msg: DeskShareGetDeskShareInfoRequest): Unit = {
|
handleStopPollReqMsg(msg.header.userId)
|
||||||
|
|
||||||
log.info("handleDeskShareGetDeskShareInfoRequest: " + msg.conferenceName + "isBroadcasting="
|
// switch user presenter status for old and new presenter
|
||||||
+ ScreenshareModel.isBroadcastingRTMP(liveMeeting.screenshareModel) + " URL:" +
|
usersApp.handleAssignPresenterReqMsg(msg)
|
||||||
ScreenshareModel.getRTMPBroadcastingUrl(liveMeeting.screenshareModel))
|
|
||||||
|
// TODO stop current screen sharing session (initiated by the old presenter)
|
||||||
if (ScreenshareModel.isBroadcastingRTMP(liveMeeting.screenshareModel)) {
|
|
||||||
// if the meeting has an ongoing WebRTC Deskshare session, send a notification
|
}
|
||||||
//outGW.send(new DeskShareNotifyASingleViewer(props.meetingProp.intId, msg.requesterID,
|
|
||||||
// DeskshareModel.getRTMPBroadcastingUrl(liveMeeting.deskshareModel),
|
def handleDeskShareGetDeskShareInfoRequest(msg: DeskShareGetDeskShareInfoRequest): Unit = {
|
||||||
// DeskshareModel.getDesktopShareVideoWidth(liveMeeting.deskshareModel),
|
|
||||||
// DeskshareModel.getDesktopShareVideoHeight(liveMeeting.deskshareModel), true))
|
log.info("handleDeskShareGetDeskShareInfoRequest: " + msg.conferenceName + "isBroadcasting="
|
||||||
}
|
+ ScreenshareModel.isBroadcastingRTMP(liveMeeting.screenshareModel) + " URL:" +
|
||||||
}
|
ScreenshareModel.getRTMPBroadcastingUrl(liveMeeting.screenshareModel))
|
||||||
|
|
||||||
def handleGetGuestPolicy(msg: GetGuestPolicy) {
|
if (ScreenshareModel.isBroadcastingRTMP(liveMeeting.screenshareModel)) {
|
||||||
// outGW.send(new GetGuestPolicyReply(msg.meetingID, props.recordProp.record,
|
// if the meeting has an ongoing WebRTC Deskshare session, send a notification
|
||||||
// msg.requesterID, MeetingStatus2x.getGuestPolicy(liveMeeting.status).toString()))
|
//outGW.send(new DeskShareNotifyASingleViewer(props.meetingProp.intId, msg.requesterID,
|
||||||
}
|
// DeskshareModel.getRTMPBroadcastingUrl(liveMeeting.deskshareModel),
|
||||||
|
// DeskshareModel.getDesktopShareVideoWidth(liveMeeting.deskshareModel),
|
||||||
def handleSetGuestPolicy(msg: SetGuestPolicy) {
|
// DeskshareModel.getDesktopShareVideoHeight(liveMeeting.deskshareModel), true))
|
||||||
// MeetingStatus2x.setGuestPolicy(liveMeeting.status, msg.policy)
|
}
|
||||||
// MeetingStatus2x.setGuestPolicySetBy(liveMeeting.status, msg.setBy)
|
}
|
||||||
// outGW.send(new GuestPolicyChanged(msg.meetingID, props.recordProp.record,
|
|
||||||
// MeetingStatus2x.getGuestPolicy(liveMeeting.status).toString()))
|
def handleAllowUserToShareDesktop(msg: AllowUserToShareDesktop): Unit = {
|
||||||
}
|
Users2x.findPresenter(liveMeeting.users2x) match {
|
||||||
|
case Some(curPres) => {
|
||||||
def handleAllowUserToShareDesktop(msg: AllowUserToShareDesktop): Unit = {
|
val allowed = msg.userID equals (curPres.intId)
|
||||||
Users2x.findPresenter(liveMeeting.users2x) match {
|
// outGW.send(AllowUserToShareDesktopOut(msg.meetingID, msg.userID, allowed))
|
||||||
case Some(curPres) => {
|
}
|
||||||
val allowed = msg.userID equals (curPres.intId)
|
case None => // do nothing
|
||||||
// outGW.send(AllowUserToShareDesktopOut(msg.meetingID, msg.userID, allowed))
|
}
|
||||||
}
|
}
|
||||||
case None => // do nothing
|
|
||||||
}
|
def handleMonitorNumberOfUsers(msg: MonitorNumberOfUsersInternalMsg) {
|
||||||
}
|
state = expiryTrackerHelper.processMeetingInactivityAudit(state)
|
||||||
|
state = expiryTrackerHelper.processMeetingExpiryAudit(state)
|
||||||
def handleMonitorNumberOfUsers(msg: MonitorNumberOfUsers) {
|
}
|
||||||
inactivityTracker = MeetingInactivityTrackerHelper.processMeetingInactivityAudit(
|
|
||||||
props = liveMeeting.props,
|
def handleExtendMeetingDuration(msg: ExtendMeetingDuration) {
|
||||||
outGW,
|
|
||||||
eventBus,
|
}
|
||||||
inactivityTracker
|
|
||||||
)
|
def startRecordingIfAutoStart() {
|
||||||
|
if (props.recordProp.record && !MeetingStatus2x.isRecording(liveMeeting.status) &&
|
||||||
expiryTracker = MeetingExpiryTracker.processMeetingExpiryAudit(liveMeeting.props, expiryTracker, eventBus)
|
props.recordProp.autoStartRecording && Users2x.numUsers(liveMeeting.users2x) == 1) {
|
||||||
|
log.info("Auto start recording. meetingId={}", props.meetingProp.intId)
|
||||||
monitorNumberOfWebUsers()
|
MeetingStatus2x.recordingStarted(liveMeeting.status)
|
||||||
monitorNumberOfUsers()
|
|
||||||
}
|
def buildRecordingStatusChangedEvtMsg(meetingId: String, userId: String, recording: Boolean): BbbCommonEnvCoreMsg = {
|
||||||
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
|
||||||
def monitorNumberOfWebUsers() {
|
val envelope = BbbCoreEnvelope(RecordingStatusChangedEvtMsg.NAME, routing)
|
||||||
|
val body = RecordingStatusChangedEvtMsgBody(recording, userId)
|
||||||
def buildEjectAllFromVoiceConfMsg(meetingId: String, voiceConf: String): BbbCommonEnvCoreMsg = {
|
val header = BbbClientMsgHeader(RecordingStatusChangedEvtMsg.NAME, meetingId, userId)
|
||||||
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
|
val event = RecordingStatusChangedEvtMsg(header, body)
|
||||||
val envelope = BbbCoreEnvelope(EjectAllFromVoiceConfMsg.NAME, routing)
|
|
||||||
val body = EjectAllFromVoiceConfMsgBody(voiceConf)
|
BbbCommonEnvCoreMsg(envelope, event)
|
||||||
val header = BbbCoreHeaderWithMeetingId(EjectAllFromVoiceConfMsg.NAME, meetingId)
|
}
|
||||||
val event = EjectAllFromVoiceConfMsg(header, body)
|
|
||||||
|
val event = buildRecordingStatusChangedEvtMsg(
|
||||||
BbbCommonEnvCoreMsg(envelope, event)
|
liveMeeting.props.meetingProp.intId,
|
||||||
}
|
"system", MeetingStatus2x.isRecording(liveMeeting.status)
|
||||||
|
)
|
||||||
if (Users2x.numUsers(liveMeeting.users2x) == 0 &&
|
outGW.send(event)
|
||||||
MeetingStatus2x.lastWebUserLeftOn(liveMeeting.status) > 0) {
|
|
||||||
if (liveMeeting.timeNowInMinutes - MeetingStatus2x.lastWebUserLeftOn(liveMeeting.status) > 2) {
|
}
|
||||||
log.info("Empty meeting. Ejecting all users from voice. meetingId={}", props.meetingProp.intId)
|
}
|
||||||
val event = buildEjectAllFromVoiceConfMsg(props.meetingProp.intId, props.voiceProp.voiceConf)
|
|
||||||
outGW.send(event)
|
def stopAutoStartedRecording() {
|
||||||
}
|
if (props.recordProp.record && MeetingStatus2x.isRecording(liveMeeting.status) &&
|
||||||
}
|
props.recordProp.autoStartRecording && Users2x.numUsers(liveMeeting.users2x) == 0) {
|
||||||
}
|
log.info("Last web user left. Auto stopping recording. meetingId={}", props.meetingProp.intId)
|
||||||
|
MeetingStatus2x.recordingStopped(liveMeeting.status)
|
||||||
def monitorNumberOfUsers() {
|
|
||||||
val hasUsers = Users2x.numUsers(liveMeeting.users2x) != 0
|
def buildRecordingStatusChangedEvtMsg(meetingId: String, userId: String, recording: Boolean): BbbCommonEnvCoreMsg = {
|
||||||
// TODO: We could use a better control over this message to send it just when it really matters :)
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
|
||||||
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, UpdateMeetingExpireMonitor(props.meetingProp.intId, hasUsers)))
|
val envelope = BbbCoreEnvelope(RecordingStatusChangedEvtMsg.NAME, routing)
|
||||||
}
|
val body = RecordingStatusChangedEvtMsgBody(recording, userId)
|
||||||
|
val header = BbbClientMsgHeader(RecordingStatusChangedEvtMsg.NAME, meetingId, userId)
|
||||||
def handleExtendMeetingDuration(msg: ExtendMeetingDuration) {
|
val event = RecordingStatusChangedEvtMsg(header, body)
|
||||||
|
|
||||||
}
|
BbbCommonEnvCoreMsg(envelope, event)
|
||||||
|
}
|
||||||
def startRecordingIfAutoStart() {
|
|
||||||
if (props.recordProp.record && !MeetingStatus2x.isRecording(liveMeeting.status) &&
|
val event = buildRecordingStatusChangedEvtMsg(
|
||||||
props.recordProp.autoStartRecording && Users2x.numUsers(liveMeeting.users2x) == 1) {
|
liveMeeting.props.meetingProp.intId,
|
||||||
log.info("Auto start recording. meetingId={}", props.meetingProp.intId)
|
"system", MeetingStatus2x.isRecording(liveMeeting.status)
|
||||||
MeetingStatus2x.recordingStarted(liveMeeting.status)
|
)
|
||||||
|
outGW.send(event)
|
||||||
def buildRecordingStatusChangedEvtMsg(meetingId: String, userId: String, recording: Boolean): BbbCommonEnvCoreMsg = {
|
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
|
}
|
||||||
val envelope = BbbCoreEnvelope(RecordingStatusChangedEvtMsg.NAME, routing)
|
}
|
||||||
val body = RecordingStatusChangedEvtMsgBody(recording, userId)
|
|
||||||
val header = BbbClientMsgHeader(RecordingStatusChangedEvtMsg.NAME, meetingId, userId)
|
def record(msg: BbbCoreMsg): Unit = {
|
||||||
val event = RecordingStatusChangedEvtMsg(header, body)
|
if (liveMeeting.props.recordProp.record) {
|
||||||
|
outGW.record(msg)
|
||||||
BbbCommonEnvCoreMsg(envelope, event)
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
val event = buildRecordingStatusChangedEvtMsg(
|
|
||||||
liveMeeting.props.meetingProp.intId,
|
|
||||||
"system", MeetingStatus2x.isRecording(liveMeeting.status)
|
|
||||||
)
|
|
||||||
outGW.send(event)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def stopAutoStartedRecording() {
|
|
||||||
if (props.recordProp.record && MeetingStatus2x.isRecording(liveMeeting.status) &&
|
|
||||||
props.recordProp.autoStartRecording && Users2x.numUsers(liveMeeting.users2x) == 0) {
|
|
||||||
log.info("Last web user left. Auto stopping recording. meetingId={}", props.meetingProp.intId)
|
|
||||||
MeetingStatus2x.recordingStopped(liveMeeting.status)
|
|
||||||
|
|
||||||
def buildRecordingStatusChangedEvtMsg(meetingId: String, userId: String, recording: Boolean): BbbCommonEnvCoreMsg = {
|
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
|
|
||||||
val envelope = BbbCoreEnvelope(RecordingStatusChangedEvtMsg.NAME, routing)
|
|
||||||
val body = RecordingStatusChangedEvtMsgBody(recording, userId)
|
|
||||||
val header = BbbClientMsgHeader(RecordingStatusChangedEvtMsg.NAME, meetingId, userId)
|
|
||||||
val event = RecordingStatusChangedEvtMsg(header, body)
|
|
||||||
|
|
||||||
BbbCommonEnvCoreMsg(envelope, event)
|
|
||||||
}
|
|
||||||
|
|
||||||
val event = buildRecordingStatusChangedEvtMsg(
|
|
||||||
liveMeeting.props.meetingProp.intId,
|
|
||||||
"system", MeetingStatus2x.isRecording(liveMeeting.status)
|
|
||||||
)
|
|
||||||
outGW.send(event)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def record(msg: BbbCoreMsg): Unit = {
|
|
||||||
if (liveMeeting.props.recordProp.record) {
|
|
||||||
outGW.record(msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -72,7 +72,7 @@ class MeetingActorAudit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
def handleMonitorNumberOfWebUsers() {
|
def handleMonitorNumberOfWebUsers() {
|
||||||
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, MonitorNumberOfUsers(props.meetingProp.intId)))
|
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, MonitorNumberOfUsersInternalMsg(props.meetingProp.intId)))
|
||||||
|
|
||||||
// Trigger updating users of time remaining on meeting.
|
// Trigger updating users of time remaining on meeting.
|
||||||
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, SendTimeRemainingUpdate(props.meetingProp.intId)))
|
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, SendTimeRemainingUpdate(props.meetingProp.intId)))
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
package org.bigbluebutton.core.running
|
|
||||||
|
|
||||||
import org.bigbluebutton.common2.domain.DefaultProps
|
|
||||||
import org.bigbluebutton.core.api.EndMeeting
|
|
||||||
import org.bigbluebutton.core.bus.{ BigBlueButtonEvent, IncomingEventBus }
|
|
||||||
import org.bigbluebutton.core.domain.MeetingExpiryTracker
|
|
||||||
import org.bigbluebutton.core.util.TimeUtil
|
|
||||||
|
|
||||||
object MeetingExpiryTracker {
|
|
||||||
|
|
||||||
def hasMeetingExpiredNeverBeenJoined(nowInMinutes: Long, startedOnInMinutes: Long, meetingExpireIfNoUserJoinedInMinutes: Long): Boolean = {
|
|
||||||
nowInMinutes - startedOnInMinutes > meetingExpireIfNoUserJoinedInMinutes
|
|
||||||
}
|
|
||||||
|
|
||||||
def meetingOverDuration(nowInMinutes: Long, startedOnInMinutes: Long, durationInMinutes: Long): Boolean = {
|
|
||||||
nowInMinutes > startedOnInMinutes + durationInMinutes
|
|
||||||
}
|
|
||||||
|
|
||||||
def processNeverBeenJoinedExpiry(nowInMinutes: Long, props: DefaultProps, tracker: MeetingExpiryTracker, eventBus: IncomingEventBus): MeetingExpiryTracker = {
|
|
||||||
if (hasMeetingExpiredNeverBeenJoined(nowInMinutes, tracker.startedOnInMinutes,
|
|
||||||
props.durationProps.meetingExpireIfNoUserJoinedInMinutes)) {
|
|
||||||
sendEndMeetingDueToExpiry(props, eventBus)
|
|
||||||
tracker
|
|
||||||
} else {
|
|
||||||
tracker
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def processMeetingExpiryAudit(props: DefaultProps, tracker: MeetingExpiryTracker, eventBus: IncomingEventBus): MeetingExpiryTracker = {
|
|
||||||
val nowInMinutes = TimeUtil.millisToMinutes(System.currentTimeMillis())
|
|
||||||
|
|
||||||
if (!tracker.meetingJoined) {
|
|
||||||
processNeverBeenJoinedExpiry(nowInMinutes, props, tracker, eventBus)
|
|
||||||
} else {
|
|
||||||
if (meetingOverDuration(nowInMinutes, tracker.startedOnInMinutes, props.durationProps.duration)) {
|
|
||||||
sendEndMeetingDueToExpiry(props, eventBus)
|
|
||||||
tracker
|
|
||||||
} else {
|
|
||||||
tracker
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def sendEndMeetingDueToExpiry(props: DefaultProps, eventBus: IncomingEventBus): Unit = {
|
|
||||||
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, EndMeeting(props.meetingProp.intId)))
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,70 @@
|
|||||||
|
package org.bigbluebutton.core.running
|
||||||
|
|
||||||
|
import akka.actor.ActorContext
|
||||||
|
import akka.event.Logging
|
||||||
|
import org.bigbluebutton.common2.domain.DefaultProps
|
||||||
|
import org.bigbluebutton.common2.msgs._
|
||||||
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
|
import org.bigbluebutton.core.bus.IncomingEventBus
|
||||||
|
import org.bigbluebutton.core.domain.{ MeetingEndReason, MeetingExpiryTracker, MeetingInactivityTracker, MeetingState2x }
|
||||||
|
import org.bigbluebutton.core.util.TimeUtil
|
||||||
|
|
||||||
|
class MeetingExpiryTrackerHelper(
|
||||||
|
val liveMeeting: LiveMeeting,
|
||||||
|
val outGW: OutMessageGateway,
|
||||||
|
val eventBus: IncomingEventBus
|
||||||
|
)(implicit val context: ActorContext) extends HandlerHelpers {
|
||||||
|
|
||||||
|
val log = Logging(context.system, getClass)
|
||||||
|
|
||||||
|
def processMeetingExpiryAudit(state: MeetingState2x): MeetingState2x = {
|
||||||
|
val nowInSeconds = TimeUtil.timeNowInSeconds()
|
||||||
|
|
||||||
|
val (expired, reason) = MeetingExpiryTracker.hasMeetingExpired(state, nowInSeconds)
|
||||||
|
if (expired) {
|
||||||
|
for {
|
||||||
|
expireReason <- reason
|
||||||
|
} yield {
|
||||||
|
sendEndMeetingDueToExpiry(expireReason, eventBus, outGW, liveMeeting)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
|
def processMeetingInactivityAudit(state: MeetingState2x): MeetingState2x = {
|
||||||
|
|
||||||
|
val nowInSeconds = TimeUtil.timeNowInSeconds()
|
||||||
|
if (!MeetingInactivityTracker.hasRecentActivity(state, nowInSeconds)) {
|
||||||
|
if (MeetingInactivityTracker.isMeetingInactive(state, nowInSeconds)) {
|
||||||
|
sendEndMeetingDueToExpiry(MeetingEndReason.ENDED_DUE_TO_INACTIVITY, eventBus, outGW, liveMeeting)
|
||||||
|
state
|
||||||
|
} else {
|
||||||
|
if (!MeetingInactivityTracker.warningHasBeenSent(state)) {
|
||||||
|
warnOfMeetingInactivity(nowInSeconds, state)
|
||||||
|
MeetingInactivityTracker.setWarningSentAndTimestamp(state, nowInSeconds)
|
||||||
|
} else {
|
||||||
|
state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def warnOfMeetingInactivity(nowInSeconds: Long, state: MeetingState2x): Unit = {
|
||||||
|
val timeLeftSeconds = MeetingInactivityTracker.timeLeftInSeconds(state, nowInSeconds)
|
||||||
|
val event = buildMeetingInactivityWarningEvtMsg(liveMeeting.props.meetingProp.intId, timeLeftSeconds)
|
||||||
|
outGW.send(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
def buildMeetingInactivityWarningEvtMsg(meetingId: String, timeLeftInSec: Long): BbbCommonEnvCoreMsg = {
|
||||||
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
||||||
|
val envelope = BbbCoreEnvelope(MeetingInactivityWarningEvtMsg.NAME, routing)
|
||||||
|
val body = MeetingInactivityWarningEvtMsgBody(timeLeftInSec)
|
||||||
|
val header = BbbClientMsgHeader(MeetingInactivityWarningEvtMsg.NAME, meetingId, "not-used")
|
||||||
|
val event = MeetingInactivityWarningEvtMsg(header, body)
|
||||||
|
|
||||||
|
BbbCommonEnvCoreMsg(envelope, event)
|
||||||
|
}
|
||||||
|
}
|
@ -1,112 +0,0 @@
|
|||||||
package org.bigbluebutton.core.running
|
|
||||||
|
|
||||||
import org.bigbluebutton.core.domain.MeetingInactivityTracker
|
|
||||||
import com.softwaremill.quicklens._
|
|
||||||
import org.bigbluebutton.common2.domain.DefaultProps
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
|
||||||
import org.bigbluebutton.core.api.EndMeeting
|
|
||||||
import org.bigbluebutton.core.bus.{ BigBlueButtonEvent, IncomingEventBus }
|
|
||||||
import org.bigbluebutton.core.util.TimeUtil
|
|
||||||
|
|
||||||
object MeetingInactivityTrackerHelper {
|
|
||||||
|
|
||||||
def isMeetingActive(
|
|
||||||
nowInMinutes: Long,
|
|
||||||
lastActivityTimeInMinutes: Long,
|
|
||||||
maxInactivityTimeoutMinutes: Long
|
|
||||||
): Boolean = {
|
|
||||||
nowInMinutes - lastActivityTimeInMinutes < maxInactivityTimeoutMinutes
|
|
||||||
}
|
|
||||||
|
|
||||||
def isMeetingInactive(
|
|
||||||
warningSent: Boolean,
|
|
||||||
nowInMinutes: Long,
|
|
||||||
lastActivityTimeInMinutes: Long,
|
|
||||||
maxInactivityTimeoutMinutes: Long
|
|
||||||
): Boolean = {
|
|
||||||
warningSent && (nowInMinutes - lastActivityTimeInMinutes) > maxInactivityTimeoutMinutes
|
|
||||||
}
|
|
||||||
|
|
||||||
def processMeetingInactivityAudit(
|
|
||||||
props: DefaultProps,
|
|
||||||
outGW: OutMessageGateway,
|
|
||||||
eventBus: IncomingEventBus,
|
|
||||||
tracker: MeetingInactivityTracker
|
|
||||||
): MeetingInactivityTracker = {
|
|
||||||
|
|
||||||
val nowInMinutes = TimeUtil.millisToMinutes(System.currentTimeMillis())
|
|
||||||
if (isMeetingActive(nowInMinutes, tracker.lastActivityTimeInMinutes, tracker.maxInactivityTimeoutMinutes)) {
|
|
||||||
tracker
|
|
||||||
} else {
|
|
||||||
if (isMeetingInactive(tracker.warningSent, nowInMinutes,
|
|
||||||
tracker.lastActivityTimeInMinutes,
|
|
||||||
tracker.maxInactivityTimeoutMinutes)) {
|
|
||||||
sendEndMeetingDueToInactivity(props, eventBus)
|
|
||||||
tracker
|
|
||||||
} else {
|
|
||||||
if (tracker.warningSent) {
|
|
||||||
tracker
|
|
||||||
} else {
|
|
||||||
warnOfMeetingInactivity(props, outGW, nowInMinutes, tracker)
|
|
||||||
tracker.modify(_.warningSent).setTo(true).modify(_.warningSentOnTimeInMinutes).setTo(nowInMinutes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def timeLeftInMinutes(nowInMinutes: Long, tracker: MeetingInactivityTracker): Long = {
|
|
||||||
tracker.lastActivityTimeInMinutes + tracker.maxInactivityTimeoutMinutes - nowInMinutes
|
|
||||||
}
|
|
||||||
|
|
||||||
def warnOfMeetingInactivity(props: DefaultProps, outGW: OutMessageGateway,
|
|
||||||
nowInMinutes: Long, tracker: MeetingInactivityTracker): MeetingInactivityTracker = {
|
|
||||||
val timeLeftSeconds = TimeUtil.minutesToSeconds(timeLeftInMinutes(nowInMinutes, tracker))
|
|
||||||
sendMeetingInactivityWarning(props, outGW, timeLeftSeconds)
|
|
||||||
tracker
|
|
||||||
}
|
|
||||||
|
|
||||||
def sendEndMeetingDueToInactivity(props: DefaultProps, eventBus: IncomingEventBus): Unit = {
|
|
||||||
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, EndMeeting(props.meetingProp.intId)))
|
|
||||||
}
|
|
||||||
|
|
||||||
def sendMeetingInactivityWarning(props: DefaultProps, outGW: OutMessageGateway, timeLeftSeconds: Long): Unit = {
|
|
||||||
def build(meetingId: String, timeLeftInSec: Long): BbbCommonEnvCoreMsg = {
|
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
|
||||||
val envelope = BbbCoreEnvelope(MeetingInactivityWarningEvtMsg.NAME, routing)
|
|
||||||
val body = MeetingInactivityWarningEvtMsgBody(timeLeftInSec)
|
|
||||||
val header = BbbClientMsgHeader(MeetingInactivityWarningEvtMsg.NAME, meetingId, "not-used")
|
|
||||||
val event = MeetingInactivityWarningEvtMsg(header, body)
|
|
||||||
|
|
||||||
BbbCommonEnvCoreMsg(envelope, event)
|
|
||||||
}
|
|
||||||
|
|
||||||
val event = build(props.meetingProp.intId, timeLeftSeconds)
|
|
||||||
outGW.send(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
def processMeetingActivityResponse(
|
|
||||||
props: DefaultProps,
|
|
||||||
outGW: OutMessageGateway,
|
|
||||||
msg: MeetingActivityResponseCmdMsg,
|
|
||||||
tracker: MeetingInactivityTracker
|
|
||||||
): MeetingInactivityTracker = {
|
|
||||||
|
|
||||||
def buildMeetingIsActiveEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
|
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
|
||||||
val envelope = BbbCoreEnvelope(MeetingIsActiveEvtMsg.NAME, routing)
|
|
||||||
val body = MeetingIsActiveEvtMsgBody(meetingId)
|
|
||||||
val header = BbbClientMsgHeader(MeetingIsActiveEvtMsg.NAME, meetingId, "not-used")
|
|
||||||
val event = MeetingIsActiveEvtMsg(header, body)
|
|
||||||
|
|
||||||
BbbCommonEnvCoreMsg(envelope, event)
|
|
||||||
}
|
|
||||||
|
|
||||||
val event = buildMeetingIsActiveEvtMsg(props.meetingProp.intId)
|
|
||||||
outGW.send(event)
|
|
||||||
|
|
||||||
tracker.modify(_.warningSent).setTo(false)
|
|
||||||
.modify(_.warningSentOnTimeInMinutes).setTo(0L)
|
|
||||||
.modify(_.lastActivityTimeInMinutes).setTo(System.currentTimeMillis())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
package org.bigbluebutton.core.running
|
package org.bigbluebutton.core.running
|
||||||
|
|
||||||
import akka.actor.ActorContext
|
import akka.actor.ActorContext
|
||||||
import org.bigbluebutton.common2.domain.{ DefaultProps }
|
import org.bigbluebutton.common2.domain.DefaultProps
|
||||||
import org.bigbluebutton.core.apps._
|
import org.bigbluebutton.core.apps._
|
||||||
import org.bigbluebutton.core.bus._
|
import org.bigbluebutton.core.bus._
|
||||||
import org.bigbluebutton.core.models._
|
import org.bigbluebutton.core.models._
|
||||||
|
@ -3,6 +3,7 @@ package org.bigbluebutton.core.util
|
|||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
object TimeUtil {
|
object TimeUtil {
|
||||||
|
|
||||||
def minutesToMillis(minutes: Long): Long = {
|
def minutesToMillis(minutes: Long): Long = {
|
||||||
TimeUnit.MINUTES.toMillis(minutes)
|
TimeUnit.MINUTES.toMillis(minutes)
|
||||||
}
|
}
|
||||||
@ -14,4 +15,7 @@ object TimeUtil {
|
|||||||
def minutesToSeconds(minutes: Long): Long = {
|
def minutesToSeconds(minutes: Long): Long = {
|
||||||
TimeUnit.MINUTES.toSeconds(minutes)
|
TimeUnit.MINUTES.toSeconds(minutes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def timeNowInMinutes(): Long = TimeUnit.NANOSECONDS.toMinutes(System.nanoTime())
|
||||||
|
def timeNowInSeconds(): Long = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime())
|
||||||
}
|
}
|
||||||
|
@ -39,9 +39,6 @@ object MeetingStatus2x {
|
|||||||
def recordingStarted(status: MeetingStatus2x) = status.recording = true
|
def recordingStarted(status: MeetingStatus2x) = status.recording = true
|
||||||
def recordingStopped(status: MeetingStatus2x) = status.recording = false
|
def recordingStopped(status: MeetingStatus2x) = status.recording = false
|
||||||
def isRecording(status: MeetingStatus2x): Boolean = status.recording
|
def isRecording(status: MeetingStatus2x): Boolean = status.recording
|
||||||
def lastWebUserLeft(status: MeetingStatus2x) = status.lastWebUserLeftOnTimestamp = MeetingStatus2x.timeNowInMinutes
|
|
||||||
def lastWebUserLeftOn(status: MeetingStatus2x): Long = status.lastWebUserLeftOnTimestamp
|
|
||||||
def resetLastWebUserLeftOn(status: MeetingStatus2x) = status.lastWebUserLeftOnTimestamp = 0
|
|
||||||
def setVoiceRecordingFilename(status: MeetingStatus2x, path: String) = status.voiceRecordingFilename = path
|
def setVoiceRecordingFilename(status: MeetingStatus2x, path: String) = status.voiceRecordingFilename = path
|
||||||
def getVoiceRecordingFilename(status: MeetingStatus2x): String = status.voiceRecordingFilename
|
def getVoiceRecordingFilename(status: MeetingStatus2x): String = status.voiceRecordingFilename
|
||||||
def permisionsInitialized(status: MeetingStatus2x): Boolean = status.permissionsInited
|
def permisionsInitialized(status: MeetingStatus2x): Boolean = status.permissionsInited
|
||||||
@ -57,10 +54,6 @@ object MeetingStatus2x {
|
|||||||
def timeNowInMinutes(status: MeetingStatus2x): Long = TimeUnit.NANOSECONDS.toMinutes(System.nanoTime())
|
def timeNowInMinutes(status: MeetingStatus2x): Long = TimeUnit.NANOSECONDS.toMinutes(System.nanoTime())
|
||||||
def timeNowInSeconds(status: MeetingStatus2x): Long = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime())
|
def timeNowInSeconds(status: MeetingStatus2x): Long = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime())
|
||||||
|
|
||||||
def startedOn(status: MeetingStatus2x): Long = status.startedOn
|
|
||||||
|
|
||||||
def timeNowInMinutes(): Long = TimeUnit.NANOSECONDS.toMinutes(System.nanoTime())
|
|
||||||
def timeNowInSeconds(): Long = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MeetingStatus2x {
|
class MeetingStatus2x {
|
||||||
@ -75,15 +68,10 @@ class MeetingStatus2x {
|
|||||||
private var meetingEnded = false
|
private var meetingEnded = false
|
||||||
private var meetingMuted = false
|
private var meetingMuted = false
|
||||||
|
|
||||||
private var hasLastWebUserLeft = false
|
|
||||||
private var lastWebUserLeftOnTimestamp: Long = 0
|
|
||||||
|
|
||||||
private var voiceRecordingFilename: String = ""
|
private var voiceRecordingFilename: String = ""
|
||||||
|
|
||||||
private var extension = new MeetingExtensionProp
|
private var extension = new MeetingExtensionProp
|
||||||
|
|
||||||
private val startedOn = MeetingStatus2x.timeNowInSeconds;
|
|
||||||
|
|
||||||
private def startRecordingVoice() {
|
private def startRecordingVoice() {
|
||||||
recordingVoice = true
|
recordingVoice = true
|
||||||
}
|
}
|
||||||
@ -115,9 +103,7 @@ class MeetingStatus2x {
|
|||||||
private def recordingStarted() = recording = true
|
private def recordingStarted() = recording = true
|
||||||
private def recordingStopped() = recording = false
|
private def recordingStopped() = recording = false
|
||||||
private def isRecording(): Boolean = recording
|
private def isRecording(): Boolean = recording
|
||||||
private def lastWebUserLeft() = lastWebUserLeftOnTimestamp = MeetingStatus2x.timeNowInMinutes
|
|
||||||
private def lastWebUserLeftOn(): Long = lastWebUserLeftOnTimestamp
|
|
||||||
private def resetLastWebUserLeftOn() = lastWebUserLeftOnTimestamp = 0
|
|
||||||
private def setVoiceRecordingFilename(path: String) = voiceRecordingFilename = path
|
private def setVoiceRecordingFilename(path: String) = voiceRecordingFilename = path
|
||||||
private def getVoiceRecordingFilename(): String = voiceRecordingFilename
|
private def getVoiceRecordingFilename(): String = voiceRecordingFilename
|
||||||
private def permisionsInitialized(): Boolean = permissionsInited
|
private def permisionsInitialized(): Boolean = permissionsInited
|
||||||
|
@ -2,10 +2,11 @@ package org.bigbluebutton.core2.message.handlers
|
|||||||
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
import org.bigbluebutton.core.api.{ SendTimeRemainingUpdate }
|
import org.bigbluebutton.core.api.SendTimeRemainingUpdate
|
||||||
|
import org.bigbluebutton.core.domain.{ MeetingExpiryTracker, MeetingState2x }
|
||||||
import org.bigbluebutton.core.models.BreakoutRooms
|
import org.bigbluebutton.core.models.BreakoutRooms
|
||||||
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting }
|
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting }
|
||||||
import org.bigbluebutton.core2.MeetingStatus2x
|
import org.bigbluebutton.core.util.TimeUtil
|
||||||
|
|
||||||
trait SendTimeRemainingUpdateHdlr {
|
trait SendTimeRemainingUpdateHdlr {
|
||||||
this: BaseMeetingActor =>
|
this: BaseMeetingActor =>
|
||||||
@ -13,10 +14,11 @@ trait SendTimeRemainingUpdateHdlr {
|
|||||||
val liveMeeting: LiveMeeting
|
val liveMeeting: LiveMeeting
|
||||||
val outGW: OutMessageGateway
|
val outGW: OutMessageGateway
|
||||||
|
|
||||||
def handleSendTimeRemainingUpdate(msg: SendTimeRemainingUpdate) {
|
def handleSendTimeRemainingUpdate(msg: SendTimeRemainingUpdate, state: MeetingState2x): MeetingState2x = {
|
||||||
|
|
||||||
if (liveMeeting.props.durationProps.duration > 0) {
|
if (liveMeeting.props.durationProps.duration > 0) {
|
||||||
val endMeetingTime = MeetingStatus2x.startedOn(liveMeeting.status) + (liveMeeting.props.durationProps.duration * 60)
|
val endMeetingTime = MeetingExpiryTracker.endMeetingTime(state)
|
||||||
val timeRemaining = endMeetingTime - liveMeeting.timeNowInSeconds
|
val timeRemaining = endMeetingTime - TimeUtil.timeNowInSeconds
|
||||||
|
|
||||||
def buildMeetingTimeRemainingUpdateEvtMsg(meetingId: String, timeLeftInSec: Long): BbbCommonEnvCoreMsg = {
|
def buildMeetingTimeRemainingUpdateEvtMsg(meetingId: String, timeLeftInSec: Long): BbbCommonEnvCoreMsg = {
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
||||||
@ -34,7 +36,7 @@ trait SendTimeRemainingUpdateHdlr {
|
|||||||
if (!liveMeeting.props.meetingProp.isBreakout && !BreakoutRooms.getRooms(liveMeeting.breakoutRooms).isEmpty) {
|
if (!liveMeeting.props.meetingProp.isBreakout && !BreakoutRooms.getRooms(liveMeeting.breakoutRooms).isEmpty) {
|
||||||
val endMeetingTime = BreakoutRooms.breakoutRoomsStartedOn(liveMeeting.breakoutRooms) +
|
val endMeetingTime = BreakoutRooms.breakoutRoomsStartedOn(liveMeeting.breakoutRooms) +
|
||||||
(BreakoutRooms.breakoutRoomsdurationInMinutes(liveMeeting.breakoutRooms) * 60)
|
(BreakoutRooms.breakoutRoomsdurationInMinutes(liveMeeting.breakoutRooms) * 60)
|
||||||
val timeRemaining = endMeetingTime - liveMeeting.timeNowInSeconds
|
val timeRemaining = endMeetingTime - TimeUtil.timeNowInSeconds
|
||||||
|
|
||||||
def buildBreakoutRoomsTimeRemainingUpdateEvtMsg(meetingId: String, timeLeftInSec: Long): BbbCommonEnvCoreMsg = {
|
def buildBreakoutRoomsTimeRemainingUpdateEvtMsg(meetingId: String, timeLeftInSec: Long): BbbCommonEnvCoreMsg = {
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
||||||
@ -53,6 +55,8 @@ trait SendTimeRemainingUpdateHdlr {
|
|||||||
BreakoutRooms.breakoutRoomsdurationInMinutes(liveMeeting.breakoutRooms, 0)
|
BreakoutRooms.breakoutRoomsdurationInMinutes(liveMeeting.breakoutRooms, 0)
|
||||||
BreakoutRooms.breakoutRoomsStartedOn(liveMeeting.breakoutRooms, 0)
|
BreakoutRooms.breakoutRoomsStartedOn(liveMeeting.breakoutRooms, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package org.bigbluebutton.core2.message.handlers.guests
|
||||||
|
|
||||||
|
import org.bigbluebutton.common2.msgs._
|
||||||
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
|
import org.bigbluebutton.core.models.{ GuestWaiting, GuestsWaiting, Roles, Users2x }
|
||||||
|
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting }
|
||||||
|
import org.bigbluebutton.core2.message.senders.{ MsgBuilder, Sender }
|
||||||
|
|
||||||
|
trait GetGuestPolicyReqMsgHdlr {
|
||||||
|
this: BaseMeetingActor =>
|
||||||
|
|
||||||
|
val liveMeeting: LiveMeeting
|
||||||
|
val outGW: OutMessageGateway
|
||||||
|
|
||||||
|
def handleGetGuestPolicyReqMsg(msg: GetGuestPolicyReqMsg): Unit = {
|
||||||
|
val event = buildGetGuestPolicyRespMsg(liveMeeting.props.meetingProp.intId, msg.body.requestedBy,
|
||||||
|
liveMeeting.guestsWaiting.getGuestPolicy().policy)
|
||||||
|
outGW.send(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
def buildGetGuestPolicyRespMsg(meetingId: String, userId: String, policy: String): BbbCommonEnvCoreMsg = {
|
||||||
|
val routing = Routing.addMsgToClientRouting(MessageTypes.DIRECT, meetingId, userId)
|
||||||
|
val envelope = BbbCoreEnvelope(GetGuestPolicyRespMsg.NAME, routing)
|
||||||
|
val header = BbbClientMsgHeader(GetGuestPolicyRespMsg.NAME, meetingId, userId)
|
||||||
|
val body = GetGuestPolicyRespMsgBody(policy)
|
||||||
|
val event = GetGuestPolicyRespMsg(header, body)
|
||||||
|
BbbCommonEnvCoreMsg(envelope, event)
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package org.bigbluebutton.core2.message.handlers.guests
|
package org.bigbluebutton.core2.message.handlers.guests
|
||||||
|
|
||||||
import org.bigbluebutton.common2.msgs.SetGuestPolicyMsg
|
import org.bigbluebutton.common2.msgs.{ SetGuestPolicyCmdMsg }
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
import org.bigbluebutton.core.models.{ GuestPolicy, GuestPolicyType, GuestWaiting, GuestsWaiting }
|
import org.bigbluebutton.core.models.{ GuestPolicy, GuestPolicyType, GuestWaiting, GuestsWaiting }
|
||||||
import org.bigbluebutton.core.running.{ BaseMeetingActor, HandlerHelpers, LiveMeeting }
|
import org.bigbluebutton.core.running.{ BaseMeetingActor, HandlerHelpers, LiveMeeting }
|
||||||
@ -12,7 +12,7 @@ trait SetGuestPolicyMsgHdlr {
|
|||||||
val liveMeeting: LiveMeeting
|
val liveMeeting: LiveMeeting
|
||||||
val outGW: OutMessageGateway
|
val outGW: OutMessageGateway
|
||||||
|
|
||||||
def handleSetGuestPolicyMsg(msg: SetGuestPolicyMsg): Unit = {
|
def handleSetGuestPolicyMsg(msg: SetGuestPolicyCmdMsg): Unit = {
|
||||||
val newPolicy = msg.body.policy.toUpperCase()
|
val newPolicy = msg.body.policy.toUpperCase()
|
||||||
if (GuestPolicyType.policyTypes.contains(newPolicy)) {
|
if (GuestPolicyType.policyTypes.contains(newPolicy)) {
|
||||||
val policy = GuestPolicy(newPolicy, msg.body.setBy)
|
val policy = GuestPolicy(newPolicy, msg.body.setBy)
|
||||||
|
1
akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/meeting/DestroyMeetingSysCmdMsgHdlr.scala
Normal file → Executable file
1
akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/handlers/meeting/DestroyMeetingSysCmdMsgHdlr.scala
Normal file → Executable file
@ -3,7 +3,6 @@ package org.bigbluebutton.core2.message.handlers.meeting
|
|||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting }
|
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting }
|
||||||
import org.bigbluebutton.core2.MeetingStatus2x
|
|
||||||
import org.bigbluebutton.core2.message.senders.MsgBuilder
|
import org.bigbluebutton.core2.message.senders.MsgBuilder
|
||||||
|
|
||||||
trait DestroyMeetingSysCmdMsgHdlr {
|
trait DestroyMeetingSysCmdMsgHdlr {
|
||||||
|
@ -2,24 +2,19 @@ package org.bigbluebutton.core2.message.handlers.meeting
|
|||||||
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
import org.bigbluebutton.common2.msgs._
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
import org.bigbluebutton.core.OutMessageGateway
|
||||||
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting }
|
import org.bigbluebutton.core.bus.IncomingEventBus
|
||||||
import org.bigbluebutton.core2.MeetingStatus2x
|
import org.bigbluebutton.core.domain.MeetingEndReason
|
||||||
import org.bigbluebutton.core2.message.senders.MsgBuilder
|
import org.bigbluebutton.core.running.{ BaseMeetingActor, HandlerHelpers, LiveMeeting }
|
||||||
|
|
||||||
trait EndMeetingSysCmdMsgHdlr {
|
trait EndMeetingSysCmdMsgHdlr extends HandlerHelpers {
|
||||||
this: BaseMeetingActor =>
|
this: BaseMeetingActor =>
|
||||||
|
|
||||||
val liveMeeting: LiveMeeting
|
val liveMeeting: LiveMeeting
|
||||||
val outGW: OutMessageGateway
|
val outGW: OutMessageGateway
|
||||||
|
val eventBus: IncomingEventBus
|
||||||
|
|
||||||
def handleEndMeeting(msg: EndMeetingSysCmdMsg) {
|
def handleEndMeeting(msg: EndMeetingSysCmdMsg) {
|
||||||
// Broadcast users the meeting will end
|
sendEndMeetingDueToExpiry(MeetingEndReason.ENDED_FROM_API, eventBus, outGW, liveMeeting)
|
||||||
outGW.send(MsgBuilder.buildMeetingEndingEvtMsg(liveMeeting.props.meetingProp.intId))
|
|
||||||
|
|
||||||
MeetingStatus2x.meetingHasEnded(liveMeeting.status)
|
|
||||||
|
|
||||||
// Sent from akka-apps to bbb-web to inform about end of meeting
|
|
||||||
outGW.send(MsgBuilder.buildMeetingEndedEvtMsg(liveMeeting.props.meetingProp.intId))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
package org.bigbluebutton.core2.message.handlers.users
|
|
||||||
|
|
||||||
import org.bigbluebutton.common2.msgs.UserJoinMeetingReqMsg
|
|
||||||
import org.bigbluebutton.core.{ OutMessageGateway }
|
|
||||||
import org.bigbluebutton.core.running.{ HandlerHelpers, LiveMeeting, BaseMeetingActor }
|
|
||||||
|
|
||||||
trait UserJoinMeetingReqMsgHdlr extends HandlerHelpers {
|
|
||||||
this: BaseMeetingActor =>
|
|
||||||
|
|
||||||
val liveMeeting: LiveMeeting
|
|
||||||
val outGW: OutMessageGateway
|
|
||||||
|
|
||||||
def handleUserJoinMeetingReqMsg(msg: UserJoinMeetingReqMsg): Unit = {
|
|
||||||
userJoinMeeting(outGW, msg.body.authToken, liveMeeting)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
|||||||
package org.bigbluebutton.core2.message.handlers.users
|
|
||||||
|
|
||||||
import org.bigbluebutton.common2.domain.VoiceUserVO
|
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
|
||||||
import org.bigbluebutton.core.api._
|
|
||||||
import org.bigbluebutton.core.models._
|
|
||||||
import org.bigbluebutton.core.running.MeetingActor
|
|
||||||
import org.bigbluebutton.core2.MeetingStatus2x
|
|
||||||
|
|
||||||
trait UserJoiningHdlr {
|
|
||||||
this: MeetingActor =>
|
|
||||||
|
|
||||||
val outGW: OutMessageGateway
|
|
||||||
def handleUserJoin(msg: UserJoining): Unit = {
|
|
||||||
log.debug("Received user joined meeting. metingId=" + props.meetingProp.intId + " userId=" + msg.userID)
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
for {
|
|
||||||
uvo <- Users.newUser(msg.userID, lockStatus, ru, waitingForAcceptance, vu, liveMeeting.users)
|
|
||||||
} yield {
|
|
||||||
log.info("User joined meeting. metingId=" + props.meetingProp.intId + " userId=" + uvo.id + " user=" + uvo)
|
|
||||||
|
|
||||||
if (uvo.guest && MeetingStatus2x.getGuestPolicy(liveMeeting.status) == GuestPolicy.ALWAYS_DENY) {
|
|
||||||
outGW.send(new GuestAccessDenied(props.meetingProp.intId, props.recordProp.record, uvo.id))
|
|
||||||
} else {
|
|
||||||
outGW.send(new UserJoined(props.meetingProp.intId, props.recordProp.record, uvo))
|
|
||||||
outGW.send(new MeetingState(props.meetingProp.intId, props.recordProp.record, uvo.id,
|
|
||||||
MeetingStatus2x.getPermissions(liveMeeting.status), MeetingStatus2x.isMeetingMuted(liveMeeting.status)))
|
|
||||||
|
|
||||||
if (!waitingForAcceptance) {
|
|
||||||
// Become presenter if the only moderator
|
|
||||||
if ((Users.numModerators(liveMeeting.users) == 1) || (Users.hasNoPresenter(liveMeeting.users))) {
|
|
||||||
if (ru.role == Roles.MODERATOR_ROLE) {
|
|
||||||
log.info("Assigning presenter to lone moderator. metingId=" + props.meetingProp.intId + " userId=" + uvo.id)
|
|
||||||
assignNewPresenter(msg.userID, ru.name, msg.userID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.info("User waiting for acceptance. metingId=" + props.meetingProp.intId + " userId=" + uvo.id)
|
|
||||||
}
|
|
||||||
liveMeeting.webUserJoined
|
|
||||||
startRecordingIfAutoStart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
package org.bigbluebutton.core2.message.handlers.users
|
|
||||||
|
|
||||||
import org.bigbluebutton.common2.msgs._
|
|
||||||
import org.bigbluebutton.core.OutMessageGateway
|
|
||||||
import org.bigbluebutton.core.apps.users.UsersApp
|
|
||||||
import org.bigbluebutton.core.models._
|
|
||||||
import org.bigbluebutton.core.running.{ HandlerHelpers, LiveMeeting }
|
|
||||||
|
|
||||||
trait ValidateAuthTokenReqMsgHdlr extends HandlerHelpers {
|
|
||||||
this: UsersApp =>
|
|
||||||
|
|
||||||
val liveMeeting: LiveMeeting
|
|
||||||
val outGW: OutMessageGateway
|
|
||||||
|
|
||||||
def handleValidateAuthTokenReqMsg(msg: ValidateAuthTokenReqMsg): Unit = {
|
|
||||||
log.debug("RECEIVED ValidateAuthTokenReqMsg msg {}", msg)
|
|
||||||
|
|
||||||
RegisteredUsers.getRegisteredUserWithToken(msg.body.authToken, msg.body.userId, liveMeeting.registeredUsers) match {
|
|
||||||
case Some(u) =>
|
|
||||||
val guestPolicyType = GuestsWaiting.getGuestPolicy(liveMeeting.guestsWaiting).policy
|
|
||||||
if (guestPolicyType == GuestPolicyType.ALWAYS_ACCEPT) {
|
|
||||||
userValidatedAndNoNeedToWaitForApproval(outGW, liveMeeting, u)
|
|
||||||
} else if (guestPolicyType == GuestPolicyType.ASK_MODERATOR) {
|
|
||||||
if (u.guest && u.waitingForAcceptance) {
|
|
||||||
userValidatedButNeedToWaitForApproval(outGW, liveMeeting, u)
|
|
||||||
} else {
|
|
||||||
userValidatedAndNoNeedToWaitForApproval(outGW, liveMeeting, u)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
validateTokenFailed(outGW, meetingId = liveMeeting.props.meetingProp.intId,
|
|
||||||
userId = msg.body.userId, authToken = msg.body.authToken, valid = false, waitForApproval = false)
|
|
||||||
// TODO: Disconnect user
|
|
||||||
}
|
|
||||||
case None =>
|
|
||||||
validateTokenFailed(outGW, meetingId = liveMeeting.props.meetingProp.intId,
|
|
||||||
userId = msg.body.userId, authToken = msg.body.authToken, valid = false, waitForApproval = false)
|
|
||||||
// TODO: Disconnect user
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -227,26 +227,6 @@ object MsgBuilder {
|
|||||||
BbbCommonEnvCoreMsg(envelope, event)
|
BbbCommonEnvCoreMsg(envelope, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
def buildMeetingEndingEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
|
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
|
|
||||||
val envelope = BbbCoreEnvelope(MeetingEndingEvtMsg.NAME, routing)
|
|
||||||
val body = MeetingEndingEvtMsgBody(meetingId)
|
|
||||||
val header = BbbClientMsgHeader(MeetingEndingEvtMsg.NAME, meetingId, "not-used")
|
|
||||||
val event = MeetingEndingEvtMsg(header, body)
|
|
||||||
|
|
||||||
BbbCommonEnvCoreMsg(envelope, event)
|
|
||||||
}
|
|
||||||
|
|
||||||
def buildMeetingEndedEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
|
|
||||||
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
|
|
||||||
val envelope = BbbCoreEnvelope(MeetingEndedEvtMsg.NAME, routing)
|
|
||||||
val body = MeetingEndedEvtMsgBody(meetingId)
|
|
||||||
val header = BbbCoreBaseHeader(MeetingEndedEvtMsg.NAME)
|
|
||||||
val event = MeetingEndedEvtMsg(header, body)
|
|
||||||
|
|
||||||
BbbCommonEnvCoreMsg(envelope, event)
|
|
||||||
}
|
|
||||||
|
|
||||||
def buildBreakoutRoomEndedEvtMsg(meetingId: String, userId: String, breakoutRoomId: String): BbbCommonEnvCoreMsg = {
|
def buildBreakoutRoomEndedEvtMsg(meetingId: String, userId: String, breakoutRoomId: String): BbbCommonEnvCoreMsg = {
|
||||||
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
|
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
|
||||||
val envelope = BbbCoreEnvelope(BreakoutRoomEndedEvtMsg.NAME, routing)
|
val envelope = BbbCoreEnvelope(BreakoutRoomEndedEvtMsg.NAME, routing)
|
||||||
|
@ -9,14 +9,25 @@ import org.bigbluebutton.core.running.LiveMeeting
|
|||||||
trait FakeTestData {
|
trait FakeTestData {
|
||||||
|
|
||||||
def createFakeUsers(liveMeeting: LiveMeeting): Unit = {
|
def createFakeUsers(liveMeeting: LiveMeeting): Unit = {
|
||||||
createUserVoiceAndCam(liveMeeting, Roles.MODERATOR_ROLE, false, false, CallingWith.WEBRTC, muted = false,
|
val mod1 = createUserVoiceAndCam(liveMeeting, Roles.MODERATOR_ROLE, false, false, CallingWith.WEBRTC, muted = false,
|
||||||
talking = true, listenOnly = false)
|
talking = true, listenOnly = false)
|
||||||
createUserVoiceAndCam(liveMeeting, Roles.MODERATOR_ROLE, guest = true, authed = true, CallingWith.WEBRTC, muted = false,
|
Users2x.add(liveMeeting.users2x, mod1)
|
||||||
|
|
||||||
|
val mod2 = createUserVoiceAndCam(liveMeeting, Roles.MODERATOR_ROLE, guest = false, authed = true, CallingWith.WEBRTC, muted = false,
|
||||||
talking = false, listenOnly = false)
|
talking = false, listenOnly = false)
|
||||||
createUserVoiceAndCam(liveMeeting, Roles.VIEWER_ROLE, guest = true, authed = true, CallingWith.WEBRTC, muted = false,
|
Users2x.add(liveMeeting.users2x, mod2)
|
||||||
|
|
||||||
|
val guest1 = createUserVoiceAndCam(liveMeeting, Roles.VIEWER_ROLE, guest = true, authed = true, CallingWith.WEBRTC, muted = false,
|
||||||
talking = false, listenOnly = false)
|
talking = false, listenOnly = false)
|
||||||
createUserVoiceAndCam(liveMeeting, Roles.VIEWER_ROLE, guest = true, authed = true, CallingWith.FLASH, muted = false,
|
Users2x.add(liveMeeting.users2x, guest1)
|
||||||
|
val guestWait1 = GuestWaiting(guest1.intId, guest1.name, guest1.role)
|
||||||
|
GuestsWaiting.add(liveMeeting.guestsWaiting, guestWait1)
|
||||||
|
|
||||||
|
val guest2 = createUserVoiceAndCam(liveMeeting, Roles.VIEWER_ROLE, guest = true, authed = true, CallingWith.FLASH, muted = false,
|
||||||
talking = false, listenOnly = false)
|
talking = false, listenOnly = false)
|
||||||
|
Users2x.add(liveMeeting.users2x, guest2)
|
||||||
|
val guestWait2 = GuestWaiting(guest2.intId, guest2.name, guest2.role)
|
||||||
|
GuestsWaiting.add(liveMeeting.guestsWaiting, guestWait2)
|
||||||
|
|
||||||
val vu1 = FakeUserGenerator.createFakeVoiceOnlyUser(CallingWith.PHONE, muted = false, talking = false, listenOnly = false)
|
val vu1 = FakeUserGenerator.createFakeVoiceOnlyUser(CallingWith.PHONE, muted = false, talking = false, listenOnly = false)
|
||||||
VoiceUsers.add(liveMeeting.voiceUsers, vu1)
|
VoiceUsers.add(liveMeeting.voiceUsers, vu1)
|
||||||
@ -33,7 +44,7 @@ trait FakeTestData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def createUserVoiceAndCam(liveMeeting: LiveMeeting, role: String, guest: Boolean, authed: Boolean, callingWith: String,
|
def createUserVoiceAndCam(liveMeeting: LiveMeeting, role: String, guest: Boolean, authed: Boolean, callingWith: String,
|
||||||
muted: Boolean, talking: Boolean, listenOnly: Boolean): Unit = {
|
muted: Boolean, talking: Boolean, listenOnly: Boolean): UserState = {
|
||||||
|
|
||||||
val ruser1 = FakeUserGenerator.createFakeRegisteredUser(liveMeeting.registeredUsers, Roles.MODERATOR_ROLE, true, false)
|
val ruser1 = FakeUserGenerator.createFakeRegisteredUser(liveMeeting.registeredUsers, Roles.MODERATOR_ROLE, true, false)
|
||||||
|
|
||||||
@ -49,10 +60,10 @@ trait FakeTestData {
|
|||||||
createFakeUser(liveMeeting, ruser1)
|
createFakeUser(liveMeeting, ruser1)
|
||||||
}
|
}
|
||||||
|
|
||||||
def createFakeUser(liveMeeting: LiveMeeting, regUser: RegisteredUser): Unit = {
|
def createFakeUser(liveMeeting: LiveMeeting, regUser: RegisteredUser): UserState = {
|
||||||
val u = UserState(intId = regUser.id, extId = regUser.externId, name = regUser.name, role = regUser.role,
|
UserState(intId = regUser.id, extId = regUser.externId, name = regUser.name, role = regUser.role,
|
||||||
guest = regUser.guest, authed = regUser.authed, waitingForAcceptance = regUser.waitingForAcceptance,
|
guest = regUser.guest, authed = regUser.authed, waitingForAcceptance = regUser.waitingForAcceptance,
|
||||||
emoji = "none", locked = false, presenter = false, avatar = regUser.avatarURL)
|
emoji = "none", locked = false, presenter = false, avatar = regUser.avatarURL)
|
||||||
Users2x.add(liveMeeting.users2x, u)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,8 +53,10 @@ object FakeUserGenerator {
|
|||||||
val avatarURL = "https://www." + RandomStringGenerator.randomAlphanumericString(32) + ".com/" +
|
val avatarURL = "https://www." + RandomStringGenerator.randomAlphanumericString(32) + ".com/" +
|
||||||
RandomStringGenerator.randomAlphanumericString(10) + ".png"
|
RandomStringGenerator.randomAlphanumericString(10) + ".png"
|
||||||
|
|
||||||
RegisteredUsers.create(userId = id, extId, name, role,
|
val ru = RegisteredUsers.create(userId = id, extId, name, role,
|
||||||
authToken, avatarURL, guest, authed, waitingForAcceptance = true, users)
|
authToken, avatarURL, guest, authed, waitingForAcceptance = true)
|
||||||
|
RegisteredUsers.add(users, ru)
|
||||||
|
ru
|
||||||
}
|
}
|
||||||
|
|
||||||
def createFakeVoiceUser(user: RegisteredUser, callingWith: String, muted: Boolean, talking: Boolean,
|
def createFakeVoiceUser(user: RegisteredUser, callingWith: String, muted: Boolean, talking: Boolean,
|
||||||
|
@ -9,12 +9,10 @@ case class DisconnectAllConnections(scope: String) extends SystemMessage
|
|||||||
class MsgToClientGW(val connInvokerService: IConnectionInvokerService) {
|
class MsgToClientGW(val connInvokerService: IConnectionInvokerService) {
|
||||||
|
|
||||||
def broadcastToMeeting(msg: BroadcastToMeetingMsg): Unit = {
|
def broadcastToMeeting(msg: BroadcastToMeetingMsg): Unit = {
|
||||||
//println("**** MsgToClientGW broadcastToMeeting " + msg.json)
|
|
||||||
connInvokerService.sendMessage(msg)
|
connInvokerService.sendMessage(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
def directToClient(msg: DirectToClientMsg): Unit = {
|
def directToClient(msg: DirectToClientMsg): Unit = {
|
||||||
//println("**** MsgToClientGW directToClient " + msg.json)
|
|
||||||
connInvokerService.sendMessage(msg)
|
connInvokerService.sendMessage(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ object GetGuestsWaitingApprovalReqMsg {
|
|||||||
val NAME = "GetGuestsWaitingApprovalReqMsg"
|
val NAME = "GetGuestsWaitingApprovalReqMsg"
|
||||||
}
|
}
|
||||||
case class GetGuestsWaitingApprovalReqMsg(header: BbbClientMsgHeader,
|
case class GetGuestsWaitingApprovalReqMsg(header: BbbClientMsgHeader,
|
||||||
body: GetGuestsWaitingApprovalReqMsgBody) extends BbbCoreMsg
|
body: GetGuestsWaitingApprovalReqMsgBody) extends StandardMsg
|
||||||
case class GetGuestsWaitingApprovalReqMsgBody(requesterId: String)
|
case class GetGuestsWaitingApprovalReqMsgBody(requesterId: String)
|
||||||
|
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ object GuestsWaitingApprovedMsg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case class GuestsWaitingApprovedMsg(header: BbbClientMsgHeader,
|
case class GuestsWaitingApprovedMsg(header: BbbClientMsgHeader,
|
||||||
body: GuestsWaitingApprovedMsgBody) extends BbbCoreMsg
|
body: GuestsWaitingApprovedMsgBody) extends StandardMsg
|
||||||
|
|
||||||
case class GuestsWaitingApprovedMsgBody(guests: Vector[GuestApprovedVO], approvedBy: String)
|
case class GuestsWaitingApprovedMsgBody(guests: Vector[GuestApprovedVO], approvedBy: String)
|
||||||
case class GuestApprovedVO(guest: String, approved: Boolean)
|
case class GuestApprovedVO(guest: String, approved: Boolean)
|
||||||
@ -76,12 +76,12 @@ case class GuestApprovedEvtMsgBody(approved: Boolean, approvedBy: String)
|
|||||||
/**
|
/**
|
||||||
* Message from user to set the guest policy.
|
* Message from user to set the guest policy.
|
||||||
*/
|
*/
|
||||||
object SetGuestPolicyMsg {
|
object SetGuestPolicyCmdMsg {
|
||||||
val NAME = "SetGuestPolicyMsg"
|
val NAME = "SetGuestPolicyCmdMsg"
|
||||||
}
|
}
|
||||||
case class SetGuestPolicyMsg(header: BbbClientMsgHeader,
|
case class SetGuestPolicyCmdMsg(header: BbbClientMsgHeader,
|
||||||
body: SetGuestPolicyMsgBody) extends BbbCoreMsg
|
body: SetGuestPolicyCmdMsgBody) extends StandardMsg
|
||||||
case class SetGuestPolicyMsgBody(policy: String, setBy: String)
|
case class SetGuestPolicyCmdMsgBody(policy: String, setBy: String)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message sent to all clients that guest policy has been changed.
|
* Message sent to all clients that guest policy has been changed.
|
||||||
@ -94,6 +94,18 @@ case class GuestPolicyChangedEvtMsg(header: BbbClientMsgHeader,
|
|||||||
case class GuestPolicyChangedEvtMsgBody(policy: String, setBy: String)
|
case class GuestPolicyChangedEvtMsgBody(policy: String, setBy: String)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message from user to get the guest policy.
|
||||||
|
*/
|
||||||
|
object GetGuestPolicyReqMsg { val NAME = "GetGuestPolicyReqMsg" }
|
||||||
|
case class GetGuestPolicyReqMsg(header: BbbClientMsgHeader,
|
||||||
|
body: GetGuestPolicyReqMsgBody) extends StandardMsg
|
||||||
|
case class GetGuestPolicyReqMsgBody(requestedBy: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sent to client as response to query for guest policy.
|
||||||
|
*/
|
||||||
|
object GetGuestPolicyRespMsg { val NAME = "GetGuestPolicyRespMsg" }
|
||||||
|
case class GetGuestPolicyRespMsg(header: BbbClientMsgHeader,
|
||||||
|
body: GetGuestPolicyRespMsgBody) extends StandardMsg
|
||||||
|
case class GetGuestPolicyRespMsgBody(policy: String)
|
||||||
|
@ -59,7 +59,7 @@ case class MeetingEndedEvtMsgBody(meetingId: String)
|
|||||||
object MeetingEndingEvtMsg { val NAME = "MeetingEndingEvtMsg"}
|
object MeetingEndingEvtMsg { val NAME = "MeetingEndingEvtMsg"}
|
||||||
case class MeetingEndingEvtMsg(header: BbbClientMsgHeader,
|
case class MeetingEndingEvtMsg(header: BbbClientMsgHeader,
|
||||||
body: MeetingEndingEvtMsgBody) extends BbbCoreMsg
|
body: MeetingEndingEvtMsgBody) extends BbbCoreMsg
|
||||||
case class MeetingEndingEvtMsgBody(meetingId: String)
|
case class MeetingEndingEvtMsgBody(meetingId: String, reason: String)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,14 +150,14 @@ public class ConnectionInvokerService implements IConnectionInvokerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleCloseMeetingAllConnectionsMsg(CloseMeetingAllConnectionsMsg msg) {
|
private void handleCloseMeetingAllConnectionsMsg(CloseMeetingAllConnectionsMsg msg) {
|
||||||
|
log.info("Disconnecting all clients for meeting {}", msg.meetingId);
|
||||||
|
|
||||||
IScope meetingScope = getScope(msg.meetingId);
|
IScope meetingScope = getScope(msg.meetingId);
|
||||||
if (meetingScope != null) {
|
if (meetingScope != null) {
|
||||||
Set<IConnection> conns = meetingScope.getClientConnections();
|
Set<IConnection> conns = meetingScope.getClientConnections();
|
||||||
|
|
||||||
for (IConnection conn : conns) {
|
for (IConnection conn : conns) {
|
||||||
if (conn.isConnected()) {
|
if (conn.isConnected()) {
|
||||||
String connId = (String) conn.getAttribute("INTERNAL_USER_ID");
|
|
||||||
log.info("Disconnecting client=[{}] from meeting=[{}]", connId, msg.meetingId);
|
|
||||||
conn.close();
|
conn.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,5 +13,21 @@ package org.bigbluebutton.core.model
|
|||||||
this.streamId = streamId;
|
this.streamId = streamId;
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addViewer(userId: String):void {
|
||||||
|
for (var i: int=0; i < viewers.length; i++) {
|
||||||
|
var viewer: String = viewers[i] as String;
|
||||||
|
if (viewer == userId) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
viewers.push(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeViewer(userId: String):void {
|
||||||
|
var index: int = viewers.indexOf(userId);
|
||||||
|
if (index > -1 && index < viewers.length) {
|
||||||
|
viewers.removeAt(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -85,7 +85,21 @@ package org.bigbluebutton.core.model
|
|||||||
return tempArray;
|
return tempArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStreamIdsViewingForUser(userId: String): Array {
|
public function startedViewingStream(userId: String, streamId: String): void {
|
||||||
|
var _stream: MediaStream = getStream(streamId);
|
||||||
|
if (_stream != null) {
|
||||||
|
_stream.addViewer(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stoppedViewingStream(userId: String, streamId: String): void {
|
||||||
|
var _stream: MediaStream = getStream(streamId);
|
||||||
|
if (_stream != null) {
|
||||||
|
_stream.removeViewer(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStreamIdsIAmViewingForUser(userId: String): Array {
|
||||||
var tempArray: Array = new Array();
|
var tempArray: Array = new Array();
|
||||||
|
|
||||||
for (var i:int = 0; i < _webcams.length; i++) {
|
for (var i:int = 0; i < _webcams.length; i++) {
|
||||||
|
@ -10,6 +10,10 @@ package org.bigbluebutton.core.model.users
|
|||||||
|
|
||||||
private var _guests:ArrayCollection = new ArrayCollection();
|
private var _guests:ArrayCollection = new ArrayCollection();
|
||||||
|
|
||||||
|
public function getGuests(): Array {
|
||||||
|
return new ArrayCollection(_guests.toArray()).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
public function add(user: GuestWaiting):void {
|
public function add(user: GuestWaiting):void {
|
||||||
_guests.addItem(user);
|
_guests.addItem(user);
|
||||||
}
|
}
|
||||||
@ -63,6 +67,14 @@ package org.bigbluebutton.core.model.users
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setGuestPolicy(value: String): void {
|
||||||
|
_guestPolicy = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGuestPolicy(): String {
|
||||||
|
return _guestPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
public function userJoined(vu: GuestWaiting):void {
|
public function userJoined(vu: GuestWaiting):void {
|
||||||
add(vu);
|
add(vu);
|
||||||
}
|
}
|
||||||
|
@ -18,62 +18,7 @@ package org.bigbluebutton.core.model.users
|
|||||||
|
|
||||||
// Flag to tell that user is in the process of leaving the meeting.
|
// Flag to tell that user is in the process of leaving the meeting.
|
||||||
public var isLeavingFlag:Boolean = false;
|
public var isLeavingFlag:Boolean = false;
|
||||||
|
|
||||||
[Bindable] private var _viewingStream:Array = new Array();
|
|
||||||
|
|
||||||
[Bindable]
|
|
||||||
public function get viewingStream():Array {
|
|
||||||
return _viewingStream;
|
|
||||||
}
|
|
||||||
public function set viewingStream(v:Array):void {
|
|
||||||
throw new Error("Please use the helpers addViewingStream or removeViewingStream to handle viewingStream");
|
|
||||||
}
|
|
||||||
public function addViewingStream(streamName:String):Boolean {
|
|
||||||
if (isViewingStream(streamName)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_viewingStream.push(streamName);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public function removeViewingStream(streamName:String):Boolean {
|
|
||||||
if (!isViewingStream(streamName)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_viewingStream = _viewingStream.filter(function(item:*, index:int, array:Array):Boolean { return item != streamName; });
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
private function isViewingStream(streamName:String):Boolean {
|
|
||||||
return _viewingStream.some(function(item:*, index:int, array:Array):Boolean { return item == streamName; });
|
|
||||||
}
|
|
||||||
public function isViewingAllStreams():Boolean {
|
|
||||||
return _viewingStream.length == streamNames.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Bindable] public var streamNames:Array = new Array();
|
|
||||||
|
|
||||||
[Bindable]
|
|
||||||
public function get streamName():String {
|
|
||||||
var streams:String = "";
|
|
||||||
for each(var stream:String in streamNames) {
|
|
||||||
streams = streams + stream + "|";
|
|
||||||
}
|
|
||||||
//Remove last |
|
|
||||||
streams = streams.slice(0, streams.length-1);
|
|
||||||
return streams;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function hasThisStream(streamName:String):Boolean {
|
|
||||||
return streamNames.some(function(item:*, index:int, array:Array):Boolean { return item == streamName; });
|
|
||||||
}
|
|
||||||
|
|
||||||
public function set streamName(streamNames:String):void {
|
|
||||||
if(streamNames) {
|
|
||||||
var streamNamesList:Array = streamNames.split("|");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function copy(source: User2x):User2x {
|
public static function copy(source: User2x):User2x {
|
||||||
var dest: User2x = new User2x();
|
var dest: User2x = new User2x();
|
||||||
dest.intId = source.intId;
|
dest.intId = source.intId;
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 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.main.events
|
||||||
|
{
|
||||||
|
import flash.events.Event;
|
||||||
|
|
||||||
|
public class StartedViewingWebcamEvent extends Event
|
||||||
|
{
|
||||||
|
public static const STARTED_VIEWING_WEBCAM:String = "started viewing webcam event";
|
||||||
|
|
||||||
|
// The userID of the webcam being viewed.
|
||||||
|
public var webcamUserID:String;
|
||||||
|
|
||||||
|
// The streamName of the user
|
||||||
|
public var streamName:String;
|
||||||
|
|
||||||
|
public function StartedViewingWebcamEvent(bubbles:Boolean=true, cancelable:Boolean=false)
|
||||||
|
{
|
||||||
|
super(STARTED_VIEWING_WEBCAM, bubbles, cancelable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,140 +1,146 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
BigBlueButton open source conferencing system - http://www.bigbluebutton.org
|
BigBlueButton open source conferencing system - http://www.bigbluebutton.org
|
||||||
|
|
||||||
Copyright (c) 2010 BigBlueButton Inc. and by respective authors (see below).
|
Copyright (c) 2010 BigBlueButton Inc. and by respective authors (see below).
|
||||||
|
|
||||||
BigBlueButton is free software; you can redistribute it and/or modify it under the
|
BigBlueButton 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
|
terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
Foundation; either version 2.1 of the License, or (at your option) any later
|
Foundation; either version 2.1 of the License, or (at your option) any later
|
||||||
version.
|
version.
|
||||||
|
|
||||||
BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
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
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
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
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
$Id: $
|
$Id: $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<mx:TitleWindow xmlns:mx="library://ns.adobe.com/flex/mx"
|
<mx:TitleWindow xmlns:mx="library://ns.adobe.com/flex/mx"
|
||||||
xmlns:fx="http://ns.adobe.com/mxml/2009"
|
xmlns:fx="http://ns.adobe.com/mxml/2009"
|
||||||
title="{ResourceUtil.getInstance().getString('bbb.guests.title')}" showCloseButton="false" creationComplete="init()"
|
title="{ResourceUtil.getInstance().getString('bbb.guests.title')}" showCloseButton="false" creationComplete="init()"
|
||||||
x="0" y="0" layout="vertical" width="320" horizontalAlign="center"
|
x="0" y="0" layout="vertical" width="320" horizontalAlign="center"
|
||||||
xmlns:mate="http://mate.asfusion.com/" >
|
xmlns:mate="http://mate.asfusion.com/" >
|
||||||
|
|
||||||
<fx:Declarations>
|
<fx:Declarations>
|
||||||
<mate:Listener type="{BBBEvent.ACCEPT_ALL_WAITING_GUESTS}" method="acceptAllWaitingGuests" />
|
<mate:Listener type="{BBBEvent.ACCEPT_ALL_WAITING_GUESTS}" method="acceptAllWaitingGuests" />
|
||||||
<mate:Listener type="{BBBEvent.DENY_ALL_WAITING_GUESTS}" method="denyAllWaitingGuests" />
|
<mate:Listener type="{BBBEvent.DENY_ALL_WAITING_GUESTS}" method="denyAllWaitingGuests" />
|
||||||
<mate:Listener type="{RemoveGuestFromViewEvent.REMOVE_GUEST}" receive="{remove(event.userid)}" />
|
<mate:Listener type="{RemoveGuestFromViewEvent.REMOVE_GUEST}" receive="{remove(event.userid)}" />
|
||||||
</fx:Declarations>
|
</fx:Declarations>
|
||||||
|
|
||||||
<fx:Script>
|
<fx:Script>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
import mx.managers.PopUpManager;
|
import com.asfusion.mate.events.Dispatcher;
|
||||||
import com.asfusion.mate.events.Dispatcher;
|
|
||||||
import org.bigbluebutton.main.events.RemoveGuestEvent;
|
import mx.controls.Button;
|
||||||
import org.bigbluebutton.main.events.ResponseModeratorEvent;
|
import mx.events.CloseEvent;
|
||||||
import org.bigbluebutton.main.events.RemoveGuestFromViewEvent;
|
import mx.managers.PopUpManager;
|
||||||
import org.bigbluebutton.util.i18n.ResourceUtil;
|
|
||||||
import mx.controls.Button;
|
import org.bigbluebutton.core.model.LiveMeeting;
|
||||||
import mx.events.CloseEvent;
|
import org.bigbluebutton.core.model.users.GuestWaiting;
|
||||||
import org.bigbluebutton.main.events.BBBEvent;
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
|
import org.bigbluebutton.main.events.RemoveGuestEvent;
|
||||||
private var guestButtons:Object = new Object();
|
import org.bigbluebutton.main.events.RemoveGuestFromViewEvent;
|
||||||
[Bindable] private var numberOfGuests:Number = 0;
|
import org.bigbluebutton.main.events.ResponseModeratorEvent;
|
||||||
private var dispatcher:Dispatcher = new Dispatcher();
|
import org.bigbluebutton.util.i18n.ResourceUtil;
|
||||||
|
|
||||||
public function init():void {
|
private var guestButtons:Object = new Object();
|
||||||
//Uncomment this line to make titlewindow undraggable
|
[Bindable] private var numberOfGuests:Number = 0;
|
||||||
//this.isPopUp = false;
|
private var dispatcher:Dispatcher = new Dispatcher();
|
||||||
}
|
|
||||||
|
public function init():void {
|
||||||
public function refreshGuestView(listOfGuests:Object):void {
|
//Uncomment this line to make titlewindow undraggable
|
||||||
for (var userid:String in listOfGuests) {
|
//this.isPopUp = false;
|
||||||
if(guestButtons[userid] == null) {
|
}
|
||||||
var guestItem:GuestItem = new GuestItem();
|
|
||||||
guestItem.setUser(listOfGuests[userid], userid);
|
public function refreshGuestView():void {
|
||||||
guestListBox.addChild(guestItem);
|
var _guests: Array = LiveMeeting.inst().guestsWaiting.getGuests();
|
||||||
guestButtons[userid] = guestItem;
|
for (var i:int = 0; i < _guests.length; i++) {
|
||||||
numberOfGuests++;
|
var _guest: GuestWaiting = _guests[i] as GuestWaiting;
|
||||||
}
|
if(guestButtons[_guest.intId] == null) {
|
||||||
}
|
var guestItem:GuestItem = new GuestItem();
|
||||||
this.visible = true;
|
guestItem.setUser(_guest.name, _guest.intId);
|
||||||
}
|
guestListBox.addChild(guestItem);
|
||||||
|
guestButtons[_guest.intId] = guestItem;
|
||||||
public function sendResponseToAllGuests(resp:Boolean):void {
|
numberOfGuests++;
|
||||||
removeAllGuests();
|
}
|
||||||
var respCommand:ResponseModeratorEvent = new ResponseModeratorEvent(ResponseModeratorEvent.RESPONSE_ALL);
|
}
|
||||||
respCommand.resp = resp;
|
this.visible = true;
|
||||||
dispatcher.dispatchEvent(respCommand);
|
}
|
||||||
}
|
|
||||||
|
public function sendResponseToAllGuests(resp:Boolean):void {
|
||||||
public function sendResponseToAllGuestsCheckBox(resp:Boolean):void {
|
removeAllGuests();
|
||||||
if(rememberCheckBox.selected) {
|
var respCommand:ResponseModeratorEvent = new ResponseModeratorEvent(ResponseModeratorEvent.RESPONSE_ALL);
|
||||||
var event:BBBEvent = new BBBEvent(BBBEvent.BROADCAST_GUEST_POLICY);
|
respCommand.resp = resp;
|
||||||
if (resp) {
|
dispatcher.dispatchEvent(respCommand);
|
||||||
event.payload['guestPolicy'] = "ALWAYS_ACCEPT";
|
}
|
||||||
} else {
|
|
||||||
event.payload['guestPolicy'] = "ALWAYS_DENY";
|
public function sendResponseToAllGuestsCheckBox(resp:Boolean):void {
|
||||||
}
|
if(rememberCheckBox.selected) {
|
||||||
dispatcher.dispatchEvent(event);
|
var event:BBBEvent = new BBBEvent(BBBEvent.BROADCAST_GUEST_POLICY);
|
||||||
}
|
if (resp) {
|
||||||
sendResponseToAllGuests(resp);
|
event.payload['guestPolicy'] = "ALWAYS_ACCEPT";
|
||||||
}
|
} else {
|
||||||
|
event.payload['guestPolicy'] = "ALWAYS_DENY";
|
||||||
public function acceptAllWaitingGuests(event:BBBEvent):void {
|
}
|
||||||
sendResponseToAllGuests(true);
|
dispatcher.dispatchEvent(event);
|
||||||
}
|
}
|
||||||
|
sendResponseToAllGuests(resp);
|
||||||
public function denyAllWaitingGuests(event:BBBEvent):void {
|
}
|
||||||
sendResponseToAllGuests(false);
|
|
||||||
}
|
public function acceptAllWaitingGuests(event:BBBEvent):void {
|
||||||
|
sendResponseToAllGuests(true);
|
||||||
public function removeAllGuests():void {
|
}
|
||||||
var removeGuestEvent:RemoveGuestEvent = new RemoveGuestEvent(RemoveGuestEvent.REMOVE_ALL);
|
|
||||||
dispatcher.dispatchEvent(removeGuestEvent);
|
public function denyAllWaitingGuests(event:BBBEvent):void {
|
||||||
|
sendResponseToAllGuests(false);
|
||||||
closeWindow();
|
}
|
||||||
}
|
|
||||||
|
public function removeAllGuests():void {
|
||||||
public function remove(userid:String):void {
|
var removeGuestEvent:RemoveGuestEvent = new RemoveGuestEvent(RemoveGuestEvent.REMOVE_ALL);
|
||||||
if (guestButtons[userid] != null) {
|
dispatcher.dispatchEvent(removeGuestEvent);
|
||||||
numberOfGuests = numberOfGuests - 1;
|
|
||||||
guestListBox.removeChild(guestButtons[userid]);
|
closeWindow();
|
||||||
delete guestButtons[userid];
|
}
|
||||||
|
|
||||||
var removeGuestEvent:RemoveGuestEvent = new RemoveGuestEvent();
|
public function remove(userid:String):void {
|
||||||
removeGuestEvent.userid = userid;
|
if (guestButtons[userid] != null) {
|
||||||
dispatcher.dispatchEvent(removeGuestEvent);
|
numberOfGuests = numberOfGuests - 1;
|
||||||
|
guestListBox.removeChild(guestButtons[userid]);
|
||||||
if (!hasGuest()) {
|
delete guestButtons[userid];
|
||||||
closeWindow();
|
|
||||||
}
|
var removeGuestEvent:RemoveGuestEvent = new RemoveGuestEvent();
|
||||||
}
|
removeGuestEvent.userid = userid;
|
||||||
}
|
dispatcher.dispatchEvent(removeGuestEvent);
|
||||||
|
|
||||||
public function hasGuest():Boolean {
|
if (!hasGuest()) {
|
||||||
return numberOfGuests > 0;
|
closeWindow();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public function closeWindow():void {
|
}
|
||||||
this.visible = false;
|
|
||||||
PopUpManager.removePopUp(this);
|
public function hasGuest():Boolean {
|
||||||
dispatchEvent(new CloseEvent(CloseEvent.CLOSE));
|
return numberOfGuests > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
]]>
|
public function closeWindow():void {
|
||||||
</fx:Script>
|
this.visible = false;
|
||||||
<mx:Label text="{numberOfGuests > 1? ResourceUtil.getInstance().getString('bbb.guests.message.plural', [String(numberOfGuests)]): ResourceUtil.getInstance().getString('bbb.guests.message.singular', [String(numberOfGuests)])}"/>
|
PopUpManager.removePopUp(this);
|
||||||
<mx:HRule width="100%"/>
|
//dispatchEvent(new CloseEvent(CloseEvent.CLOSE));
|
||||||
<mx:Button id="allowEveryoneBtn" label="{ResourceUtil.getInstance().getString('bbb.guests.allowEveryoneBtn.text')}" width="70%" click="sendResponseToAllGuestsCheckBox(true)" toolTip="{allowEveryoneBtn.label}"/>
|
}
|
||||||
<mx:Button id="denyEveryoneBtn" label="{ResourceUtil.getInstance().getString('bbb.guests.denyEveryoneBtn.text')}" width="70%" click="sendResponseToAllGuestsCheckBox(false)" toolTip="{denyEveryoneBtn.label}"/>
|
|
||||||
<mx:CheckBox id="rememberCheckBox" label="{ResourceUtil.getInstance().getString('bbb.guests.rememberAction.text')}"/>
|
]]>
|
||||||
<mx:HRule width="100%"/>
|
</fx:Script>
|
||||||
<mx:VBox id="guestListBox" width="100%" height="100%" maxHeight="200" paddingLeft="10" paddingRight="10" paddingBottom="2" />
|
<mx:Label text="{numberOfGuests > 1? ResourceUtil.getInstance().getString('bbb.guests.message.plural', [String(numberOfGuests)]): ResourceUtil.getInstance().getString('bbb.guests.message.singular', [String(numberOfGuests)])}"/>
|
||||||
|
<mx:HRule width="100%"/>
|
||||||
|
<mx:Button id="allowEveryoneBtn" label="{ResourceUtil.getInstance().getString('bbb.guests.allowEveryoneBtn.text')}" width="70%" click="sendResponseToAllGuestsCheckBox(true)" toolTip="{allowEveryoneBtn.label}"/>
|
||||||
|
<mx:Button id="denyEveryoneBtn" label="{ResourceUtil.getInstance().getString('bbb.guests.denyEveryoneBtn.text')}" width="70%" click="sendResponseToAllGuestsCheckBox(false)" toolTip="{denyEveryoneBtn.label}"/>
|
||||||
|
<mx:CheckBox id="rememberCheckBox" label="{ResourceUtil.getInstance().getString('bbb.guests.rememberAction.text')}"/>
|
||||||
|
<mx:HRule width="100%"/>
|
||||||
|
<mx:VBox id="guestListBox" width="100%" height="100%" maxHeight="200" paddingLeft="10" paddingRight="10" paddingBottom="2" />
|
||||||
|
|
||||||
</mx:TitleWindow>
|
</mx:TitleWindow>
|
||||||
|
@ -78,75 +78,75 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
<mate:Listener type="{BBBEvent.RETRIEVE_GUEST_POLICY}" method="setGuestPolicy"/>
|
<mate:Listener type="{BBBEvent.RETRIEVE_GUEST_POLICY}" method="setGuestPolicy"/>
|
||||||
<mate:Listener type="{ConnectionFailedEvent.MODERATOR_DENIED_ME}" method="handleLogout" />
|
<mate:Listener type="{ConnectionFailedEvent.MODERATOR_DENIED_ME}" method="handleLogout" />
|
||||||
<mate:Listener type="{BBBEvent.MODERATOR_ALLOWED_ME_TO_JOIN}" method="guestAllowed" />
|
<mate:Listener type="{BBBEvent.MODERATOR_ALLOWED_ME_TO_JOIN}" method="guestAllowed" />
|
||||||
<mate:Listener type="{RefreshGuestEvent.REFRESH_GUEST_VIEW}" method="refreshGuestView" />
|
<mate:Listener type="{NewGuestWaitingEvent.NEW_GUEST_WAITING}" method="refreshGuestView" />
|
||||||
<mate:Listener type="{BBBEvent.REMOVE_GUEST_FROM_LIST}" method="removeGuestWindow" />
|
<mate:Listener type="{BBBEvent.REMOVE_GUEST_FROM_LIST}" method="removeGuestWindow" />
|
||||||
<mate:Listener type="{BBBEvent.WAITING_FOR_MODERATOR_ACCEPTANCE}" method="openWaitWindow" />
|
<mate:Listener type="{BBBEvent.WAITING_FOR_MODERATOR_ACCEPTANCE}" method="openWaitWindow" />
|
||||||
<mate:Listener type="{BBBEvent.RECONNECT_DISCONNECTED_EVENT}" method="closeWaitWindow"/>
|
<mate:Listener type="{BBBEvent.RECONNECT_DISCONNECTED_EVENT}" method="closeWaitWindow"/>
|
||||||
</fx:Declarations>
|
</fx:Declarations>
|
||||||
<fx:Script>
|
<fx:Script>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
import com.asfusion.mate.events.Dispatcher;
|
import com.asfusion.mate.events.Dispatcher;
|
||||||
|
|
||||||
import flash.events.Event;
|
import flash.events.Event;
|
||||||
import flash.events.FullScreenEvent;
|
import flash.events.FullScreenEvent;
|
||||||
import flash.events.IOErrorEvent;
|
import flash.events.IOErrorEvent;
|
||||||
import flash.events.TextEvent;
|
import flash.events.TextEvent;
|
||||||
import flash.geom.Point;
|
import flash.geom.Point;
|
||||||
import flash.net.navigateToURL;
|
import flash.net.navigateToURL;
|
||||||
|
|
||||||
import mx.binding.utils.ChangeWatcher;
|
import mx.binding.utils.ChangeWatcher;
|
||||||
import mx.collections.ArrayCollection;
|
import mx.collections.ArrayCollection;
|
||||||
import mx.controls.Alert;
|
import mx.controls.Alert;
|
||||||
import mx.core.FlexGlobals;
|
import mx.core.FlexGlobals;
|
||||||
import mx.core.IFlexDisplayObject;
|
import mx.core.IFlexDisplayObject;
|
||||||
import mx.core.UIComponent;
|
import mx.core.UIComponent;
|
||||||
import mx.events.FlexEvent;
|
import mx.events.FlexEvent;
|
||||||
|
|
||||||
import flexlib.mdi.effects.effectsLib.MDIVistaEffects;
|
import flexlib.mdi.effects.effectsLib.MDIVistaEffects;
|
||||||
|
|
||||||
import org.as3commons.lang.StringUtils;
|
import org.as3commons.lang.StringUtils;
|
||||||
import org.as3commons.logging.api.ILogger;
|
import org.as3commons.logging.api.ILogger;
|
||||||
import org.as3commons.logging.api.getClassLogger;
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
import org.bigbluebutton.common.IBbbModuleWindow;
|
import org.bigbluebutton.common.IBbbModuleWindow;
|
||||||
import org.bigbluebutton.common.events.AddUIComponentToMainCanvas;
|
import org.bigbluebutton.common.events.AddUIComponentToMainCanvas;
|
||||||
import org.bigbluebutton.common.events.CloseWindowEvent;
|
import org.bigbluebutton.common.events.CloseWindowEvent;
|
||||||
import org.bigbluebutton.common.events.OpenWindowEvent;
|
import org.bigbluebutton.common.events.OpenWindowEvent;
|
||||||
import org.bigbluebutton.common.events.ToolbarButtonEvent;
|
import org.bigbluebutton.common.events.ToolbarButtonEvent;
|
||||||
import org.bigbluebutton.core.BBB;
|
import org.bigbluebutton.core.BBB;
|
||||||
import org.bigbluebutton.core.Options;
|
import org.bigbluebutton.core.Options;
|
||||||
import org.bigbluebutton.core.PopUpUtil;
|
import org.bigbluebutton.core.PopUpUtil;
|
||||||
import org.bigbluebutton.core.UsersUtil;
|
import org.bigbluebutton.core.UsersUtil;
|
||||||
import org.bigbluebutton.core.events.LockControlEvent;
|
import org.bigbluebutton.core.events.LockControlEvent;
|
||||||
import org.bigbluebutton.core.events.SwitchedLayoutEvent;
|
import org.bigbluebutton.core.events.NewGuestWaitingEvent;
|
||||||
import org.bigbluebutton.core.vo.LockSettingsVO;
|
import org.bigbluebutton.core.events.SwitchedLayoutEvent;
|
||||||
import org.bigbluebutton.main.events.AppVersionEvent;
|
import org.bigbluebutton.core.vo.LockSettingsVO;
|
||||||
import org.bigbluebutton.main.events.BBBEvent;
|
import org.bigbluebutton.main.events.AppVersionEvent;
|
||||||
import org.bigbluebutton.main.events.BreakoutRoomEvent;
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
import org.bigbluebutton.main.events.ClientStatusEvent;
|
import org.bigbluebutton.main.events.BreakoutRoomEvent;
|
||||||
import org.bigbluebutton.main.events.ConfigLoadedEvent;
|
import org.bigbluebutton.main.events.ClientStatusEvent;
|
||||||
import org.bigbluebutton.main.events.ExitApplicationEvent;
|
import org.bigbluebutton.main.events.ConfigLoadedEvent;
|
||||||
import org.bigbluebutton.main.events.InvalidAuthTokenEvent;
|
import org.bigbluebutton.main.events.ExitApplicationEvent;
|
||||||
import org.bigbluebutton.main.events.MeetingNotFoundEvent;
|
import org.bigbluebutton.main.events.InvalidAuthTokenEvent;
|
||||||
import org.bigbluebutton.main.events.ModuleLoadEvent;
|
import org.bigbluebutton.main.events.MeetingNotFoundEvent;
|
||||||
import org.bigbluebutton.main.events.NetworkStatsEvent;
|
import org.bigbluebutton.main.events.ModuleLoadEvent;
|
||||||
import org.bigbluebutton.main.events.RefreshGuestEvent;
|
import org.bigbluebutton.main.events.NetworkStatsEvent;
|
||||||
import org.bigbluebutton.main.events.ShortcutEvent;
|
import org.bigbluebutton.main.events.ShortcutEvent;
|
||||||
import org.bigbluebutton.main.model.Guest;
|
import org.bigbluebutton.main.model.Guest;
|
||||||
import org.bigbluebutton.main.model.ImageLoader;
|
import org.bigbluebutton.main.model.ImageLoader;
|
||||||
import org.bigbluebutton.main.model.options.BrandingOptions;
|
import org.bigbluebutton.main.model.options.BrandingOptions;
|
||||||
import org.bigbluebutton.main.model.options.BrowserVersionsOptions;
|
import org.bigbluebutton.main.model.options.BrowserVersionsOptions;
|
||||||
import org.bigbluebutton.main.model.options.LanguageOptions;
|
import org.bigbluebutton.main.model.options.LanguageOptions;
|
||||||
import org.bigbluebutton.main.model.options.LayoutOptions;
|
import org.bigbluebutton.main.model.options.LayoutOptions;
|
||||||
import org.bigbluebutton.main.model.users.events.ConnectionFailedEvent;
|
import org.bigbluebutton.main.model.users.events.ConnectionFailedEvent;
|
||||||
import org.bigbluebutton.modules.phone.events.AudioSelectionWindowEvent;
|
import org.bigbluebutton.modules.phone.events.AudioSelectionWindowEvent;
|
||||||
import org.bigbluebutton.modules.phone.events.FlashMicSettingsEvent;
|
import org.bigbluebutton.modules.phone.events.FlashMicSettingsEvent;
|
||||||
import org.bigbluebutton.modules.phone.events.WebRTCCallEvent;
|
import org.bigbluebutton.modules.phone.events.WebRTCCallEvent;
|
||||||
import org.bigbluebutton.modules.phone.events.WebRTCEchoTestEvent;
|
import org.bigbluebutton.modules.phone.events.WebRTCEchoTestEvent;
|
||||||
import org.bigbluebutton.modules.phone.events.WebRTCMediaEvent;
|
import org.bigbluebutton.modules.phone.events.WebRTCMediaEvent;
|
||||||
import org.bigbluebutton.modules.phone.models.PhoneOptions;
|
import org.bigbluebutton.modules.phone.models.PhoneOptions;
|
||||||
import org.bigbluebutton.modules.users.views.BreakoutRoomSettings;
|
import org.bigbluebutton.modules.users.views.BreakoutRoomSettings;
|
||||||
import org.bigbluebutton.modules.videoconf.events.ShareCameraRequestEvent;
|
import org.bigbluebutton.modules.videoconf.events.ShareCameraRequestEvent;
|
||||||
import org.bigbluebutton.util.i18n.ResourceUtil;
|
import org.bigbluebutton.util.i18n.ResourceUtil;
|
||||||
|
|
||||||
private static const LOGGER:ILogger = getClassLogger(MainApplicationShell);
|
private static const LOGGER:ILogger = getClassLogger(MainApplicationShell);
|
||||||
|
|
||||||
@ -493,7 +493,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function refreshGuestView(evt:RefreshGuestEvent):void {
|
private function refreshGuestView(evt:NewGuestWaitingEvent):void {
|
||||||
// do not show the guest window if the user isn't moderator or if he's waiting for acceptance
|
// do not show the guest window if the user isn't moderator or if he's waiting for acceptance
|
||||||
if (!UsersUtil.amIModerator() || UsersUtil.amIWaitingForAcceptance()) {
|
if (!UsersUtil.amIModerator() || UsersUtil.amIWaitingForAcceptance()) {
|
||||||
closeGuestWindow();
|
closeGuestWindow();
|
||||||
@ -507,7 +507,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
guestWindow.x = systemManager.screen.width - guestWindow.width - 20;
|
guestWindow.x = systemManager.screen.width - guestWindow.width - 20;
|
||||||
guestWindow.y = 20;
|
guestWindow.y = 20;
|
||||||
}
|
}
|
||||||
guestWindow.refreshGuestView(evt.listOfGuests);
|
guestWindow.refreshGuestView();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function removeGuestWindow(evt:BBBEvent):void {
|
public function removeGuestWindow(evt:BBBEvent):void {
|
||||||
|
@ -24,16 +24,12 @@ package org.bigbluebutton.modules.users.events
|
|||||||
{
|
{
|
||||||
public static const VIEW_CAMERA_EVENT:String = "VIEW_CAMERA_EVENT";
|
public static const VIEW_CAMERA_EVENT:String = "VIEW_CAMERA_EVENT";
|
||||||
|
|
||||||
public var stream:String;
|
|
||||||
public var viewedName:String;
|
|
||||||
public var userID:String;
|
public var userID:String;
|
||||||
|
|
||||||
public function ViewCameraEvent(userID:String, stream:String, viewedName:String)
|
public function ViewCameraEvent(userID:String)
|
||||||
{
|
{
|
||||||
super(VIEW_CAMERA_EVENT,true);
|
super(VIEW_CAMERA_EVENT,true);
|
||||||
this.userID = userID;
|
this.userID = userID;
|
||||||
this.stream = stream;
|
|
||||||
this.viewedName = viewedName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
|
||||||
<EventHandlers type="{ResponseModeratorEvent.RESPONSE_ALL}" >
|
<EventHandlers type="{ResponseModeratorEvent.RESPONSE_ALL}" >
|
||||||
<MethodInvoker generator="{UserService}" method="responseToGuest" arguments="{event}" />
|
<MethodInvoker generator="{UserService}" method="responseToAllGuest" arguments="{event}" />
|
||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
|
||||||
<EventHandlers type="{BBBEvent.BROADCAST_GUEST_POLICY}" >
|
<EventHandlers type="{BBBEvent.BROADCAST_GUEST_POLICY}" >
|
||||||
|
@ -112,15 +112,9 @@ package org.bigbluebutton.modules.users.services
|
|||||||
case "GuestsWaitingForApprovalEvtMsg":
|
case "GuestsWaitingForApprovalEvtMsg":
|
||||||
handleGuestsWaitingForApprovalEvtMsg(message);
|
handleGuestsWaitingForApprovalEvtMsg(message);
|
||||||
break;
|
break;
|
||||||
case "meetingEnded":
|
|
||||||
handleLogout(message);
|
|
||||||
break;
|
|
||||||
case "MeetingEndingEvtMsg":
|
case "MeetingEndingEvtMsg":
|
||||||
handleMeetingEnding(message);
|
handleMeetingEnding(message);
|
||||||
break;
|
break;
|
||||||
case "meetingHasEnded":
|
|
||||||
handleMeetingHasEnded(message);
|
|
||||||
break;
|
|
||||||
case "meetingMuted":
|
case "meetingMuted":
|
||||||
handleMeetingMuted(message);
|
handleMeetingMuted(message);
|
||||||
break;
|
break;
|
||||||
@ -182,10 +176,10 @@ package org.bigbluebutton.modules.users.services
|
|||||||
case "ScreenshareRtmpBroadcastStoppedEvtMsg":
|
case "ScreenshareRtmpBroadcastStoppedEvtMsg":
|
||||||
handleScreenshareRtmpBroadcastStoppedEvtMsg(message);
|
handleScreenshareRtmpBroadcastStoppedEvtMsg(message);
|
||||||
break;
|
break;
|
||||||
case "get_guest_policy_reply":
|
case "GetGuestPolicyRespMsg":
|
||||||
handleGetGuestPolicyReply(message);
|
handleGetGuestPolicyReply(message);
|
||||||
break;
|
break;
|
||||||
case "guest_policy_changed":
|
case "GuestPolicyChangedEvtMsg":
|
||||||
handleGuestPolicyChanged(message);
|
handleGuestPolicyChanged(message);
|
||||||
break;
|
break;
|
||||||
case "guest_access_denied":
|
case "guest_access_denied":
|
||||||
@ -274,6 +268,7 @@ package org.bigbluebutton.modules.users.services
|
|||||||
var guestWaiting: GuestWaiting = new GuestWaiting(guest.intId, guest.name, guest.role);
|
var guestWaiting: GuestWaiting = new GuestWaiting(guest.intId, guest.name, guest.role);
|
||||||
LiveMeeting.inst().guestsWaiting.add(guestWaiting);
|
LiveMeeting.inst().guestsWaiting.add(guestWaiting);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleGuestsWaitingForApprovalEvtMsg(msg: Object): void {
|
private function handleGuestsWaitingForApprovalEvtMsg(msg: Object): void {
|
||||||
var body: Object = msg.body as Object;
|
var body: Object = msg.body as Object;
|
||||||
var guests: Array = body.guests as Array;
|
var guests: Array = body.guests as Array;
|
||||||
@ -473,10 +468,6 @@ package org.bigbluebutton.modules.users.services
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleMeetingHasEnded(msg: Object):void {
|
|
||||||
LOGGER.debug("*** handleMeetingHasEnded {0} **** \n", [msg.msg]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function handlePermissionsSettingsChanged(msg:Object):void {
|
private function handlePermissionsSettingsChanged(msg:Object):void {
|
||||||
//LOGGER.debug("handlePermissionsSettingsChanged {0} \n", [msg.msg]);
|
//LOGGER.debug("handlePermissionsSettingsChanged {0} \n", [msg.msg]);
|
||||||
@ -565,23 +556,16 @@ package org.bigbluebutton.modules.users.services
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by the server to tell the client that the meeting has ended.
|
|
||||||
*/
|
|
||||||
public function handleLogout(msg:Object):void {
|
|
||||||
var endMeetingEvent:BBBEvent = new BBBEvent(BBBEvent.END_MEETING_EVENT);
|
|
||||||
dispatcher.dispatchEvent(endMeetingEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This meeting is in the process of ending by the server
|
* This meeting is in the process of ending by the server
|
||||||
*/
|
*/
|
||||||
public function handleMeetingEnding(msg:Object):void {
|
public function handleMeetingEnding(msg:Object):void {
|
||||||
// Avoid trying to reconnect
|
// Avoid trying to reconnect
|
||||||
var endMeetingEvent:BBBEvent = new BBBEvent(BBBEvent.CANCEL_RECONNECTION_EVENT);
|
var cancelReconnectEvent:BBBEvent = new BBBEvent(BBBEvent.CANCEL_RECONNECTION_EVENT);
|
||||||
dispatcher.dispatchEvent(endMeetingEvent);
|
dispatcher.dispatchEvent(cancelReconnectEvent);
|
||||||
|
var endMeetingEvent:BBBEvent = new BBBEvent(BBBEvent.END_MEETING_EVENT);
|
||||||
|
dispatcher.dispatchEvent(endMeetingEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleAssignPresenterCallback(msg:Object):void {
|
public function handleAssignPresenterCallback(msg:Object):void {
|
||||||
@ -670,7 +654,6 @@ package org.bigbluebutton.modules.users.services
|
|||||||
|
|
||||||
var webUser: User2x = UsersUtil.getUser(userId);
|
var webUser: User2x = UsersUtil.getUser(userId);
|
||||||
if (webUser != null) {
|
if (webUser != null) {
|
||||||
webUser.streamNames.push(streamId);
|
|
||||||
sendStreamStartedEvent(userId, webUser.name, streamId);
|
sendStreamStartedEvent(userId, webUser.name, streamId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,6 +674,8 @@ package org.bigbluebutton.modules.users.services
|
|||||||
logData.user.webcamStream = stream;
|
logData.user.webcamStream = stream;
|
||||||
LOGGER.info(JSON.stringify(logData));
|
LOGGER.info(JSON.stringify(logData));
|
||||||
|
|
||||||
|
LiveMeeting.inst().webcams.remove(stream);
|
||||||
|
|
||||||
sendStreamStoppedEvent(userId, stream);
|
sendStreamStoppedEvent(userId, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,9 +684,6 @@ package org.bigbluebutton.modules.users.services
|
|||||||
dispatcher.dispatchEvent(new StreamStoppedEvent(userId, streamId));
|
dispatcher.dispatchEvent(new StreamStoppedEvent(userId, streamId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private function handleBreakoutRoomsList(msg:Object):void{
|
private function handleBreakoutRoomsList(msg:Object):void{
|
||||||
for each(var room : Object in msg.body.rooms)
|
for each(var room : Object in msg.body.rooms)
|
||||||
@ -774,24 +756,26 @@ package org.bigbluebutton.modules.users.services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function handleGuestPolicyChanged(msg:Object):void {
|
public function handleGuestPolicyChanged(msg:Object):void {
|
||||||
LOGGER.debug("*** handleGuestPolicyChanged " + msg.msg + " **** \n");
|
var header: Object = msg.header as Object;
|
||||||
var map:Object = JSON.parse(msg.msg);
|
var body: Object = msg.body as Object;
|
||||||
|
var policy: String = body.policy as String;
|
||||||
|
|
||||||
var policy:BBBEvent = new BBBEvent(BBBEvent.RETRIEVE_GUEST_POLICY);
|
var policyEvent:BBBEvent = new BBBEvent(BBBEvent.RETRIEVE_GUEST_POLICY);
|
||||||
policy.payload['guestPolicy'] = map.guestPolicy;
|
policyEvent.payload['guestPolicy'] = policy;
|
||||||
dispatcher.dispatchEvent(policy);
|
dispatcher.dispatchEvent(policyEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleGetGuestPolicyReply(msg:Object):void {
|
public function handleGetGuestPolicyReply(msg:Object):void {
|
||||||
LOGGER.debug("*** handleGetGuestPolicyReply " + msg.msg + " **** \n");
|
var header: Object = msg.header as Object;
|
||||||
var map:Object = JSON.parse(msg.msg);
|
var body: Object = msg.body as Object;
|
||||||
|
var policy: String = body.policy as String;
|
||||||
var policy:BBBEvent = new BBBEvent(BBBEvent.RETRIEVE_GUEST_POLICY);
|
|
||||||
policy.payload['guestPolicy'] = map.guestPolicy;
|
LiveMeeting.inst().guestsWaiting.setGuestPolicy(policy);
|
||||||
dispatcher.dispatchEvent(policy);
|
|
||||||
|
var policyEvent:BBBEvent = new BBBEvent(BBBEvent.RETRIEVE_GUEST_POLICY);
|
||||||
|
policyEvent.payload['guestPolicy'] = policyEvent;
|
||||||
|
dispatcher.dispatchEvent(policyEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleGuestAccessDenied(msg:Object):void {
|
public function handleGuestAccessDenied(msg:Object):void {
|
||||||
|
@ -37,6 +37,8 @@ package org.bigbluebutton.modules.users.services
|
|||||||
import org.bigbluebutton.core.connection.messages.breakoutrooms.RequestBreakoutJoinURLMsg;
|
import org.bigbluebutton.core.connection.messages.breakoutrooms.RequestBreakoutJoinURLMsg;
|
||||||
import org.bigbluebutton.core.connection.messages.breakoutrooms.RequestBreakoutJoinURLMsgBody;
|
import org.bigbluebutton.core.connection.messages.breakoutrooms.RequestBreakoutJoinURLMsgBody;
|
||||||
import org.bigbluebutton.core.managers.ConnectionManager;
|
import org.bigbluebutton.core.managers.ConnectionManager;
|
||||||
|
import org.bigbluebutton.core.model.LiveMeeting;
|
||||||
|
import org.bigbluebutton.core.model.users.GuestWaiting;
|
||||||
|
|
||||||
public class MessageSender {
|
public class MessageSender {
|
||||||
private static const LOGGER:ILogger = getClassLogger(MessageSender);
|
private static const LOGGER:ILogger = getClassLogger(MessageSender);
|
||||||
@ -577,8 +579,15 @@ package org.bigbluebutton.modules.users.services
|
|||||||
|
|
||||||
public function queryForGuestPolicy():void {
|
public function queryForGuestPolicy():void {
|
||||||
LOGGER.debug("queryForGuestPolicy");
|
LOGGER.debug("queryForGuestPolicy");
|
||||||
|
|
||||||
|
var message:Object = {
|
||||||
|
header: {name: "GetGuestPolicyReqMsg", meetingId: UsersUtil.getInternalMeetingID(),
|
||||||
|
userId: UsersUtil.getMyUserID()},
|
||||||
|
body: {requestedBy: UsersUtil.getMyUserID()}
|
||||||
|
};
|
||||||
|
|
||||||
var _nc:ConnectionManager = BBB.initConnectionManager();
|
var _nc:ConnectionManager = BBB.initConnectionManager();
|
||||||
_nc.sendMessage("participants.getGuestPolicy",
|
_nc.sendMessage2x(
|
||||||
function(result:String):void { // On successful result
|
function(result:String):void { // On successful result
|
||||||
LOGGER.debug(result);
|
LOGGER.debug(result);
|
||||||
},
|
},
|
||||||
@ -587,14 +596,15 @@ package org.bigbluebutton.modules.users.services
|
|||||||
logData.tags = ["apps"];
|
logData.tags = ["apps"];
|
||||||
logData.message = "Error occured query guest policy.";
|
logData.message = "Error occured query guest policy.";
|
||||||
LOGGER.info(JSON.stringify(logData));
|
LOGGER.info(JSON.stringify(logData));
|
||||||
}
|
},
|
||||||
|
JSON.stringify(message)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setGuestPolicy(policy:String):void {
|
public function setGuestPolicy(policy:String):void {
|
||||||
LOGGER.debug("setGuestPolicy - new policy:[" + policy + "]");
|
LOGGER.debug("setGuestPolicy - new policy:[" + policy + "]");
|
||||||
var message:Object = {
|
var message:Object = {
|
||||||
header: {name: "SetGuestPolicyMsg", meetingId: UsersUtil.getInternalMeetingID(),
|
header: {name: "SetGuestPolicyCmdMsg", meetingId: UsersUtil.getInternalMeetingID(),
|
||||||
userId: UsersUtil.getMyUserID()},
|
userId: UsersUtil.getMyUserID()},
|
||||||
body: {policy: policy, setBy: UsersUtil.getMyUserID()}
|
body: {policy: policy, setBy: UsersUtil.getMyUserID()}
|
||||||
};
|
};
|
||||||
@ -617,12 +627,17 @@ package org.bigbluebutton.modules.users.services
|
|||||||
public function responseToGuest(userId:String, response:Boolean):void {
|
public function responseToGuest(userId:String, response:Boolean):void {
|
||||||
LOGGER.debug("responseToGuest - userId:[" + userId + "] response:[" + response + "]");
|
LOGGER.debug("responseToGuest - userId:[" + userId + "] response:[" + response + "]");
|
||||||
|
|
||||||
var message:Object = new Object();
|
var _guests: Array = new Array();
|
||||||
message["userId"] = userId;
|
_guests.push({guest: userId, approved: response});
|
||||||
message["response"] = response;
|
|
||||||
|
var message:Object = {
|
||||||
|
header: {name: "GuestsWaitingApprovedMsg", meetingId: UsersUtil.getInternalMeetingID(),
|
||||||
|
userId: UsersUtil.getMyUserID()},
|
||||||
|
body: {guests: _guests, approvedBy: UsersUtil.getMyUserID()}
|
||||||
|
};
|
||||||
|
|
||||||
var _nc:ConnectionManager = BBB.initConnectionManager();
|
var _nc:ConnectionManager = BBB.initConnectionManager();
|
||||||
_nc.sendMessage("participants.responseToGuest",
|
_nc.sendMessage2x(
|
||||||
function(result:String):void { // On successful result
|
function(result:String):void { // On successful result
|
||||||
LOGGER.debug(result);
|
LOGGER.debug(result);
|
||||||
},
|
},
|
||||||
@ -632,12 +647,38 @@ package org.bigbluebutton.modules.users.services
|
|||||||
logData.message = "Error occured response guest.";
|
logData.message = "Error occured response guest.";
|
||||||
LOGGER.info(JSON.stringify(logData));
|
LOGGER.info(JSON.stringify(logData));
|
||||||
},
|
},
|
||||||
message
|
JSON.stringify(message)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function responseToAllGuests(response:Boolean):void {
|
public function responseToAllGuests(response:Boolean):void {
|
||||||
responseToGuest(null, response);
|
var _guestsWaiting: Array = LiveMeeting.inst().guestsWaiting.getGuests();
|
||||||
|
var _guests: Array = new Array();
|
||||||
|
|
||||||
|
for (var i:int = 0; i < _guests.length; i++) {
|
||||||
|
var _guest: GuestWaiting = _guestsWaiting[i] as GuestWaiting;
|
||||||
|
_guests.push({guest: _guest.intId, approved: response});
|
||||||
|
}
|
||||||
|
|
||||||
|
var message:Object = {
|
||||||
|
header: {name: "GuestsWaitingApprovedMsg", meetingId: UsersUtil.getInternalMeetingID(),
|
||||||
|
userId: UsersUtil.getMyUserID()},
|
||||||
|
body: {guests: _guests, approvedBy: UsersUtil.getMyUserID()}
|
||||||
|
};
|
||||||
|
|
||||||
|
var _nc:ConnectionManager = BBB.initConnectionManager();
|
||||||
|
_nc.sendMessage2x(
|
||||||
|
function(result:String):void { // On successful result
|
||||||
|
LOGGER.debug(result);
|
||||||
|
},
|
||||||
|
function(status:String):void { // status - On error occurred
|
||||||
|
var logData:Object = UsersUtil.initLogData();
|
||||||
|
logData.tags = ["apps"];
|
||||||
|
logData.message = "Error occured response guest.";
|
||||||
|
LOGGER.info(JSON.stringify(logData));
|
||||||
|
},
|
||||||
|
JSON.stringify(message)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function viewCamera():void {
|
private function viewCamera():void {
|
||||||
dispatchEvent(new ViewCameraEvent(data.userId, data.streamName, data.name));
|
dispatchEvent(new ViewCameraEvent(data.userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function kickUser():void{
|
private function kickUser():void{
|
||||||
|
@ -52,69 +52,77 @@
|
|||||||
<mate:Listener type="{UserLeftEvent.LEFT}" method="handleUserLeftEvent" />
|
<mate:Listener type="{UserLeftEvent.LEFT}" method="handleUserLeftEvent" />
|
||||||
<mate:Listener type="{UserEmojiChangedEvent.USER_EMOJI_CHANGED}" method="handleUserEmojiChangedEvent" />
|
<mate:Listener type="{UserEmojiChangedEvent.USER_EMOJI_CHANGED}" method="handleUserEmojiChangedEvent" />
|
||||||
<mate:Listener type="{SwitchedPresenterEvent.SWITCHED_PRESENTER}" method="handleSwitchedPresenterEvent" />
|
<mate:Listener type="{SwitchedPresenterEvent.SWITCHED_PRESENTER}" method="handleSwitchedPresenterEvent" />
|
||||||
|
<mate:Listener type="{StoppedViewingWebcamEvent.STOPPED_VIEWING_WEBCAM}" method="handleStoppedViewingWebcamEvent" />
|
||||||
|
<mate:Listener type="{StartedViewingWebcamEvent.STARTED_VIEWING_WEBCAM}" method="handleStartedViewingWebcamEvent" />
|
||||||
|
<mate:Listener type="{StreamStartedEvent.STREAM_STARTED}" method="handleStreamStartedEvent" />
|
||||||
|
<mate:Listener type="{StreamStoppedEvent.STREAM_STOPPED}" method="handleStreamStoppedEvent" />
|
||||||
|
|
||||||
|
|
||||||
</fx:Declarations>
|
</fx:Declarations>
|
||||||
<fx:Script>
|
<fx:Script>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
import com.asfusion.mate.events.Dispatcher;
|
import com.asfusion.mate.events.Dispatcher;
|
||||||
|
|
||||||
import flash.net.navigateToURL;
|
import flash.net.navigateToURL;
|
||||||
|
|
||||||
import mx.binding.utils.BindingUtils;
|
import mx.binding.utils.BindingUtils;
|
||||||
import mx.collections.ArrayCollection;
|
import mx.collections.ArrayCollection;
|
||||||
import mx.controls.Alert;
|
import mx.controls.Alert;
|
||||||
import mx.controls.Menu;
|
import mx.controls.Menu;
|
||||||
import mx.controls.dataGridClasses.DataGridColumn;
|
import mx.controls.dataGridClasses.DataGridColumn;
|
||||||
import mx.controls.listClasses.IListItemRenderer;
|
import mx.controls.listClasses.IListItemRenderer;
|
||||||
import mx.core.FlexGlobals;
|
import mx.core.FlexGlobals;
|
||||||
import mx.core.mx_internal;
|
import mx.core.mx_internal;
|
||||||
import mx.events.CloseEvent;
|
import mx.events.CloseEvent;
|
||||||
import mx.events.CollectionEvent;
|
import mx.events.CollectionEvent;
|
||||||
import mx.events.ListEvent;
|
import mx.events.ListEvent;
|
||||||
import mx.events.MenuEvent;
|
import mx.events.MenuEvent;
|
||||||
import mx.managers.PopUpManager;
|
import mx.managers.PopUpManager;
|
||||||
|
|
||||||
import org.as3commons.logging.api.ILogger;
|
import org.as3commons.logging.api.ILogger;
|
||||||
import org.as3commons.logging.api.getClassLogger;
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
import org.bigbluebutton.common.IBbbModuleWindow;
|
import org.bigbluebutton.common.IBbbModuleWindow;
|
||||||
import org.bigbluebutton.common.Role;
|
import org.bigbluebutton.common.Role;
|
||||||
import org.bigbluebutton.common.events.LocaleChangeEvent;
|
import org.bigbluebutton.common.events.LocaleChangeEvent;
|
||||||
import org.bigbluebutton.core.EventConstants;
|
import org.bigbluebutton.core.EventConstants;
|
||||||
import org.bigbluebutton.core.KeyboardUtil;
|
import org.bigbluebutton.core.KeyboardUtil;
|
||||||
import org.bigbluebutton.core.PopUpUtil;
|
import org.bigbluebutton.core.PopUpUtil;
|
||||||
import org.bigbluebutton.core.TimerUtil;
|
import org.bigbluebutton.core.TimerUtil;
|
||||||
import org.bigbluebutton.core.UsersUtil;
|
import org.bigbluebutton.core.UsersUtil;
|
||||||
import org.bigbluebutton.core.events.BreakoutRoomsListUpdatedEvent;
|
import org.bigbluebutton.core.events.BreakoutRoomsListUpdatedEvent;
|
||||||
import org.bigbluebutton.core.events.CoreEvent;
|
import org.bigbluebutton.core.events.CoreEvent;
|
||||||
import org.bigbluebutton.core.events.LockControlEvent;
|
import org.bigbluebutton.core.events.LockControlEvent;
|
||||||
import org.bigbluebutton.core.events.UserEmojiChangedEvent;
|
import org.bigbluebutton.core.events.UserEmojiChangedEvent;
|
||||||
import org.bigbluebutton.core.events.UserStatusChangedEvent;
|
import org.bigbluebutton.core.events.UserStatusChangedEvent;
|
||||||
import org.bigbluebutton.core.events.VoiceConfEvent;
|
import org.bigbluebutton.core.events.VoiceConfEvent;
|
||||||
import org.bigbluebutton.core.model.LiveMeeting;
|
import org.bigbluebutton.core.model.LiveMeeting;
|
||||||
import org.bigbluebutton.core.model.users.User2x;
|
import org.bigbluebutton.core.model.users.User2x;
|
||||||
import org.bigbluebutton.core.vo.LockSettingsVO;
|
import org.bigbluebutton.core.vo.LockSettingsVO;
|
||||||
import org.bigbluebutton.main.events.BBBEvent;
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
import org.bigbluebutton.main.events.BreakoutRoomEvent;
|
import org.bigbluebutton.main.events.BreakoutRoomEvent;
|
||||||
import org.bigbluebutton.main.events.ShortcutEvent;
|
import org.bigbluebutton.main.events.ShortcutEvent;
|
||||||
import org.bigbluebutton.main.events.SwitchedPresenterEvent;
|
import org.bigbluebutton.main.events.StartedViewingWebcamEvent;
|
||||||
import org.bigbluebutton.main.events.UserJoinedEvent;
|
import org.bigbluebutton.main.events.StoppedViewingWebcamEvent;
|
||||||
import org.bigbluebutton.main.events.UserLeftEvent;
|
import org.bigbluebutton.main.events.SwitchedPresenterEvent;
|
||||||
import org.bigbluebutton.main.model.users.BreakoutRoom;
|
import org.bigbluebutton.main.events.UserJoinedEvent;
|
||||||
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
|
import org.bigbluebutton.main.events.UserLeftEvent;
|
||||||
import org.bigbluebutton.main.model.users.events.EmojiStatusEvent;
|
import org.bigbluebutton.main.model.users.BreakoutRoom;
|
||||||
import org.bigbluebutton.main.model.users.events.KickUserEvent;
|
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
|
||||||
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
|
import org.bigbluebutton.main.model.users.events.EmojiStatusEvent;
|
||||||
import org.bigbluebutton.main.views.MainCanvas;
|
import org.bigbluebutton.main.model.users.events.KickUserEvent;
|
||||||
import org.bigbluebutton.main.views.WellPositionedMenu;
|
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
|
||||||
import org.bigbluebutton.modules.phone.events.LeaveVoiceConferenceCommand;
|
import org.bigbluebutton.main.model.users.events.StreamStartedEvent;
|
||||||
import org.bigbluebutton.modules.users.events.MeetingMutedEvent;
|
import org.bigbluebutton.main.model.users.events.StreamStoppedEvent;
|
||||||
import org.bigbluebutton.modules.users.events.UsersRollEvent;
|
import org.bigbluebutton.main.views.MainCanvas;
|
||||||
import org.bigbluebutton.modules.users.model.BreakoutRoomsOptions;
|
import org.bigbluebutton.main.views.WellPositionedMenu;
|
||||||
import org.bigbluebutton.modules.users.model.UsersOptions;
|
import org.bigbluebutton.modules.phone.events.LeaveVoiceConferenceCommand;
|
||||||
import org.bigbluebutton.modules.users.views.model.BBBUser2x;
|
import org.bigbluebutton.modules.users.events.MeetingMutedEvent;
|
||||||
import org.bigbluebutton.modules.videoconf.events.StopBroadcastEvent;
|
import org.bigbluebutton.modules.users.events.UsersRollEvent;
|
||||||
import org.bigbluebutton.util.i18n.ResourceUtil;
|
import org.bigbluebutton.modules.users.model.BreakoutRoomsOptions;
|
||||||
|
import org.bigbluebutton.modules.users.model.UsersOptions;
|
||||||
|
import org.bigbluebutton.modules.users.views.model.BBBUser2x;
|
||||||
|
import org.bigbluebutton.modules.videoconf.events.StopBroadcastEvent;
|
||||||
|
import org.bigbluebutton.util.i18n.ResourceUtil;
|
||||||
|
|
||||||
private static const LOGGER:ILogger = getClassLogger(UsersWindow);
|
private static const LOGGER:ILogger = getClassLogger(UsersWindow);
|
||||||
|
|
||||||
@ -196,7 +204,22 @@
|
|||||||
handler.handleUserLeftEvent(event.userID);
|
handler.handleUserLeftEvent(event.userID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function handleStoppedViewingWebcamEvent(event: StoppedViewingWebcamEvent): void {
|
||||||
|
handler.handleStoppedViewingWebcamEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleStartedViewingWebcamEvent(event: StartedViewingWebcamEvent): void {
|
||||||
|
handler.handleStartedViewingWebcamEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleStreamStartedEvent(event: StreamStartedEvent): void {
|
||||||
|
handler.handleStreamStartedEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleStreamStoppedEvent(event: StreamStoppedEvent): void {
|
||||||
|
handler.handleStreamStoppedEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
private function handleUserJoinedEvent(event: UserJoinedEvent):void {
|
private function handleUserJoinedEvent(event: UserJoinedEvent):void {
|
||||||
handler.handleUserJoinedEvent(event);
|
handler.handleUserJoinedEvent(event);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,11 @@ package org.bigbluebutton.modules.users.views
|
|||||||
import org.bigbluebutton.core.model.LiveMeeting;
|
import org.bigbluebutton.core.model.LiveMeeting;
|
||||||
import org.bigbluebutton.core.model.users.User2x;
|
import org.bigbluebutton.core.model.users.User2x;
|
||||||
import org.bigbluebutton.core.model.users.VoiceUser2x;
|
import org.bigbluebutton.core.model.users.VoiceUser2x;
|
||||||
|
import org.bigbluebutton.main.events.StartedViewingWebcamEvent;
|
||||||
|
import org.bigbluebutton.main.events.StoppedViewingWebcamEvent;
|
||||||
import org.bigbluebutton.main.events.UserJoinedEvent;
|
import org.bigbluebutton.main.events.UserJoinedEvent;
|
||||||
|
import org.bigbluebutton.main.model.users.events.StreamStartedEvent;
|
||||||
|
import org.bigbluebutton.main.model.users.events.StreamStoppedEvent;
|
||||||
import org.bigbluebutton.modules.users.views.model.BBBUser2x;
|
import org.bigbluebutton.modules.users.views.model.BBBUser2x;
|
||||||
import org.bigbluebutton.modules.users.views.model.BBBVoiceUser2x;
|
import org.bigbluebutton.modules.users.views.model.BBBVoiceUser2x;
|
||||||
|
|
||||||
@ -86,15 +90,14 @@ package org.bigbluebutton.modules.users.views
|
|||||||
users.refresh();
|
users.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getWebcamStreamsForUser(userId: String): String {
|
private function getWebcamStreamsForUser(userId: String): Array {
|
||||||
var streamIds: Array = LiveMeeting.inst().webcams.getStreamIdsForUser(userId);
|
var streamIds: Array = LiveMeeting.inst().webcams.getStreamIdsForUser(userId);
|
||||||
var streams:String = "";
|
return streamIds;
|
||||||
for each(var stream:String in streamIds) {
|
}
|
||||||
streams = streams + stream + "|";
|
|
||||||
}
|
private function getWebcamStreamsViewingForUser(userId: String): Array {
|
||||||
//Remove last |
|
var streamIds: Array = LiveMeeting.inst().webcams.getStreamIdsIAmViewingForUser(userId);
|
||||||
streams = streams.slice(0, streams.length-1);
|
return streamIds;
|
||||||
return streams;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function addUser(users: ArrayCollection, user: User2x):void {
|
private function addUser(users: ArrayCollection, user: User2x):void {
|
||||||
@ -107,7 +110,8 @@ package org.bigbluebutton.modules.users.views
|
|||||||
buser.locked = user.locked;
|
buser.locked = user.locked;
|
||||||
buser.emojiStatus = user.emoji;
|
buser.emojiStatus = user.emoji;
|
||||||
buser.presenter = user.presenter;
|
buser.presenter = user.presenter;
|
||||||
buser.streamName = getWebcamStreamsForUser(buser.userId);
|
buser.streams = getWebcamStreamsForUser(buser.userId);
|
||||||
|
buser.viewedStream = getWebcamStreamsViewingForUser(buser.userId);
|
||||||
|
|
||||||
buser.inVoiceConf = false;
|
buser.inVoiceConf = false;
|
||||||
|
|
||||||
@ -131,7 +135,6 @@ package org.bigbluebutton.modules.users.views
|
|||||||
var user: User2x = UsersUtil.getUser(event.userID);
|
var user: User2x = UsersUtil.getUser(event.userID);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
addUser(users, user);
|
addUser(users, user);
|
||||||
trace("!!!!!!!!!!!!!!!********* " + user.name + " " + user.presenter + " ********!!!!!!!!");
|
|
||||||
users.refresh();
|
users.refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,8 +156,6 @@ package org.bigbluebutton.modules.users.views
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function handleUserJoinedVoiceConfEvent(userId: String):void {
|
public function handleUserJoinedVoiceConfEvent(userId: String):void {
|
||||||
var webUser: BBBUser2x = findUser(userId);
|
var webUser: BBBUser2x = findUser(userId);
|
||||||
if (webUser != null) {
|
if (webUser != null) {
|
||||||
@ -258,6 +259,32 @@ package org.bigbluebutton.modules.users.views
|
|||||||
users.refresh();
|
users.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function refreshWebcamStreamsInfo(userId: String): void {
|
||||||
|
var user: BBBUser2x = findUser(userId);
|
||||||
|
if (user != null) {
|
||||||
|
user.streams = getWebcamStreamsForUser(user.userId);
|
||||||
|
user.viewedStream = getWebcamStreamsViewingForUser(user.userId);
|
||||||
|
}
|
||||||
|
users.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleStoppedViewingWebcamEvent(event: StoppedViewingWebcamEvent): void {
|
||||||
|
refreshWebcamStreamsInfo(event.webcamUserID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleStartedViewingWebcamEvent(event: StartedViewingWebcamEvent): void {
|
||||||
|
refreshWebcamStreamsInfo(event.webcamUserID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleStreamStartedEvent(event: StreamStartedEvent): void {
|
||||||
|
refreshWebcamStreamsInfo(event.userID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleStreamStoppedEvent(event: StreamStoppedEvent): void {
|
||||||
|
refreshWebcamStreamsInfo(event.userId);
|
||||||
|
}
|
||||||
|
|
||||||
private function findUser(userId: String): BBBUser2x {
|
private function findUser(userId: String): BBBUser2x {
|
||||||
for (var i: int = 0; i < users.length; i++) {
|
for (var i: int = 0; i < users.length; i++) {
|
||||||
var user: BBBUser2x = users[i] as BBBUser2x;
|
var user: BBBUser2x = users[i] as BBBUser2x;
|
||||||
|
@ -19,15 +19,17 @@
|
|||||||
package org.bigbluebutton.modules.users.views.model
|
package org.bigbluebutton.modules.users.views.model
|
||||||
{
|
{
|
||||||
import com.asfusion.mate.events.Dispatcher;
|
import com.asfusion.mate.events.Dispatcher;
|
||||||
|
|
||||||
import flash.events.Event;
|
import flash.events.Event;
|
||||||
|
|
||||||
import org.as3commons.lang.ArrayUtils;
|
import org.as3commons.lang.ArrayUtils;
|
||||||
import org.as3commons.logging.api.ILogger;
|
import org.as3commons.logging.api.ILogger;
|
||||||
import org.as3commons.logging.api.getClassLogger;
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
import org.bigbluebutton.common.Role;
|
import org.bigbluebutton.common.Role;
|
||||||
import org.bigbluebutton.main.model.users.events.StreamStartedEvent;
|
|
||||||
import org.bigbluebutton.util.i18n.ResourceUtil;
|
|
||||||
import org.bigbluebutton.main.model.users.Status;
|
import org.bigbluebutton.main.model.users.Status;
|
||||||
import org.bigbluebutton.main.model.users.StatusCollection;
|
import org.bigbluebutton.main.model.users.StatusCollection;
|
||||||
|
import org.bigbluebutton.main.model.users.events.StreamStartedEvent;
|
||||||
|
import org.bigbluebutton.util.i18n.ResourceUtil;
|
||||||
|
|
||||||
public class BBBUser2x {
|
public class BBBUser2x {
|
||||||
private static const LOGGER:ILogger = getClassLogger(BBBUser2x);
|
private static const LOGGER:ILogger = getClassLogger(BBBUser2x);
|
||||||
@ -48,7 +50,7 @@ package org.bigbluebutton.modules.users.views.model
|
|||||||
|
|
||||||
[Bindable]
|
[Bindable]
|
||||||
public function get hasStream():Boolean {
|
public function get hasStream():Boolean {
|
||||||
return streamNames.length > 0;
|
return _streamNames.length > 0;
|
||||||
}
|
}
|
||||||
public function set hasStream(s:Boolean):void {
|
public function set hasStream(s:Boolean):void {
|
||||||
throw new Error("hasStream cannot be set. It is derived directly from streamName");
|
throw new Error("hasStream cannot be set. It is derived directly from streamName");
|
||||||
@ -56,59 +58,37 @@ package org.bigbluebutton.modules.users.views.model
|
|||||||
|
|
||||||
[Bindable] private var _viewingStream:Array = new Array();
|
[Bindable] private var _viewingStream:Array = new Array();
|
||||||
|
|
||||||
[Bindable]
|
|
||||||
public function get viewingStream():Array {
|
|
||||||
return _viewingStream;
|
|
||||||
}
|
|
||||||
public function set viewingStream(v:Array):void {
|
|
||||||
throw new Error("Please use the helpers addViewingStream or removeViewingStream to handle viewingStream");
|
|
||||||
}
|
|
||||||
public function addViewingStream(streamName:String):Boolean {
|
|
||||||
if (isViewingStream(streamName)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_viewingStream.push(streamName);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public function removeViewingStream(streamName:String):Boolean {
|
|
||||||
if (!isViewingStream(streamName)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_viewingStream = _viewingStream.filter(function(item:*, index:int, array:Array):Boolean { return item != streamName; });
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
private function isViewingStream(streamName:String):Boolean {
|
|
||||||
return _viewingStream.some(function(item:*, index:int, array:Array):Boolean { return item == streamName; });
|
|
||||||
}
|
|
||||||
public function isViewingAllStreams():Boolean {
|
public function isViewingAllStreams():Boolean {
|
||||||
return _viewingStream.length == streamNames.length;
|
return _viewingStream.length == _streamNames.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Bindable] public var streamNames:Array = new Array();
|
public function set viewedStream(streamIds: Array): void {
|
||||||
|
if (streamIds != null) {
|
||||||
|
_viewingStream = streamIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var _streamNames:Array = new Array();
|
||||||
|
|
||||||
[Bindable]
|
[Bindable]
|
||||||
public function get streamName():String {
|
public function get streams():Array {
|
||||||
var streams:String = "";
|
return _streamNames;
|
||||||
for each(var stream:String in streamNames) {
|
|
||||||
streams = streams + stream + "|";
|
|
||||||
}
|
|
||||||
//Remove last |
|
|
||||||
streams = streams.slice(0, streams.length-1);
|
|
||||||
return streams;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function hasThisStream(streamName:String):Boolean {
|
private function hasThisStream(streamName:String):Boolean {
|
||||||
return streamNames.some(function(item:*, index:int, array:Array):Boolean { return item == streamName; });
|
for each(var streamId:String in _streamNames) {
|
||||||
|
if (streamId == streamName) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set streamName(streamNames:String):void {
|
public function set streams(streamIds:Array):void {
|
||||||
if(streamNames) {
|
if (streamIds != null) {
|
||||||
var streamNamesList:Array = streamNames.split("|");
|
_streamNames = streamIds;
|
||||||
for each(var streamName:String in streamNamesList) {
|
// for each(var streamId:String in _streamNames) {
|
||||||
sharedWebcam(streamName);
|
// sharedWebcam(streamId);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,19 +222,12 @@ package org.bigbluebutton.modules.users.views.model
|
|||||||
|
|
||||||
public function sharedWebcam(stream: String):void {
|
public function sharedWebcam(stream: String):void {
|
||||||
if(stream && stream != "" && !hasThisStream(stream)) {
|
if(stream && stream != "" && !hasThisStream(stream)) {
|
||||||
streamNames.push(stream);
|
|
||||||
sendStreamStartedEvent(stream);
|
sendStreamStartedEvent(stream);
|
||||||
}
|
}
|
||||||
buildStatus();
|
buildStatus();
|
||||||
verifyMedia();
|
verifyMedia();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unsharedWebcam(stream: String):void {
|
|
||||||
streamNames = streamNames.filter(function(item:*, index:int, array:Array):Boolean { return item != stream });
|
|
||||||
buildStatus();
|
|
||||||
verifyMedia();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function presenterStatusChanged(presenter: Boolean):void {
|
public function presenterStatusChanged(presenter: Boolean):void {
|
||||||
this.presenter = presenter;
|
this.presenter = presenter;
|
||||||
buildStatus();
|
buildStatus();
|
||||||
@ -270,18 +243,6 @@ package org.bigbluebutton.modules.users.views.model
|
|||||||
case "presenter":
|
case "presenter":
|
||||||
presenter=(status.value.toString().toUpperCase() == "TRUE") ? true : false;
|
presenter=(status.value.toString().toUpperCase() == "TRUE") ? true : false;
|
||||||
break;
|
break;
|
||||||
case "hasStream":
|
|
||||||
var streamInfo:Array=String(status.value).split(/,/);
|
|
||||||
/**
|
|
||||||
* Cannot use this statement as new Boolean(expression)
|
|
||||||
* return true if the expression is a non-empty string not
|
|
||||||
* when the string equals "true". See Boolean class def.
|
|
||||||
*
|
|
||||||
* hasStream = new Boolean(String(streamInfo[0]));
|
|
||||||
*/
|
|
||||||
var streamNameInfo:Array=String(streamInfo[1]).split(/=/);
|
|
||||||
streamName=streamNameInfo[1];
|
|
||||||
break;
|
|
||||||
// @FIXME : check the coming status from the server
|
// @FIXME : check the coming status from the server
|
||||||
case "emojiStatus":
|
case "emojiStatus":
|
||||||
emojiStatus = status.value.toString();
|
emojiStatus = status.value.toString();
|
||||||
|
@ -88,7 +88,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
<EventHandlers type="{StreamStartedEvent.STREAM_STARTED}">
|
<EventHandlers type="{StreamStartedEvent.STREAM_STARTED}">
|
||||||
<ObjectBuilder generator="{VideoEventMapDelegate}" cache="global" constructorArguments="{scope.dispatcher}"/>
|
<ObjectBuilder generator="{VideoEventMapDelegate}" cache="global" constructorArguments="{scope.dispatcher}"/>
|
||||||
<MethodInvoker generator="{VideoEventMapDelegate}" method="viewCamera" arguments="{[event.userID, event.stream, event.user]}" />
|
<MethodInvoker generator="{VideoEventMapDelegate}" method="viewCamera" arguments="{[event.userID]}" />
|
||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
|
||||||
<EventHandlers type="{StreamStoppedEvent.STREAM_STOPPED}">
|
<EventHandlers type="{StreamStoppedEvent.STREAM_STOPPED}">
|
||||||
@ -96,7 +96,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
|||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
|
||||||
<EventHandlers type="{ViewCameraEvent.VIEW_CAMERA_EVENT}">
|
<EventHandlers type="{ViewCameraEvent.VIEW_CAMERA_EVENT}">
|
||||||
<MethodInvoker generator="{VideoEventMapDelegate}" method="viewCamera" arguments="{[event.userID, event.stream, event.viewedName]}" />
|
<MethodInvoker generator="{VideoEventMapDelegate}" method="viewCamera" arguments="{[event.userID]}" />
|
||||||
</EventHandlers>
|
</EventHandlers>
|
||||||
|
|
||||||
<EventHandlers type="{UserJoinedEvent.JOINED}">
|
<EventHandlers type="{UserJoinedEvent.JOINED}">
|
||||||
|
@ -114,11 +114,10 @@ package org.bigbluebutton.modules.videoconf.maps
|
|||||||
_graphics.addStaticComponent(component);
|
_graphics.addStaticComponent(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function viewCamera(userID:String, stream:String, name:String, mock:Boolean = false):void {
|
public function viewCamera(userID:String):void {
|
||||||
LOGGER.debug("VideoEventMapDelegate:: [{0}] viewCamera. ready = [{1}]", [me, _ready]);
|
LOGGER.debug("VideoEventMapDelegate:: [{0}] viewCamera. ready = [{1}]", [me, _ready]);
|
||||||
|
|
||||||
if (!_ready) return;
|
if (!_ready) return;
|
||||||
LOGGER.debug("VideoEventMapDelegate:: [{0}] Viewing [{1} stream [{2}]", [me, userID, stream]);
|
|
||||||
if (! UsersUtil.isMe(userID)) {
|
if (! UsersUtil.isMe(userID)) {
|
||||||
openViewWindowFor(userID);
|
openViewWindowFor(userID);
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,15 @@ package org.bigbluebutton.modules.videoconf.views
|
|||||||
import org.as3commons.logging.api.ILogger;
|
import org.as3commons.logging.api.ILogger;
|
||||||
import org.as3commons.logging.api.getClassLogger;
|
import org.as3commons.logging.api.getClassLogger;
|
||||||
import org.bigbluebutton.core.BBB;
|
import org.bigbluebutton.core.BBB;
|
||||||
import org.bigbluebutton.core.model.VideoProfile;
|
|
||||||
import org.bigbluebutton.core.UsersUtil;
|
import org.bigbluebutton.core.UsersUtil;
|
||||||
|
import org.bigbluebutton.core.model.LiveMeeting;
|
||||||
|
import org.bigbluebutton.core.model.VideoProfile;
|
||||||
import org.bigbluebutton.main.events.BBBEvent;
|
import org.bigbluebutton.main.events.BBBEvent;
|
||||||
|
import org.bigbluebutton.main.events.StartedViewingWebcamEvent;
|
||||||
import org.bigbluebutton.main.events.StoppedViewingWebcamEvent;
|
import org.bigbluebutton.main.events.StoppedViewingWebcamEvent;
|
||||||
import org.bigbluebutton.main.views.VideoWithWarnings;
|
import org.bigbluebutton.main.views.VideoWithWarnings;
|
||||||
import org.bigbluebutton.modules.videoconf.events.StartBroadcastEvent;
|
import org.bigbluebutton.modules.videoconf.events.StartBroadcastEvent;
|
||||||
import org.bigbluebutton.modules.videoconf.events.StopBroadcastEvent;
|
import org.bigbluebutton.modules.videoconf.events.StopBroadcastEvent;
|
||||||
|
|
||||||
public class UserVideo extends UserGraphic {
|
public class UserVideo extends UserGraphic {
|
||||||
private static const LOGGER:ILogger = getClassLogger(UserVideo);
|
private static const LOGGER:ILogger = getClassLogger(UserVideo);
|
||||||
@ -125,13 +127,29 @@ package org.bigbluebutton.modules.videoconf.views
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function stopViewing():void {
|
private function stopViewing():void {
|
||||||
|
// Store that I stopped viewing this streamId;
|
||||||
|
var myUserId: String = UsersUtil.getMyUserID();
|
||||||
|
LiveMeeting.inst().webcams.stoppedViewingStream(myUserId, _streamName);
|
||||||
|
|
||||||
var stopEvent:StoppedViewingWebcamEvent = new StoppedViewingWebcamEvent();
|
var stopEvent:StoppedViewingWebcamEvent = new StoppedViewingWebcamEvent();
|
||||||
stopEvent.webcamUserID = user.intId;
|
stopEvent.webcamUserID = user.intId;
|
||||||
stopEvent.streamName = _streamName;
|
stopEvent.streamName = _streamName;
|
||||||
_dispatcher.dispatchEvent(stopEvent);
|
_dispatcher.dispatchEvent(stopEvent);
|
||||||
user.removeViewingStream(_streamName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function startedViewing():void {
|
||||||
|
// Store that I started viewing this streamId;
|
||||||
|
var myUserId: String = UsersUtil.getMyUserID();
|
||||||
|
LiveMeeting.inst().webcams.startedViewingStream(myUserId, _streamName);
|
||||||
|
|
||||||
|
var startEvent:StartedViewingWebcamEvent = new StartedViewingWebcamEvent();
|
||||||
|
startEvent.webcamUserID = user.intId;
|
||||||
|
startEvent.streamName = _streamName;
|
||||||
|
_dispatcher.dispatchEvent(startEvent);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private function stopPublishing():void {
|
private function stopPublishing():void {
|
||||||
var e:StopBroadcastEvent = new StopBroadcastEvent();
|
var e:StopBroadcastEvent = new StopBroadcastEvent();
|
||||||
e.stream = _streamName;
|
e.stream = _streamName;
|
||||||
@ -183,7 +201,8 @@ package org.bigbluebutton.modules.videoconf.views
|
|||||||
|
|
||||||
_ns.play(streamName);
|
_ns.play(streamName);
|
||||||
|
|
||||||
user.addViewingStream(streamName);
|
startedViewing();
|
||||||
|
|
||||||
invalidateDisplayList();
|
invalidateDisplayList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user