- stop poll if presenter leaves or presentation page changed
This commit is contained in:
parent
be9becacc1
commit
36601345c2
@ -439,11 +439,11 @@ class BigBlueButtonInGW(val system: ActorSystem, outGW: MessageOutGateway, voice
|
||||
}
|
||||
|
||||
def startPoll(meetingId: String, requesterId: String, pollId: String, pollType: String) {
|
||||
bbbActor ! new StartPollRequest(meetingId, requesterId, pollId, pollType)
|
||||
bbbActor ! new StartPollRequest(meetingId, requesterId, pollType)
|
||||
}
|
||||
|
||||
def stopPoll(meetingId: String, userId: String, pollId: String) {
|
||||
bbbActor ! new StopPollRequest(meetingId, userId, pollId)
|
||||
bbbActor ! new StopPollRequest(meetingId, userId)
|
||||
}
|
||||
|
||||
def showPollResult(meetingId: String, requesterId: String, pollId: String, show: java.lang.Boolean) {
|
||||
|
@ -10,11 +10,7 @@ import org.bigbluebutton.core.util._
|
||||
import scala.concurrent.duration._
|
||||
import org.bigbluebutton.core.apps.{ PollApp, UsersApp, PresentationApp, LayoutApp, ChatApp, WhiteboardApp }
|
||||
import org.bigbluebutton.core.apps.{ ChatModel, LayoutModel, UsersModel, PollModel, WhiteboardModel }
|
||||
|
||||
case object StopMeetingActor
|
||||
case class MeetingProperties(meetingID: String, externalMeetingID: String, meetingName: String, recorded: Boolean,
|
||||
voiceBridge: String, duration: Long, autoStartRecording: Boolean, allowStartStopRecording: Boolean,
|
||||
moderatorPass: String, viewerPass: String, createTime: Long, createDate: String)
|
||||
import org.bigbluebutton.core.apps.PresentationModel
|
||||
|
||||
object MeetingActor {
|
||||
def props(mProps: MeetingProperties, outGW: MessageOutGateway): Props =
|
||||
@ -29,9 +25,10 @@ class MeetingActor(val mProps: MeetingProperties, val outGW: MessageOutGateway)
|
||||
val chatModel = new ChatModel()
|
||||
val layoutModel = new LayoutModel()
|
||||
val meetingModel = new MeetingModel()
|
||||
val users = new UsersModel()
|
||||
val usersModel = new UsersModel()
|
||||
val pollModel = new PollModel()
|
||||
val wbModel = new WhiteboardModel()
|
||||
val presModel = new PresentationModel()
|
||||
|
||||
import context.dispatcher
|
||||
context.system.scheduler.schedule(2 seconds, 5 seconds, self, "MonitorNumberOfWebUsers")
|
||||
@ -197,13 +194,13 @@ class MeetingActor(val mProps: MeetingProperties, val outGW: MessageOutGateway)
|
||||
}
|
||||
|
||||
def webUserJoined() {
|
||||
if (users.numWebUsers > 0) {
|
||||
if (usersModel.numWebUsers > 0) {
|
||||
meetingModel.resetLastWebUserLeftOn()
|
||||
}
|
||||
}
|
||||
|
||||
def startRecordingIfAutoStart() {
|
||||
if (mProps.recorded && !meetingModel.isRecording() && mProps.autoStartRecording && users.numWebUsers == 1) {
|
||||
if (mProps.recorded && !meetingModel.isRecording() && mProps.autoStartRecording && usersModel.numWebUsers == 1) {
|
||||
log.info("Auto start recording for meeting=[" + mProps.meetingID + "]")
|
||||
meetingModel.recordingStarted()
|
||||
outGW.send(new RecordingStatusChanged(mProps.meetingID, mProps.recorded, "system", meetingModel.isRecording()))
|
||||
@ -211,7 +208,7 @@ class MeetingActor(val mProps: MeetingProperties, val outGW: MessageOutGateway)
|
||||
}
|
||||
|
||||
def stopAutoStartedRecording() {
|
||||
if (mProps.recorded && meetingModel.isRecording() && mProps.autoStartRecording && users.numWebUsers == 0) {
|
||||
if (mProps.recorded && meetingModel.isRecording() && mProps.autoStartRecording && usersModel.numWebUsers == 0) {
|
||||
log.info("Last web user left. Auto stopping recording for meeting=[{}", mProps.meetingID)
|
||||
meetingModel.recordingStopped()
|
||||
outGW.send(new RecordingStatusChanged(mProps.meetingID, mProps.recorded, "system", meetingModel.isRecording()))
|
||||
@ -219,7 +216,7 @@ class MeetingActor(val mProps: MeetingProperties, val outGW: MessageOutGateway)
|
||||
}
|
||||
|
||||
def startCheckingIfWeNeedToEndVoiceConf() {
|
||||
if (users.numWebUsers == 0) {
|
||||
if (usersModel.numWebUsers == 0) {
|
||||
meetingModel.lastWebUserLeft()
|
||||
log.debug("MonitorNumberOfWebUsers started for meeting [" + mProps.meetingID + "]")
|
||||
}
|
||||
@ -227,7 +224,7 @@ class MeetingActor(val mProps: MeetingProperties, val outGW: MessageOutGateway)
|
||||
|
||||
def handleMonitorNumberOfWebUsers() {
|
||||
println("BACK TIMER")
|
||||
if (users.numWebUsers == 0 && meetingModel.lastWebUserLeftOn > 0) {
|
||||
if (usersModel.numWebUsers == 0 && meetingModel.lastWebUserLeftOn > 0) {
|
||||
if (timeNowInMinutes - meetingModel.lastWebUserLeftOn > 2) {
|
||||
log.info("MonitorNumberOfWebUsers empty for meeting [" + mProps.meetingID + "]. Ejecting all users from voice.")
|
||||
outGW.send(new EjectAllVoiceUsers(mProps.meetingID, mProps.recorded, mProps.voiceBridge))
|
||||
|
@ -3,6 +3,11 @@ package org.bigbluebutton.core
|
||||
import org.bigbluebutton.core.api.Permissions
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
case object StopMeetingActor
|
||||
case class MeetingProperties(meetingID: String, externalMeetingID: String, meetingName: String, recorded: Boolean,
|
||||
voiceBridge: String, duration: Long, autoStartRecording: Boolean, allowStartStopRecording: Boolean,
|
||||
moderatorPass: String, viewerPass: String, createTime: Long, createDate: String)
|
||||
|
||||
class MeetingModel {
|
||||
private var audioSettingsInited = false
|
||||
private var permissionsInited = false
|
||||
|
@ -78,8 +78,8 @@ case class PresentationConversionCompleted(meetingID: String, messageKey: String
|
||||
|
||||
// Polling
|
||||
//case class CreatePollRequest(meetingID: String, requesterId: String, pollId: String, pollType: String) extends InMessage
|
||||
case class StartPollRequest(meetingID: String, requesterId: String, pollId: String, pollType: String) extends InMessage
|
||||
case class StopPollRequest(meetingID: String, requesterId: String, pollId: String) extends InMessage
|
||||
case class StartPollRequest(meetingID: String, requesterId: String, pollType: String) extends InMessage
|
||||
case class StopPollRequest(meetingID: String, requesterId: String) extends InMessage
|
||||
case class ShowPollResultRequest(meetingID: String, requesterId: String, pollId: String) extends InMessage
|
||||
case class HidePollResultRequest(meetingID: String, requesterId: String, pollId: String) extends InMessage
|
||||
case class RespondToPollRequest(meetingID: String, requesterId: String, pollId: String, questionId: Int, answerId: Int) extends InMessage
|
||||
|
@ -112,7 +112,7 @@ case class PageChanged(meetingID: String, page: Page) extends IOutMessage
|
||||
case class PollStartedMessage(meetingID: String, recorded: Boolean, requesterId: String, pollId: String, poll: SimplePollOutVO) extends IOutMessage
|
||||
case class StartPollReplyMessage(meetingID: String, recorded: Boolean, result: RequestResult, requesterId: String, pollId: String) extends IOutMessage
|
||||
case class PollStoppedMessage(meetingID: String, recorded: Boolean, requesterId: String, pollId: String) extends IOutMessage
|
||||
case class StopPollReplyMessage(meetingID: String, recorded: Boolean, result: RequestResult, requesterId: String, pollId: String) extends IOutMessage
|
||||
case class StopPollReplyMessage(meetingID: String, recorded: Boolean, result: RequestResult, requesterId: String) extends IOutMessage
|
||||
case class PollShowResultMessage(meetingID: String, recorded: Boolean, requesterId: String, pollId: String, poll: SimplePollResultOutVO) extends IOutMessage
|
||||
case class ShowPollResultReplyMessage(meetingID: String, recorded: Boolean, result: RequestResult, requesterId: String, pollId: String) extends IOutMessage
|
||||
case class PollHideResultMessage(meetingID: String, recorded: Boolean, requesterId: String, pollId: String) extends IOutMessage
|
||||
|
@ -45,14 +45,14 @@ trait LayoutApp {
|
||||
def affectedUsers(): Array[UserVO] = {
|
||||
if (layoutModel.doesLayoutApplyToViewersOnly()) {
|
||||
val au = ArrayBuffer[UserVO]()
|
||||
users.getUsers foreach { u =>
|
||||
usersModel.getUsers foreach { u =>
|
||||
if (!u.presenter && u.role != Role.MODERATOR) {
|
||||
au += u
|
||||
}
|
||||
}
|
||||
au.toArray
|
||||
} else {
|
||||
users.getUsers
|
||||
usersModel.getUsers
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,7 +15,13 @@ trait PollApp {
|
||||
}
|
||||
|
||||
def handleGetCurrentPollRequest(msg: GetCurrentPollRequest) {
|
||||
pollModel.getCurrentPoll() match {
|
||||
|
||||
val poll = for {
|
||||
page <- presModel.getCurrentPage()
|
||||
curPoll <- pollModel.getRunningPollThatStartsWith(page.id)
|
||||
} yield curPoll
|
||||
|
||||
poll match {
|
||||
case Some(p) => {
|
||||
if (p.started && p.stopped && p.showResult) {
|
||||
outGW.send(new GetCurrentPollReplyMessage(mProps.meetingID, mProps.recorded, msg.requesterId, true, Some(p)))
|
||||
@ -68,61 +74,44 @@ trait PollApp {
|
||||
}
|
||||
|
||||
def handleStopPollRequest(msg: StopPollRequest) {
|
||||
pollModel.getPoll(msg.pollId) match {
|
||||
val cpoll = for {
|
||||
page <- presModel.getCurrentPage()
|
||||
curPoll <- pollModel.getRunningPollThatStartsWith(page.id)
|
||||
} yield curPoll
|
||||
|
||||
cpoll match {
|
||||
case Some(poll) => {
|
||||
pollModel.stopPoll(poll.id)
|
||||
outGW.send(new PollStoppedMessage(mProps.meetingID, mProps.recorded, msg.requesterId, msg.pollId))
|
||||
outGW.send(new PollStoppedMessage(mProps.meetingID, mProps.recorded, msg.requesterId, poll.id))
|
||||
}
|
||||
case None => {
|
||||
val result = new RequestResult(StatusCodes.NOT_FOUND, Some(Array(ErrorCodes.RESOURCE_NOT_FOUND)))
|
||||
sender ! new StopPollReplyMessage(mProps.meetingID, mProps.recorded, result, msg.requesterId, msg.pollId)
|
||||
sender ! new StopPollReplyMessage(mProps.meetingID, mProps.recorded, result, msg.requesterId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def handleStartPollRequest(msg: StartPollRequest) {
|
||||
log.debug("Received StartPollRequest for pollId=[" + msg.pollId + "]")
|
||||
createPoll(msg)
|
||||
log.debug("Received StartPollRequest for pollType=[" + msg.pollType + "]")
|
||||
|
||||
pollModel.getSimplePoll(msg.pollId) match {
|
||||
presModel.getCurrentPage() foreach { page =>
|
||||
val pollId = page.id + "/" + System.currentTimeMillis()
|
||||
|
||||
PollFactory.createPoll(pollId, msg.pollType) foreach (poll => pollModel.addPoll(poll))
|
||||
|
||||
pollModel.getSimplePoll(pollId) match {
|
||||
case Some(poll) => {
|
||||
pollModel.startPoll(poll.id)
|
||||
outGW.send(new PollStartedMessage(mProps.meetingID, mProps.recorded, msg.requesterId, msg.pollId, poll))
|
||||
outGW.send(new PollStartedMessage(mProps.meetingID, mProps.recorded, msg.requesterId, pollId, poll))
|
||||
}
|
||||
case None => {
|
||||
val result = new RequestResult(StatusCodes.NOT_FOUND, Some(Array(ErrorCodes.RESOURCE_NOT_FOUND)))
|
||||
sender ! new StartPollReplyMessage(mProps.meetingID, mProps.recorded, result, msg.requesterId, msg.pollId)
|
||||
sender ! new StartPollReplyMessage(mProps.meetingID, mProps.recorded, result, msg.requesterId, pollId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def createPoll(msg: StartPollRequest) {
|
||||
PollFactory.createPoll(msg.pollId, msg.pollType) match {
|
||||
case Some(poll) => {
|
||||
pollModel.addPoll(poll)
|
||||
}
|
||||
case None => {
|
||||
val result = new RequestResult(StatusCodes.NOT_ACCEPTABLE, Some(Array(ErrorCodes.INVALID_DATA)))
|
||||
sender ! new StartPollReplyMessage(mProps.meetingID, mProps.recorded, result, msg.requesterId, msg.pollId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
def handleCreatePollRequest(msg: CreatePollRequest) {
|
||||
PollFactory.createPoll(msg.pollId, msg.pollType) match {
|
||||
case Some(poll) => {
|
||||
pollModel.addPoll(poll)
|
||||
outGW.send(new PollCreatedMessage(mProps.meetingID, mProps.recorded, msg.requesterId, msg.pollId, poll.toPollVO()))
|
||||
}
|
||||
case None => {
|
||||
val result = new RequestResult(StatusCodes.NOT_ACCEPTABLE, Some(Array(ErrorCodes.INVALID_DATA)))
|
||||
sender ! new CreatePollReplyMessage(mProps.meetingID, mProps.recorded, result, msg.requesterId, msg.pollId, msg.pollType)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
private def handleRespondToPoll(poll: SimplePollResultOutVO, msg: RespondToPollRequest) {
|
||||
if (hasUser(msg.requesterId)) {
|
||||
@ -137,7 +126,7 @@ trait PollApp {
|
||||
*/
|
||||
val questionId = 0
|
||||
pollModel.respondToQuestion(poll.id, questionId, msg.answerId, responder)
|
||||
users.getCurrentPresenter foreach { cp =>
|
||||
usersModel.getCurrentPresenter foreach { cp =>
|
||||
pollModel.getSimplePollResult(poll.id) foreach { updatedPoll =>
|
||||
outGW.send(new UserRespondedToPollMessage(mProps.meetingID, mProps.recorded, cp.userID, msg.pollId, updatedPoll))
|
||||
}
|
||||
|
@ -9,11 +9,12 @@ class PollModel {
|
||||
|
||||
private var currentPoll: Option[PollVO] = None
|
||||
|
||||
/**
|
||||
* *
|
||||
* Uncomment to create sample polls for manual testing purposes
|
||||
*/
|
||||
//createSamplePoll
|
||||
def getRunningPollThatStartsWith(pollId: String): Option[PollVO] = {
|
||||
for {
|
||||
poll <- polls.values find { poll => poll.id.startsWith(pollId) && poll.isRunning() }
|
||||
} yield poll.toPollVO()
|
||||
|
||||
}
|
||||
|
||||
def numPolls(): Int = {
|
||||
polls.size
|
||||
@ -125,64 +126,4 @@ class PollModel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ******************************************************
|
||||
* Some pre-created polls for testing and simulation so we don't have
|
||||
* to manually generate polls when testing the UI.
|
||||
*/
|
||||
/*
|
||||
def createSamplePoll() {
|
||||
addSamplePoll1()
|
||||
addSamplePoll2()
|
||||
addSamplePoll3()
|
||||
}
|
||||
|
||||
def addSamplePoll1() {
|
||||
val r1 = new ResponseVO("0", "Visa")
|
||||
val r2 = new ResponseVO("1", "MasterCard")
|
||||
val r3 = new ResponseVO("2", "AmEx")
|
||||
val r4 = new ResponseVO("3", "Diners Club")
|
||||
|
||||
var q = new QuestionVO("q1", false, "What type of credit card do you prefer?", Array(r1, r2, r3, r4))
|
||||
val pvo = new PollVO("pollID-101", "Preferred Credit Card", Array(q))
|
||||
|
||||
createPoll(pvo)
|
||||
|
||||
respondToQuestion("pollID-101", "q1", "1", new Responder("user1", "Juan Tamad"))
|
||||
respondToQuestion("pollID-101", "q1", "0", new Responder("user2", "Asyong Aksaya"))
|
||||
}
|
||||
|
||||
def addSamplePoll2() {
|
||||
val r1 = new ResponseVO("0", "Visa")
|
||||
val r2 = new ResponseVO("1", "MasterCard")
|
||||
val r3 = new ResponseVO("2", "AmEx")
|
||||
val r4 = new ResponseVO("3", "Diners Club")
|
||||
|
||||
var q = new QuestionVO("q1", true, "Which credit cards do you own?", Array(r1, r2, r3, r4))
|
||||
val pvo = new PollVO("pollID-102", "Owned Credit Cards", Array(q))
|
||||
|
||||
createPoll(pvo)
|
||||
|
||||
respondToQuestion("pollID-102", "q1", "1", new Responder("user1", "Juan Tamad"))
|
||||
respondToQuestion("pollID-102", "q1", "0", new Responder("user2", "Asyong Aksaya"))
|
||||
}
|
||||
|
||||
def addSamplePoll3() {
|
||||
val r1 = new ResponseVO("0", "Dumaguete")
|
||||
val r2 = new ResponseVO("1", "Cebu")
|
||||
val r3 = new ResponseVO("2", "Zamboanga")
|
||||
val r4 = new ResponseVO("3", "None of the above")
|
||||
|
||||
var q = new QuestionVO("q1", true, "What is the capital of the Philippines?", Array(r1, r2, r3, r4))
|
||||
val pvo = new PollVO("pollID-103", "Philippine Capital", Array(q))
|
||||
|
||||
createPoll(pvo)
|
||||
|
||||
respondToQuestion("pollID-103", "q1", "1", new Responder("user1", "Juan Tamad"))
|
||||
respondToQuestion("pollID-103", "q1", "0", new Responder("user2", "Asyong"))
|
||||
respondToQuestion("pollID-103", "q1", "2", new Responder("user3", "Pedro"))
|
||||
respondToQuestion("pollID-103", "q1", "3", new Responder("user4", "Aksaya"))
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
@ -4,19 +4,12 @@ import org.bigbluebutton.core.api._
|
||||
import org.bigbluebutton.core.MeetingActor
|
||||
import com.google.gson.Gson
|
||||
|
||||
case class CurrentPresenter(userId: String, name: String, assignedBy: String)
|
||||
|
||||
case class CurrentPresentationInfo(presenter: CurrentPresenter,
|
||||
presentations: Seq[Presentation])
|
||||
case class CursorLocation(xPercent: Double = 0D, yPercent: Double = 0D)
|
||||
|
||||
trait PresentationApp {
|
||||
this: MeetingActor =>
|
||||
|
||||
val outGW: MessageOutGateway
|
||||
|
||||
private var cursorLocation = new CursorLocation
|
||||
private val presModel = new PresentationModel
|
||||
|
||||
def handlePreuploadedPresentations(msg: PreuploadedPresentations) {
|
||||
val pres = msg.presentations
|
||||
@ -83,7 +76,7 @@ trait PresentationApp {
|
||||
def handleGetPresentationInfo(msg: GetPresentationInfo) {
|
||||
// println("PresentationApp : handleGetPresentationInfo GetPresentationInfo for meeting [" + msg.meetingID + "] [" + msg.requesterID + "]" )
|
||||
|
||||
val curPresenter = users.getCurrentPresenterInfo();
|
||||
val curPresenter = usersModel.getCurrentPresenterInfo();
|
||||
val presenter = new CurrentPresenter(curPresenter.presenterID, curPresenter.presenterName, curPresenter.assignedBy)
|
||||
val presentations = presModel.getPresentations
|
||||
val presentationInfo = new CurrentPresentationInfo(presenter, presentations)
|
||||
@ -108,9 +101,15 @@ trait PresentationApp {
|
||||
presModel.changePage(msg.page) foreach { page =>
|
||||
// println("Switching page for meeting=[" + msg.meetingID + "] page=[" + page.id + "]")
|
||||
outGW.send(new GotoSlideOutMsg(mProps.meetingID, mProps.recorded, page))
|
||||
|
||||
}
|
||||
// println("*** After change page ****")
|
||||
// printPresentations
|
||||
|
||||
usersModel.getCurrentPresenter() foreach { pres =>
|
||||
this.context.self ! StopPollRequest(mProps.meetingID, pres.userID)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def handleSharePresentation(msg: SharePresentation) {
|
||||
|
@ -1,5 +1,8 @@
|
||||
package org.bigbluebutton.core.apps
|
||||
|
||||
case class CurrentPresenter(userId: String, name: String, assignedBy: String)
|
||||
case class CurrentPresentationInfo(presenter: CurrentPresenter, presentations: Seq[Presentation])
|
||||
case class CursorLocation(xPercent: Double = 0D, yPercent: Double = 0D)
|
||||
case class Presentation(id: String, name: String, current: Boolean = false,
|
||||
pages: scala.collection.immutable.HashMap[String, Page])
|
||||
|
||||
@ -31,6 +34,13 @@ class PresentationModel {
|
||||
pres.pages.values find (p => p.current)
|
||||
}
|
||||
|
||||
def getCurrentPage(): Option[Page] = {
|
||||
for {
|
||||
curPres <- getCurrentPresentation()
|
||||
curPage <- getCurrentPage(curPres)
|
||||
} yield curPage
|
||||
}
|
||||
|
||||
def remove(presId: String): Option[Presentation] = {
|
||||
val pres = presentations.get(presId)
|
||||
pres foreach (p => presentations -= p.id)
|
||||
|
@ -13,29 +13,29 @@ trait UsersApp {
|
||||
val outGW: MessageOutGateway
|
||||
|
||||
def hasUser(userID: String): Boolean = {
|
||||
users.hasUser(userID)
|
||||
usersModel.hasUser(userID)
|
||||
}
|
||||
|
||||
def getUser(userID: String): Option[UserVO] = {
|
||||
users.getUser(userID)
|
||||
usersModel.getUser(userID)
|
||||
}
|
||||
|
||||
def handleUserConnectedToGlobalAudio(msg: UserConnectedToGlobalAudio) {
|
||||
val user = users.getUserWithExternalId(msg.userid)
|
||||
val user = usersModel.getUserWithExternalId(msg.userid)
|
||||
user foreach { u =>
|
||||
val vu = u.voiceUser.copy(talking = false)
|
||||
val uvo = u.copy(listenOnly = true, voiceUser = vu)
|
||||
users.addUser(uvo)
|
||||
usersModel.addUser(uvo)
|
||||
log.info("UserConnectedToGlobalAudio: mid=[" + mProps.meetingID + "] uid=[" + uvo.userID + "]")
|
||||
outGW.send(new UserListeningOnly(mProps.meetingID, mProps.recorded, uvo.userID, uvo.listenOnly))
|
||||
}
|
||||
}
|
||||
|
||||
def handleUserDisconnectedFromGlobalAudio(msg: UserDisconnectedFromGlobalAudio) {
|
||||
val user = users.getUserWithExternalId(msg.userid)
|
||||
val user = usersModel.getUserWithExternalId(msg.userid)
|
||||
user foreach { u =>
|
||||
val uvo = u.copy(listenOnly = false)
|
||||
users.addUser(uvo)
|
||||
usersModel.addUser(uvo)
|
||||
log.info("UserDisconnectedToGlobalAudio: mid=[" + mProps.meetingID + "] uid=[" + uvo.userID + "]")
|
||||
outGW.send(new UserListeningOnly(mProps.meetingID, mProps.recorded, uvo.userID, uvo.listenOnly))
|
||||
}
|
||||
@ -61,14 +61,14 @@ trait UsersApp {
|
||||
meetingModel.unmuteMeeting()
|
||||
}
|
||||
outGW.send(new MeetingMuted(mProps.meetingID, mProps.recorded, meetingModel.isMeetingMuted()))
|
||||
users.getUsers foreach { u =>
|
||||
usersModel.getUsers foreach { u =>
|
||||
outGW.send(new MuteVoiceUser(mProps.meetingID, mProps.recorded, msg.requesterID, u.userID, mProps.voiceBridge, u.voiceUser.userId, msg.mute))
|
||||
}
|
||||
}
|
||||
|
||||
def handleValidateAuthToken(msg: ValidateAuthToken) {
|
||||
// println("*************** Got ValidateAuthToken message ********************" )
|
||||
users.getRegisteredUserWithToken(msg.token) match {
|
||||
usersModel.getRegisteredUserWithToken(msg.token) match {
|
||||
case Some(u) =>
|
||||
{
|
||||
val replyTo = mProps.meetingID + '/' + msg.userId
|
||||
@ -103,7 +103,7 @@ trait UsersApp {
|
||||
sendMeetingHasEnded(msg.userID)
|
||||
} else {
|
||||
val regUser = new RegisteredUser(msg.userID, msg.extUserID, msg.name, msg.role, msg.authToken)
|
||||
users.addRegisteredUser(msg.authToken, regUser)
|
||||
usersModel.addRegisteredUser(msg.authToken, regUser)
|
||||
|
||||
log.info("Register user success: mid=[" + mProps.meetingID + "] uid=[" + msg.userID + "]")
|
||||
outGW.send(new UserRegistered(mProps.meetingID, mProps.recorded, regUser))
|
||||
@ -117,7 +117,7 @@ trait UsersApp {
|
||||
|
||||
def handleMuteUserRequest(msg: MuteUserRequest) {
|
||||
// println("Received mute user request uid=[" + msg.userID + "] mute=[" + msg.mute + "]")
|
||||
users.getUser(msg.userID) match {
|
||||
usersModel.getUser(msg.userID) match {
|
||||
case Some(u) => {
|
||||
// println("Sending mute user request uid=[" + msg.userID + "] mute=[" + msg.mute + "]")
|
||||
log.info("Muting user: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]")
|
||||
@ -132,7 +132,7 @@ trait UsersApp {
|
||||
|
||||
def handleEjectUserRequest(msg: EjectUserFromVoiceRequest) {
|
||||
// println("Received eject user request uid=[" + msg.userID + "]")
|
||||
users.getUser(msg.userId) match {
|
||||
usersModel.getUser(msg.userId) match {
|
||||
case Some(u) => {
|
||||
if (u.voiceUser.joined) {
|
||||
log.info("Ejecting user from voice: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]")
|
||||
@ -147,24 +147,24 @@ trait UsersApp {
|
||||
//println("*************** Reply with current lock settings ********************")
|
||||
|
||||
//reusing the existing handle for NewPermissionsSettings to reply to the GetLockSettings request
|
||||
outGW.send(new NewPermissionsSetting(mProps.meetingID, msg.userId, meetingModel.getPermissions(), users.getUsers))
|
||||
outGW.send(new NewPermissionsSetting(mProps.meetingID, msg.userId, meetingModel.getPermissions(), usersModel.getUsers))
|
||||
}
|
||||
|
||||
def handleSetLockSettings(msg: SetLockSettings) {
|
||||
// println("*************** Received new lock settings ********************")
|
||||
if (!permissionsEqual(msg.settings)) {
|
||||
newPermissions(msg.settings)
|
||||
outGW.send(new NewPermissionsSetting(mProps.meetingID, msg.setByUser, meetingModel.getPermissions, users.getUsers))
|
||||
outGW.send(new NewPermissionsSetting(mProps.meetingID, msg.setByUser, meetingModel.getPermissions, usersModel.getUsers))
|
||||
|
||||
handleLockLayout(msg.settings.lockedLayout, msg.setByUser)
|
||||
}
|
||||
}
|
||||
|
||||
def handleLockUserRequest(msg: LockUserRequest) {
|
||||
users.getUser(msg.userID) match {
|
||||
usersModel.getUser(msg.userID) match {
|
||||
case Some(u) => {
|
||||
val uvo = u.copy(locked = msg.lock)
|
||||
users.addUser(uvo)
|
||||
usersModel.addUser(uvo)
|
||||
|
||||
log.info("Lock user: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "] lock=[" + msg.lock + "]")
|
||||
outGW.send(new UserLocked(mProps.meetingID, u.userID, msg.lock))
|
||||
@ -179,7 +179,7 @@ trait UsersApp {
|
||||
if (!meetingModel.permisionsInitialized()) {
|
||||
meetingModel.initializePermissions()
|
||||
newPermissions(msg.settings)
|
||||
outGW.send(new PermissionsSettingInitialized(msg.meetingID, msg.settings, users.getUsers))
|
||||
outGW.send(new PermissionsSettingInitialized(msg.meetingID, msg.settings, usersModel.getUsers))
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +196,7 @@ trait UsersApp {
|
||||
def usersWhoAreNotPresenter(): Array[UserVO] = {
|
||||
val au = ArrayBuffer[UserVO]()
|
||||
|
||||
users.getUsers foreach { u =>
|
||||
usersModel.getUsers foreach { u =>
|
||||
if (!u.presenter) {
|
||||
au += u
|
||||
}
|
||||
@ -205,28 +205,28 @@ trait UsersApp {
|
||||
}
|
||||
|
||||
def handleUserRaiseHand(msg: UserRaiseHand) {
|
||||
users.getUser(msg.userId) foreach { user =>
|
||||
usersModel.getUser(msg.userId) foreach { user =>
|
||||
val uvo = user.copy(raiseHand = true)
|
||||
users.addUser(uvo)
|
||||
usersModel.addUser(uvo)
|
||||
outGW.send(new UserRaisedHand(mProps.meetingID, mProps.recorded, uvo.raiseHand, uvo.userID))
|
||||
}
|
||||
}
|
||||
|
||||
def handleUserLowerHand(msg: UserLowerHand) {
|
||||
users.getUser(msg.userId) foreach { user =>
|
||||
usersModel.getUser(msg.userId) foreach { user =>
|
||||
val uvo = user.copy(raiseHand = false)
|
||||
users.addUser(uvo)
|
||||
usersModel.addUser(uvo)
|
||||
outGW.send(new UserLoweredHand(mProps.meetingID, mProps.recorded, uvo.raiseHand, uvo.userID, msg.loweredBy))
|
||||
}
|
||||
}
|
||||
|
||||
def handleEjectUserFromMeeting(msg: EjectUserFromMeeting) {
|
||||
users.getUser(msg.userId) foreach { user =>
|
||||
usersModel.getUser(msg.userId) foreach { user =>
|
||||
if (user.voiceUser.joined) {
|
||||
outGW.send(new EjectVoiceUser(mProps.meetingID, mProps.recorded, msg.ejectedBy, msg.userId, mProps.voiceBridge, user.voiceUser.userId))
|
||||
}
|
||||
|
||||
users.removeUser(msg.userId)
|
||||
usersModel.removeUser(msg.userId)
|
||||
|
||||
log.info("Ejecting user from meeting: mid=[" + mProps.meetingID + "]uid=[" + msg.userId + "]")
|
||||
outGW.send(new UserEjectedFromMeeting(mProps.meetingID, mProps.recorded, msg.userId, msg.ejectedBy))
|
||||
@ -237,46 +237,45 @@ trait UsersApp {
|
||||
}
|
||||
|
||||
def handleUserShareWebcam(msg: UserShareWebcam) {
|
||||
users.getUser(msg.userId) foreach { user =>
|
||||
usersModel.getUser(msg.userId) foreach { user =>
|
||||
val streams = user.webcamStreams + msg.stream
|
||||
val uvo = user.copy(hasStream = true, webcamStreams = streams)
|
||||
users.addUser(uvo)
|
||||
usersModel.addUser(uvo)
|
||||
log.info("User shared webcam: mid=[" + mProps.meetingID + "] uid=[" + uvo.userID + "] sharedStream=[" + msg.stream + "] streams=[" + streams + "]")
|
||||
outGW.send(new UserSharedWebcam(mProps.meetingID, mProps.recorded, uvo.userID, msg.stream))
|
||||
}
|
||||
}
|
||||
|
||||
def handleUserunshareWebcam(msg: UserUnshareWebcam) {
|
||||
users.getUser(msg.userId) foreach { user =>
|
||||
usersModel.getUser(msg.userId) foreach { user =>
|
||||
val streams = user.webcamStreams - msg.stream
|
||||
val uvo = user.copy(hasStream = (!streams.isEmpty), webcamStreams = streams)
|
||||
users.addUser(uvo)
|
||||
usersModel.addUser(uvo)
|
||||
log.info("User unshared webcam: mid=[" + mProps.meetingID + "] uid=[" + uvo.userID + "] unsharedStream=[" + msg.stream + "] streams=[" + streams + "]")
|
||||
outGW.send(new UserUnsharedWebcam(mProps.meetingID, mProps.recorded, uvo.userID, msg.stream))
|
||||
}
|
||||
}
|
||||
|
||||
def handleChangeUserStatus(msg: ChangeUserStatus): Unit = {
|
||||
if (users.hasUser(msg.userID)) {
|
||||
if (usersModel.hasUser(msg.userID)) {
|
||||
outGW.send(new UserStatusChange(mProps.meetingID, mProps.recorded, msg.userID, msg.status, msg.value))
|
||||
}
|
||||
}
|
||||
|
||||
def handleGetUsers(msg: GetUsers): Unit = {
|
||||
outGW.send(new GetUsersReply(msg.meetingID, msg.requesterID, users.getUsers))
|
||||
outGW.send(new GetUsersReply(msg.meetingID, msg.requesterID, usersModel.getUsers))
|
||||
}
|
||||
|
||||
def handleUserJoin(msg: UserJoining): Unit = {
|
||||
val regUser = users.getRegisteredUserWithToken(msg.authToken)
|
||||
val regUser = usersModel.getRegisteredUserWithToken(msg.authToken)
|
||||
regUser foreach { ru =>
|
||||
val vu = new VoiceUser(msg.userID, msg.userID, ru.name, ru.name,
|
||||
false, false, false, false)
|
||||
val vu = new VoiceUser(msg.userID, msg.userID, ru.name, ru.name, false, false, false, false)
|
||||
val uvo = new UserVO(msg.userID, ru.externId, ru.name,
|
||||
ru.role, raiseHand = false, presenter = false,
|
||||
hasStream = false, locked = getInitialLockStatus(ru.role),
|
||||
webcamStreams = new ListSet[String](), phoneUser = false, vu, listenOnly = false)
|
||||
|
||||
users.addUser(uvo)
|
||||
usersModel.addUser(uvo)
|
||||
|
||||
log.info("User joined meeting: mid=[" + mProps.meetingID + "] uid=[" + uvo.userID + "] role=["
|
||||
+ uvo.role + "] locked=[" + uvo.locked + "] permissions.lockOnJoin=[" + meetingModel.getPermissions().lockOnJoin
|
||||
@ -286,7 +285,7 @@ trait UsersApp {
|
||||
outGW.send(new MeetingState(mProps.meetingID, mProps.recorded, uvo.userID, meetingModel.getPermissions(), meetingModel.isMeetingMuted()))
|
||||
|
||||
// Become presenter if the only moderator
|
||||
if (users.numModerators == 1) {
|
||||
if (usersModel.numModerators == 1) {
|
||||
if (ru.role == Role.MODERATOR) {
|
||||
assignNewPresenter(msg.userID, ru.name, msg.userID)
|
||||
}
|
||||
@ -297,22 +296,26 @@ trait UsersApp {
|
||||
}
|
||||
|
||||
def handleUserLeft(msg: UserLeaving): Unit = {
|
||||
if (users.hasUser(msg.userID)) {
|
||||
val user = users.removeUser(msg.userID)
|
||||
if (usersModel.hasUser(msg.userID)) {
|
||||
val user = usersModel.removeUser(msg.userID)
|
||||
user foreach { u =>
|
||||
log.info("User left meeting: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]")
|
||||
outGW.send(new UserLeft(msg.meetingID, mProps.recorded, u))
|
||||
|
||||
if (u.presenter) {
|
||||
// Stop poll if one is running as presenter left.
|
||||
this.context.self ! StopPollRequest(mProps.meetingID, u.userID)
|
||||
|
||||
/* The current presenter has left the meeting. Find a moderator and make
|
||||
* him presenter. This way, if there is a moderator in the meeting, there
|
||||
* will always be a presenter.
|
||||
*/
|
||||
val moderator = users.findAModerator()
|
||||
val moderator = usersModel.findAModerator()
|
||||
moderator.foreach { mod =>
|
||||
log.info("Presenter left meeting: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]. Making user=[" + mod.userID + "] presenter.")
|
||||
assignNewPresenter(mod.userID, mod.name, mod.userID)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,7 +329,7 @@ trait UsersApp {
|
||||
}
|
||||
|
||||
def handleUserJoinedVoiceFromPhone(msg: UserJoinedVoiceConfMessage) = {
|
||||
val user = users.getUserWithVoiceUserId(msg.voiceUserId) match {
|
||||
val user = usersModel.getUserWithVoiceUserId(msg.voiceUserId) match {
|
||||
case Some(user) => {
|
||||
log.info("Voice user=[" + msg.voiceUserId + "] is already in conf=[" + mProps.voiceBridge + "]. Must be duplicate message.")
|
||||
}
|
||||
@ -334,7 +337,7 @@ trait UsersApp {
|
||||
// No current web user. This means that the user called in through
|
||||
// the phone. We need to generate a new user as we are not able
|
||||
// to match with a web user.
|
||||
val webUserId = users.generateWebUserId
|
||||
val webUserId = usersModel.generateWebUserId
|
||||
val vu = new VoiceUser(msg.voiceUserId, webUserId, msg.callerIdName, msg.callerIdNum,
|
||||
true, false, false, false)
|
||||
|
||||
@ -345,7 +348,7 @@ trait UsersApp {
|
||||
hasStream = false, locked = getInitialLockStatus(Role.VIEWER), webcamStreams = new ListSet[String](),
|
||||
phoneUser = true, vu, listenOnly = false)
|
||||
|
||||
users.addUser(uvo)
|
||||
usersModel.addUser(uvo)
|
||||
log.info("New user joined voice for user [" + uvo.name + "] userid=[" + webUserId + "]")
|
||||
outGW.send(new UserJoined(mProps.meetingID, mProps.recorded, uvo))
|
||||
|
||||
@ -358,7 +361,7 @@ trait UsersApp {
|
||||
}
|
||||
|
||||
def startRecordingVoiceConference() {
|
||||
if (users.numUsersInVoiceConference == 1 && mProps.recorded) {
|
||||
if (usersModel.numUsersInVoiceConference == 1 && mProps.recorded) {
|
||||
log.info("********** Send START RECORDING [" + mProps.voiceBridge + "]")
|
||||
outGW.send(new StartRecordingVoiceConf(mProps.meetingID, mProps.recorded, mProps.voiceBridge))
|
||||
}
|
||||
@ -367,11 +370,11 @@ trait UsersApp {
|
||||
def handleUserJoinedVoiceConfMessage(msg: UserJoinedVoiceConfMessage) = {
|
||||
log.info("Received user joined voice for user [" + msg.callerIdName + "] userid=[" + msg.userId + "]")
|
||||
|
||||
users.getUserWithExternalId(msg.userId) match {
|
||||
usersModel.getUserWithExternalId(msg.userId) match {
|
||||
case Some(user) => {
|
||||
val vu = new VoiceUser(msg.voiceUserId, msg.userId, msg.callerIdName, msg.callerIdNum, true, false, msg.muted, msg.talking)
|
||||
val nu = user.copy(voiceUser = vu)
|
||||
users.addUser(nu)
|
||||
usersModel.addUser(nu)
|
||||
log.info("User joined voice for user [" + nu.name + "] userid=[" + msg.userId + "]")
|
||||
outGW.send(new UserJoinedVoice(mProps.meetingID, mProps.recorded, mProps.voiceBridge, nu))
|
||||
|
||||
@ -389,25 +392,25 @@ trait UsersApp {
|
||||
}
|
||||
|
||||
def stopRecordingVoiceConference() {
|
||||
if (users.numUsersInVoiceConference == 0 && mProps.recorded) {
|
||||
if (usersModel.numUsersInVoiceConference == 0 && mProps.recorded) {
|
||||
log.info("********** Send STOP RECORDING [" + mProps.voiceBridge + "]")
|
||||
outGW.send(new StopRecordingVoiceConf(mProps.meetingID, mProps.recorded, mProps.voiceBridge, meetingModel.getVoiceRecordingFilename()))
|
||||
}
|
||||
}
|
||||
|
||||
def handleUserLeftVoiceConfMessage(msg: UserLeftVoiceConfMessage) {
|
||||
users.getUserWithVoiceUserId(msg.voiceUserId) foreach { user =>
|
||||
usersModel.getUserWithVoiceUserId(msg.voiceUserId) foreach { user =>
|
||||
val vu = new VoiceUser(user.userID, user.userID, user.name, user.name, false, false, false, false)
|
||||
val nu = user.copy(voiceUser = vu)
|
||||
users.addUser(nu)
|
||||
usersModel.addUser(nu)
|
||||
|
||||
// println("Received voice user left =[" + user.name + "] wid=[" + msg.userId + "]" )
|
||||
log.info("Received user left voice for user [" + nu.name + "] userid=[" + msg.voiceUserId + "]")
|
||||
outGW.send(new UserLeftVoice(mProps.meetingID, mProps.recorded, mProps.voiceBridge, nu))
|
||||
|
||||
if (user.phoneUser) {
|
||||
if (users.hasUser(user.userID)) {
|
||||
val userLeaving = users.removeUser(user.userID)
|
||||
if (usersModel.hasUser(user.userID)) {
|
||||
val userLeaving = usersModel.removeUser(user.userID)
|
||||
userLeaving foreach (u => outGW.send(new UserLeft(mProps.meetingID, mProps.recorded, u)))
|
||||
}
|
||||
}
|
||||
@ -417,21 +420,21 @@ trait UsersApp {
|
||||
}
|
||||
|
||||
def handleUserMutedInVoiceConfMessage(msg: UserMutedInVoiceConfMessage) {
|
||||
users.getUserWithVoiceUserId(msg.voiceUserId) foreach { user =>
|
||||
usersModel.getUserWithVoiceUserId(msg.voiceUserId) foreach { user =>
|
||||
val talking: Boolean = if (msg.muted) false else user.voiceUser.talking
|
||||
val nv = user.voiceUser.copy(muted = msg.muted, talking = talking)
|
||||
val nu = user.copy(voiceUser = nv)
|
||||
users.addUser(nu)
|
||||
usersModel.addUser(nu)
|
||||
// println("Received voice muted=[" + msg.muted + "] wid=[" + msg.userId + "]" )
|
||||
outGW.send(new UserVoiceMuted(mProps.meetingID, mProps.recorded, mProps.voiceBridge, nu))
|
||||
}
|
||||
}
|
||||
|
||||
def handleUserTalkingInVoiceConfMessage(msg: UserTalkingInVoiceConfMessage) {
|
||||
users.getUserWithVoiceUserId(msg.voiceUserId) foreach { user =>
|
||||
usersModel.getUserWithVoiceUserId(msg.voiceUserId) foreach { user =>
|
||||
val nv = user.voiceUser.copy(talking = msg.talking)
|
||||
val nu = user.copy(voiceUser = nv)
|
||||
users.addUser(nu)
|
||||
usersModel.addUser(nu)
|
||||
// println("Received voice talking=[" + msg.talking + "] wid=[" + msg.userId + "]" )
|
||||
outGW.send(new UserVoiceTalking(mProps.meetingID, mProps.recorded, mProps.voiceBridge, nu))
|
||||
}
|
||||
@ -442,20 +445,20 @@ trait UsersApp {
|
||||
}
|
||||
|
||||
def assignNewPresenter(newPresenterID: String, newPresenterName: String, assignedBy: String) {
|
||||
if (users.hasUser(newPresenterID)) {
|
||||
if (usersModel.hasUser(newPresenterID)) {
|
||||
|
||||
users.getCurrentPresenter match {
|
||||
usersModel.getCurrentPresenter match {
|
||||
case Some(curPres) => {
|
||||
users.unbecomePresenter(curPres.userID)
|
||||
usersModel.unbecomePresenter(curPres.userID)
|
||||
outGW.send(new UserStatusChange(mProps.meetingID, mProps.recorded, curPres.userID, "presenter", false: java.lang.Boolean))
|
||||
}
|
||||
case None => // do nothing
|
||||
}
|
||||
|
||||
users.getUser(newPresenterID) match {
|
||||
usersModel.getUser(newPresenterID) match {
|
||||
case Some(newPres) => {
|
||||
users.becomePresenter(newPres.userID)
|
||||
users.setCurrentPresenterInfo(new Presenter(newPresenterID, newPresenterName, assignedBy))
|
||||
usersModel.becomePresenter(newPres.userID)
|
||||
usersModel.setCurrentPresenterInfo(new Presenter(newPresenterID, newPresenterName, assignedBy))
|
||||
outGW.send(new PresenterAssigned(mProps.meetingID, mProps.recorded, new Presenter(newPresenterID, newPresenterName, assignedBy)))
|
||||
outGW.send(new UserStatusChange(mProps.meetingID, mProps.recorded, newPresenterID, "presenter", true: java.lang.Boolean))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user