- stop poll if presenter leaves or presentation page changed

This commit is contained in:
Richard Alam 2015-06-24 20:32:00 +00:00
parent be9becacc1
commit 36601345c2
11 changed files with 133 additions and 189 deletions

View File

@ -439,11 +439,11 @@ class BigBlueButtonInGW(val system: ActorSystem, outGW: MessageOutGateway, voice
} }
def startPoll(meetingId: String, requesterId: String, pollId: String, pollType: String) { 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) { 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) { def showPollResult(meetingId: String, requesterId: String, pollId: String, show: java.lang.Boolean) {

View File

@ -10,11 +10,7 @@ import org.bigbluebutton.core.util._
import scala.concurrent.duration._ import scala.concurrent.duration._
import org.bigbluebutton.core.apps.{ PollApp, UsersApp, PresentationApp, LayoutApp, ChatApp, WhiteboardApp } import org.bigbluebutton.core.apps.{ PollApp, UsersApp, PresentationApp, LayoutApp, ChatApp, WhiteboardApp }
import org.bigbluebutton.core.apps.{ ChatModel, LayoutModel, UsersModel, PollModel, WhiteboardModel } import org.bigbluebutton.core.apps.{ ChatModel, LayoutModel, UsersModel, PollModel, WhiteboardModel }
import org.bigbluebutton.core.apps.PresentationModel
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)
object MeetingActor { object MeetingActor {
def props(mProps: MeetingProperties, outGW: MessageOutGateway): Props = def props(mProps: MeetingProperties, outGW: MessageOutGateway): Props =
@ -29,9 +25,10 @@ class MeetingActor(val mProps: MeetingProperties, val outGW: MessageOutGateway)
val chatModel = new ChatModel() val chatModel = new ChatModel()
val layoutModel = new LayoutModel() val layoutModel = new LayoutModel()
val meetingModel = new MeetingModel() val meetingModel = new MeetingModel()
val users = new UsersModel() val usersModel = new UsersModel()
val pollModel = new PollModel() val pollModel = new PollModel()
val wbModel = new WhiteboardModel() val wbModel = new WhiteboardModel()
val presModel = new PresentationModel()
import context.dispatcher import context.dispatcher
context.system.scheduler.schedule(2 seconds, 5 seconds, self, "MonitorNumberOfWebUsers") context.system.scheduler.schedule(2 seconds, 5 seconds, self, "MonitorNumberOfWebUsers")
@ -197,13 +194,13 @@ class MeetingActor(val mProps: MeetingProperties, val outGW: MessageOutGateway)
} }
def webUserJoined() { def webUserJoined() {
if (users.numWebUsers > 0) { if (usersModel.numWebUsers > 0) {
meetingModel.resetLastWebUserLeftOn() meetingModel.resetLastWebUserLeftOn()
} }
} }
def startRecordingIfAutoStart() { 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 + "]") log.info("Auto start recording for meeting=[" + mProps.meetingID + "]")
meetingModel.recordingStarted() meetingModel.recordingStarted()
outGW.send(new RecordingStatusChanged(mProps.meetingID, mProps.recorded, "system", meetingModel.isRecording())) 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() { 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) log.info("Last web user left. Auto stopping recording for meeting=[{}", mProps.meetingID)
meetingModel.recordingStopped() meetingModel.recordingStopped()
outGW.send(new RecordingStatusChanged(mProps.meetingID, mProps.recorded, "system", meetingModel.isRecording())) 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() { def startCheckingIfWeNeedToEndVoiceConf() {
if (users.numWebUsers == 0) { if (usersModel.numWebUsers == 0) {
meetingModel.lastWebUserLeft() meetingModel.lastWebUserLeft()
log.debug("MonitorNumberOfWebUsers started for meeting [" + mProps.meetingID + "]") log.debug("MonitorNumberOfWebUsers started for meeting [" + mProps.meetingID + "]")
} }
@ -227,7 +224,7 @@ class MeetingActor(val mProps: MeetingProperties, val outGW: MessageOutGateway)
def handleMonitorNumberOfWebUsers() { def handleMonitorNumberOfWebUsers() {
println("BACK TIMER") println("BACK TIMER")
if (users.numWebUsers == 0 && meetingModel.lastWebUserLeftOn > 0) { if (usersModel.numWebUsers == 0 && meetingModel.lastWebUserLeftOn > 0) {
if (timeNowInMinutes - meetingModel.lastWebUserLeftOn > 2) { if (timeNowInMinutes - meetingModel.lastWebUserLeftOn > 2) {
log.info("MonitorNumberOfWebUsers empty for meeting [" + mProps.meetingID + "]. Ejecting all users from voice.") log.info("MonitorNumberOfWebUsers empty for meeting [" + mProps.meetingID + "]. Ejecting all users from voice.")
outGW.send(new EjectAllVoiceUsers(mProps.meetingID, mProps.recorded, mProps.voiceBridge)) outGW.send(new EjectAllVoiceUsers(mProps.meetingID, mProps.recorded, mProps.voiceBridge))

View File

@ -3,6 +3,11 @@ package org.bigbluebutton.core
import org.bigbluebutton.core.api.Permissions import org.bigbluebutton.core.api.Permissions
import java.util.concurrent.TimeUnit 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 { class MeetingModel {
private var audioSettingsInited = false private var audioSettingsInited = false
private var permissionsInited = false private var permissionsInited = false

View File

@ -78,8 +78,8 @@ case class PresentationConversionCompleted(meetingID: String, messageKey: String
// Polling // Polling
//case class CreatePollRequest(meetingID: String, requesterId: String, pollId: String, pollType: String) extends InMessage //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 StartPollRequest(meetingID: String, requesterId: String, pollType: String) extends InMessage
case class StopPollRequest(meetingID: String, requesterId: String, pollId: 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 ShowPollResultRequest(meetingID: String, requesterId: String, pollId: String) extends InMessage
case class HidePollResultRequest(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 case class RespondToPollRequest(meetingID: String, requesterId: String, pollId: String, questionId: Int, answerId: Int) extends InMessage

View File

@ -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 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 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 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 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 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 case class PollHideResultMessage(meetingID: String, recorded: Boolean, requesterId: String, pollId: String) extends IOutMessage

View File

@ -45,14 +45,14 @@ trait LayoutApp {
def affectedUsers(): Array[UserVO] = { def affectedUsers(): Array[UserVO] = {
if (layoutModel.doesLayoutApplyToViewersOnly()) { if (layoutModel.doesLayoutApplyToViewersOnly()) {
val au = ArrayBuffer[UserVO]() val au = ArrayBuffer[UserVO]()
users.getUsers foreach { u => usersModel.getUsers foreach { u =>
if (!u.presenter && u.role != Role.MODERATOR) { if (!u.presenter && u.role != Role.MODERATOR) {
au += u au += u
} }
} }
au.toArray au.toArray
} else { } else {
users.getUsers usersModel.getUsers
} }
} }

View File

@ -15,7 +15,13 @@ trait PollApp {
} }
def handleGetCurrentPollRequest(msg: GetCurrentPollRequest) { 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) => { case Some(p) => {
if (p.started && p.stopped && p.showResult) { if (p.started && p.stopped && p.showResult) {
outGW.send(new GetCurrentPollReplyMessage(mProps.meetingID, mProps.recorded, msg.requesterId, true, Some(p))) outGW.send(new GetCurrentPollReplyMessage(mProps.meetingID, mProps.recorded, msg.requesterId, true, Some(p)))
@ -68,61 +74,44 @@ trait PollApp {
} }
def handleStopPollRequest(msg: StopPollRequest) { 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) => { case Some(poll) => {
pollModel.stopPoll(poll.id) 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 => { case None => {
val result = new RequestResult(StatusCodes.NOT_FOUND, Some(Array(ErrorCodes.RESOURCE_NOT_FOUND))) 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) { def handleStartPollRequest(msg: StartPollRequest) {
log.debug("Received StartPollRequest for pollId=[" + msg.pollId + "]") log.debug("Received StartPollRequest for pollType=[" + msg.pollType + "]")
createPoll(msg)
pollModel.getSimplePoll(msg.pollId) match { presModel.getCurrentPage() foreach { page =>
case Some(poll) => { val pollId = page.id + "/" + System.currentTimeMillis()
pollModel.startPoll(poll.id)
outGW.send(new PollStartedMessage(mProps.meetingID, mProps.recorded, msg.requesterId, msg.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)
}
}
}
private def createPoll(msg: StartPollRequest) { PollFactory.createPoll(pollId, msg.pollType) foreach (poll => pollModel.addPoll(poll))
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)
}
}
}
/* pollModel.getSimplePoll(pollId) match {
def handleCreatePollRequest(msg: CreatePollRequest) { case Some(poll) => {
PollFactory.createPoll(msg.pollId, msg.pollType) match { pollModel.startPoll(poll.id)
case Some(poll) => { outGW.send(new PollStartedMessage(mProps.meetingID, mProps.recorded, msg.requesterId, pollId, 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_FOUND, Some(Array(ErrorCodes.RESOURCE_NOT_FOUND)))
case None => { sender ! new StartPollReplyMessage(mProps.meetingID, mProps.recorded, result, msg.requesterId, pollId)
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) { private def handleRespondToPoll(poll: SimplePollResultOutVO, msg: RespondToPollRequest) {
if (hasUser(msg.requesterId)) { if (hasUser(msg.requesterId)) {
@ -137,7 +126,7 @@ trait PollApp {
*/ */
val questionId = 0 val questionId = 0
pollModel.respondToQuestion(poll.id, questionId, msg.answerId, responder) pollModel.respondToQuestion(poll.id, questionId, msg.answerId, responder)
users.getCurrentPresenter foreach { cp => usersModel.getCurrentPresenter foreach { cp =>
pollModel.getSimplePollResult(poll.id) foreach { updatedPoll => pollModel.getSimplePollResult(poll.id) foreach { updatedPoll =>
outGW.send(new UserRespondedToPollMessage(mProps.meetingID, mProps.recorded, cp.userID, msg.pollId, updatedPoll)) outGW.send(new UserRespondedToPollMessage(mProps.meetingID, mProps.recorded, cp.userID, msg.pollId, updatedPoll))
} }

View File

@ -9,11 +9,12 @@ class PollModel {
private var currentPoll: Option[PollVO] = None private var currentPoll: Option[PollVO] = None
/** def getRunningPollThatStartsWith(pollId: String): Option[PollVO] = {
* * for {
* Uncomment to create sample polls for manual testing purposes poll <- polls.values find { poll => poll.id.startsWith(pollId) && poll.isRunning() }
*/ } yield poll.toPollVO()
//createSamplePoll
}
def numPolls(): Int = { def numPolls(): Int = {
polls.size 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"))
}
*/
} }

View File

@ -4,19 +4,12 @@ import org.bigbluebutton.core.api._
import org.bigbluebutton.core.MeetingActor import org.bigbluebutton.core.MeetingActor
import com.google.gson.Gson 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 { trait PresentationApp {
this: MeetingActor => this: MeetingActor =>
val outGW: MessageOutGateway val outGW: MessageOutGateway
private var cursorLocation = new CursorLocation private var cursorLocation = new CursorLocation
private val presModel = new PresentationModel
def handlePreuploadedPresentations(msg: PreuploadedPresentations) { def handlePreuploadedPresentations(msg: PreuploadedPresentations) {
val pres = msg.presentations val pres = msg.presentations
@ -83,7 +76,7 @@ trait PresentationApp {
def handleGetPresentationInfo(msg: GetPresentationInfo) { def handleGetPresentationInfo(msg: GetPresentationInfo) {
// println("PresentationApp : handleGetPresentationInfo GetPresentationInfo for meeting [" + msg.meetingID + "] [" + msg.requesterID + "]" ) // 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 presenter = new CurrentPresenter(curPresenter.presenterID, curPresenter.presenterName, curPresenter.assignedBy)
val presentations = presModel.getPresentations val presentations = presModel.getPresentations
val presentationInfo = new CurrentPresentationInfo(presenter, presentations) val presentationInfo = new CurrentPresentationInfo(presenter, presentations)
@ -108,9 +101,15 @@ trait PresentationApp {
presModel.changePage(msg.page) foreach { page => presModel.changePage(msg.page) foreach { page =>
// println("Switching page for meeting=[" + msg.meetingID + "] page=[" + page.id + "]") // println("Switching page for meeting=[" + msg.meetingID + "] page=[" + page.id + "]")
outGW.send(new GotoSlideOutMsg(mProps.meetingID, mProps.recorded, page)) outGW.send(new GotoSlideOutMsg(mProps.meetingID, mProps.recorded, page))
} }
// println("*** After change page ****") // println("*** After change page ****")
// printPresentations // printPresentations
usersModel.getCurrentPresenter() foreach { pres =>
this.context.self ! StopPollRequest(mProps.meetingID, pres.userID)
}
} }
def handleSharePresentation(msg: SharePresentation) { def handleSharePresentation(msg: SharePresentation) {

View File

@ -1,5 +1,8 @@
package org.bigbluebutton.core.apps 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, case class Presentation(id: String, name: String, current: Boolean = false,
pages: scala.collection.immutable.HashMap[String, Page]) pages: scala.collection.immutable.HashMap[String, Page])
@ -31,6 +34,13 @@ class PresentationModel {
pres.pages.values find (p => p.current) 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] = { def remove(presId: String): Option[Presentation] = {
val pres = presentations.get(presId) val pres = presentations.get(presId)
pres foreach (p => presentations -= p.id) pres foreach (p => presentations -= p.id)

View File

@ -13,29 +13,29 @@ trait UsersApp {
val outGW: MessageOutGateway val outGW: MessageOutGateway
def hasUser(userID: String): Boolean = { def hasUser(userID: String): Boolean = {
users.hasUser(userID) usersModel.hasUser(userID)
} }
def getUser(userID: String): Option[UserVO] = { def getUser(userID: String): Option[UserVO] = {
users.getUser(userID) usersModel.getUser(userID)
} }
def handleUserConnectedToGlobalAudio(msg: UserConnectedToGlobalAudio) { def handleUserConnectedToGlobalAudio(msg: UserConnectedToGlobalAudio) {
val user = users.getUserWithExternalId(msg.userid) val user = usersModel.getUserWithExternalId(msg.userid)
user foreach { u => user foreach { u =>
val vu = u.voiceUser.copy(talking = false) val vu = u.voiceUser.copy(talking = false)
val uvo = u.copy(listenOnly = true, voiceUser = vu) val uvo = u.copy(listenOnly = true, voiceUser = vu)
users.addUser(uvo) usersModel.addUser(uvo)
log.info("UserConnectedToGlobalAudio: mid=[" + mProps.meetingID + "] uid=[" + uvo.userID + "]") log.info("UserConnectedToGlobalAudio: mid=[" + mProps.meetingID + "] uid=[" + uvo.userID + "]")
outGW.send(new UserListeningOnly(mProps.meetingID, mProps.recorded, uvo.userID, uvo.listenOnly)) outGW.send(new UserListeningOnly(mProps.meetingID, mProps.recorded, uvo.userID, uvo.listenOnly))
} }
} }
def handleUserDisconnectedFromGlobalAudio(msg: UserDisconnectedFromGlobalAudio) { def handleUserDisconnectedFromGlobalAudio(msg: UserDisconnectedFromGlobalAudio) {
val user = users.getUserWithExternalId(msg.userid) val user = usersModel.getUserWithExternalId(msg.userid)
user foreach { u => user foreach { u =>
val uvo = u.copy(listenOnly = false) val uvo = u.copy(listenOnly = false)
users.addUser(uvo) usersModel.addUser(uvo)
log.info("UserDisconnectedToGlobalAudio: mid=[" + mProps.meetingID + "] uid=[" + uvo.userID + "]") log.info("UserDisconnectedToGlobalAudio: mid=[" + mProps.meetingID + "] uid=[" + uvo.userID + "]")
outGW.send(new UserListeningOnly(mProps.meetingID, mProps.recorded, uvo.userID, uvo.listenOnly)) outGW.send(new UserListeningOnly(mProps.meetingID, mProps.recorded, uvo.userID, uvo.listenOnly))
} }
@ -61,14 +61,14 @@ trait UsersApp {
meetingModel.unmuteMeeting() meetingModel.unmuteMeeting()
} }
outGW.send(new MeetingMuted(mProps.meetingID, mProps.recorded, meetingModel.isMeetingMuted())) 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)) outGW.send(new MuteVoiceUser(mProps.meetingID, mProps.recorded, msg.requesterID, u.userID, mProps.voiceBridge, u.voiceUser.userId, msg.mute))
} }
} }
def handleValidateAuthToken(msg: ValidateAuthToken) { def handleValidateAuthToken(msg: ValidateAuthToken) {
// println("*************** Got ValidateAuthToken message ********************" ) // println("*************** Got ValidateAuthToken message ********************" )
users.getRegisteredUserWithToken(msg.token) match { usersModel.getRegisteredUserWithToken(msg.token) match {
case Some(u) => case Some(u) =>
{ {
val replyTo = mProps.meetingID + '/' + msg.userId val replyTo = mProps.meetingID + '/' + msg.userId
@ -103,7 +103,7 @@ trait UsersApp {
sendMeetingHasEnded(msg.userID) sendMeetingHasEnded(msg.userID)
} else { } else {
val regUser = new RegisteredUser(msg.userID, msg.extUserID, msg.name, msg.role, msg.authToken) 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 + "]") log.info("Register user success: mid=[" + mProps.meetingID + "] uid=[" + msg.userID + "]")
outGW.send(new UserRegistered(mProps.meetingID, mProps.recorded, regUser)) outGW.send(new UserRegistered(mProps.meetingID, mProps.recorded, regUser))
@ -117,7 +117,7 @@ trait UsersApp {
def handleMuteUserRequest(msg: MuteUserRequest) { def handleMuteUserRequest(msg: MuteUserRequest) {
// println("Received mute user request uid=[" + msg.userID + "] mute=[" + msg.mute + "]") // println("Received mute user request uid=[" + msg.userID + "] mute=[" + msg.mute + "]")
users.getUser(msg.userID) match { usersModel.getUser(msg.userID) match {
case Some(u) => { case Some(u) => {
// println("Sending mute user request uid=[" + msg.userID + "] mute=[" + msg.mute + "]") // println("Sending mute user request uid=[" + msg.userID + "] mute=[" + msg.mute + "]")
log.info("Muting user: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]") log.info("Muting user: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]")
@ -132,7 +132,7 @@ trait UsersApp {
def handleEjectUserRequest(msg: EjectUserFromVoiceRequest) { def handleEjectUserRequest(msg: EjectUserFromVoiceRequest) {
// println("Received eject user request uid=[" + msg.userID + "]") // println("Received eject user request uid=[" + msg.userID + "]")
users.getUser(msg.userId) match { usersModel.getUser(msg.userId) match {
case Some(u) => { case Some(u) => {
if (u.voiceUser.joined) { if (u.voiceUser.joined) {
log.info("Ejecting user from voice: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]") log.info("Ejecting user from voice: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]")
@ -147,24 +147,24 @@ trait UsersApp {
//println("*************** Reply with current lock settings ********************") //println("*************** Reply with current lock settings ********************")
//reusing the existing handle for NewPermissionsSettings to reply to the GetLockSettings request //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) { def handleSetLockSettings(msg: SetLockSettings) {
// println("*************** Received new lock settings ********************") // println("*************** Received new lock settings ********************")
if (!permissionsEqual(msg.settings)) { if (!permissionsEqual(msg.settings)) {
newPermissions(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) handleLockLayout(msg.settings.lockedLayout, msg.setByUser)
} }
} }
def handleLockUserRequest(msg: LockUserRequest) { def handleLockUserRequest(msg: LockUserRequest) {
users.getUser(msg.userID) match { usersModel.getUser(msg.userID) match {
case Some(u) => { case Some(u) => {
val uvo = u.copy(locked = msg.lock) 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 + "]") log.info("Lock user: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "] lock=[" + msg.lock + "]")
outGW.send(new UserLocked(mProps.meetingID, u.userID, msg.lock)) outGW.send(new UserLocked(mProps.meetingID, u.userID, msg.lock))
@ -179,7 +179,7 @@ trait UsersApp {
if (!meetingModel.permisionsInitialized()) { if (!meetingModel.permisionsInitialized()) {
meetingModel.initializePermissions() meetingModel.initializePermissions()
newPermissions(msg.settings) 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] = { def usersWhoAreNotPresenter(): Array[UserVO] = {
val au = ArrayBuffer[UserVO]() val au = ArrayBuffer[UserVO]()
users.getUsers foreach { u => usersModel.getUsers foreach { u =>
if (!u.presenter) { if (!u.presenter) {
au += u au += u
} }
@ -205,28 +205,28 @@ trait UsersApp {
} }
def handleUserRaiseHand(msg: UserRaiseHand) { def handleUserRaiseHand(msg: UserRaiseHand) {
users.getUser(msg.userId) foreach { user => usersModel.getUser(msg.userId) foreach { user =>
val uvo = user.copy(raiseHand = true) val uvo = user.copy(raiseHand = true)
users.addUser(uvo) usersModel.addUser(uvo)
outGW.send(new UserRaisedHand(mProps.meetingID, mProps.recorded, uvo.raiseHand, uvo.userID)) outGW.send(new UserRaisedHand(mProps.meetingID, mProps.recorded, uvo.raiseHand, uvo.userID))
} }
} }
def handleUserLowerHand(msg: UserLowerHand) { def handleUserLowerHand(msg: UserLowerHand) {
users.getUser(msg.userId) foreach { user => usersModel.getUser(msg.userId) foreach { user =>
val uvo = user.copy(raiseHand = false) 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)) outGW.send(new UserLoweredHand(mProps.meetingID, mProps.recorded, uvo.raiseHand, uvo.userID, msg.loweredBy))
} }
} }
def handleEjectUserFromMeeting(msg: EjectUserFromMeeting) { def handleEjectUserFromMeeting(msg: EjectUserFromMeeting) {
users.getUser(msg.userId) foreach { user => usersModel.getUser(msg.userId) foreach { user =>
if (user.voiceUser.joined) { if (user.voiceUser.joined) {
outGW.send(new EjectVoiceUser(mProps.meetingID, mProps.recorded, msg.ejectedBy, msg.userId, mProps.voiceBridge, user.voiceUser.userId)) 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 + "]") log.info("Ejecting user from meeting: mid=[" + mProps.meetingID + "]uid=[" + msg.userId + "]")
outGW.send(new UserEjectedFromMeeting(mProps.meetingID, mProps.recorded, msg.userId, msg.ejectedBy)) outGW.send(new UserEjectedFromMeeting(mProps.meetingID, mProps.recorded, msg.userId, msg.ejectedBy))
@ -237,46 +237,45 @@ trait UsersApp {
} }
def handleUserShareWebcam(msg: UserShareWebcam) { def handleUserShareWebcam(msg: UserShareWebcam) {
users.getUser(msg.userId) foreach { user => usersModel.getUser(msg.userId) foreach { user =>
val streams = user.webcamStreams + msg.stream val streams = user.webcamStreams + msg.stream
val uvo = user.copy(hasStream = true, webcamStreams = streams) 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 + "]") 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)) outGW.send(new UserSharedWebcam(mProps.meetingID, mProps.recorded, uvo.userID, msg.stream))
} }
} }
def handleUserunshareWebcam(msg: UserUnshareWebcam) { def handleUserunshareWebcam(msg: UserUnshareWebcam) {
users.getUser(msg.userId) foreach { user => usersModel.getUser(msg.userId) foreach { user =>
val streams = user.webcamStreams - msg.stream val streams = user.webcamStreams - msg.stream
val uvo = user.copy(hasStream = (!streams.isEmpty), webcamStreams = streams) 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 + "]") 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)) outGW.send(new UserUnsharedWebcam(mProps.meetingID, mProps.recorded, uvo.userID, msg.stream))
} }
} }
def handleChangeUserStatus(msg: ChangeUserStatus): Unit = { 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)) outGW.send(new UserStatusChange(mProps.meetingID, mProps.recorded, msg.userID, msg.status, msg.value))
} }
} }
def handleGetUsers(msg: GetUsers): Unit = { 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 = { def handleUserJoin(msg: UserJoining): Unit = {
val regUser = users.getRegisteredUserWithToken(msg.authToken) val regUser = usersModel.getRegisteredUserWithToken(msg.authToken)
regUser foreach { ru => regUser foreach { ru =>
val vu = new VoiceUser(msg.userID, msg.userID, ru.name, ru.name, val vu = new VoiceUser(msg.userID, msg.userID, ru.name, ru.name, false, false, false, false)
false, false, false, false)
val uvo = new UserVO(msg.userID, ru.externId, ru.name, val uvo = new UserVO(msg.userID, ru.externId, ru.name,
ru.role, raiseHand = false, presenter = false, ru.role, raiseHand = false, presenter = false,
hasStream = false, locked = getInitialLockStatus(ru.role), hasStream = false, locked = getInitialLockStatus(ru.role),
webcamStreams = new ListSet[String](), phoneUser = false, vu, listenOnly = false) 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=[" log.info("User joined meeting: mid=[" + mProps.meetingID + "] uid=[" + uvo.userID + "] role=["
+ uvo.role + "] locked=[" + uvo.locked + "] permissions.lockOnJoin=[" + meetingModel.getPermissions().lockOnJoin + 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())) outGW.send(new MeetingState(mProps.meetingID, mProps.recorded, uvo.userID, meetingModel.getPermissions(), meetingModel.isMeetingMuted()))
// Become presenter if the only moderator // Become presenter if the only moderator
if (users.numModerators == 1) { if (usersModel.numModerators == 1) {
if (ru.role == Role.MODERATOR) { if (ru.role == Role.MODERATOR) {
assignNewPresenter(msg.userID, ru.name, msg.userID) assignNewPresenter(msg.userID, ru.name, msg.userID)
} }
@ -297,22 +296,26 @@ trait UsersApp {
} }
def handleUserLeft(msg: UserLeaving): Unit = { def handleUserLeft(msg: UserLeaving): Unit = {
if (users.hasUser(msg.userID)) { if (usersModel.hasUser(msg.userID)) {
val user = users.removeUser(msg.userID) val user = usersModel.removeUser(msg.userID)
user foreach { u => user foreach { u =>
log.info("User left meeting: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]") log.info("User left meeting: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]")
outGW.send(new UserLeft(msg.meetingID, mProps.recorded, u)) outGW.send(new UserLeft(msg.meetingID, mProps.recorded, u))
if (u.presenter) { 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 /* 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 * him presenter. This way, if there is a moderator in the meeting, there
* will always be a presenter. * will always be a presenter.
*/ */
val moderator = users.findAModerator() val moderator = usersModel.findAModerator()
moderator.foreach { mod => moderator.foreach { mod =>
log.info("Presenter left meeting: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]. Making user=[" + mod.userID + "] presenter.") log.info("Presenter left meeting: mid=[" + mProps.meetingID + "] uid=[" + u.userID + "]. Making user=[" + mod.userID + "] presenter.")
assignNewPresenter(mod.userID, mod.name, mod.userID) assignNewPresenter(mod.userID, mod.name, mod.userID)
} }
} }
} }
@ -326,7 +329,7 @@ trait UsersApp {
} }
def handleUserJoinedVoiceFromPhone(msg: UserJoinedVoiceConfMessage) = { def handleUserJoinedVoiceFromPhone(msg: UserJoinedVoiceConfMessage) = {
val user = users.getUserWithVoiceUserId(msg.voiceUserId) match { val user = usersModel.getUserWithVoiceUserId(msg.voiceUserId) match {
case Some(user) => { case Some(user) => {
log.info("Voice user=[" + msg.voiceUserId + "] is already in conf=[" + mProps.voiceBridge + "]. Must be duplicate message.") 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 // 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 // the phone. We need to generate a new user as we are not able
// to match with a web user. // 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, val vu = new VoiceUser(msg.voiceUserId, webUserId, msg.callerIdName, msg.callerIdNum,
true, false, false, false) true, false, false, false)
@ -345,7 +348,7 @@ trait UsersApp {
hasStream = false, locked = getInitialLockStatus(Role.VIEWER), webcamStreams = new ListSet[String](), hasStream = false, locked = getInitialLockStatus(Role.VIEWER), webcamStreams = new ListSet[String](),
phoneUser = true, vu, listenOnly = false) phoneUser = true, vu, listenOnly = false)
users.addUser(uvo) usersModel.addUser(uvo)
log.info("New user joined voice for user [" + uvo.name + "] userid=[" + webUserId + "]") log.info("New user joined voice for user [" + uvo.name + "] userid=[" + webUserId + "]")
outGW.send(new UserJoined(mProps.meetingID, mProps.recorded, uvo)) outGW.send(new UserJoined(mProps.meetingID, mProps.recorded, uvo))
@ -358,7 +361,7 @@ trait UsersApp {
} }
def startRecordingVoiceConference() { def startRecordingVoiceConference() {
if (users.numUsersInVoiceConference == 1 && mProps.recorded) { if (usersModel.numUsersInVoiceConference == 1 && mProps.recorded) {
log.info("********** Send START RECORDING [" + mProps.voiceBridge + "]") log.info("********** Send START RECORDING [" + mProps.voiceBridge + "]")
outGW.send(new StartRecordingVoiceConf(mProps.meetingID, mProps.recorded, mProps.voiceBridge)) outGW.send(new StartRecordingVoiceConf(mProps.meetingID, mProps.recorded, mProps.voiceBridge))
} }
@ -367,11 +370,11 @@ trait UsersApp {
def handleUserJoinedVoiceConfMessage(msg: UserJoinedVoiceConfMessage) = { def handleUserJoinedVoiceConfMessage(msg: UserJoinedVoiceConfMessage) = {
log.info("Received user joined voice for user [" + msg.callerIdName + "] userid=[" + msg.userId + "]") 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) => { case Some(user) => {
val vu = new VoiceUser(msg.voiceUserId, msg.userId, msg.callerIdName, msg.callerIdNum, true, false, msg.muted, msg.talking) val vu = new VoiceUser(msg.voiceUserId, msg.userId, msg.callerIdName, msg.callerIdNum, true, false, msg.muted, msg.talking)
val nu = user.copy(voiceUser = vu) val nu = user.copy(voiceUser = vu)
users.addUser(nu) usersModel.addUser(nu)
log.info("User joined voice for user [" + nu.name + "] userid=[" + msg.userId + "]") log.info("User joined voice for user [" + nu.name + "] userid=[" + msg.userId + "]")
outGW.send(new UserJoinedVoice(mProps.meetingID, mProps.recorded, mProps.voiceBridge, nu)) outGW.send(new UserJoinedVoice(mProps.meetingID, mProps.recorded, mProps.voiceBridge, nu))
@ -389,25 +392,25 @@ trait UsersApp {
} }
def stopRecordingVoiceConference() { def stopRecordingVoiceConference() {
if (users.numUsersInVoiceConference == 0 && mProps.recorded) { if (usersModel.numUsersInVoiceConference == 0 && mProps.recorded) {
log.info("********** Send STOP RECORDING [" + mProps.voiceBridge + "]") log.info("********** Send STOP RECORDING [" + mProps.voiceBridge + "]")
outGW.send(new StopRecordingVoiceConf(mProps.meetingID, mProps.recorded, mProps.voiceBridge, meetingModel.getVoiceRecordingFilename())) outGW.send(new StopRecordingVoiceConf(mProps.meetingID, mProps.recorded, mProps.voiceBridge, meetingModel.getVoiceRecordingFilename()))
} }
} }
def handleUserLeftVoiceConfMessage(msg: UserLeftVoiceConfMessage) { 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 vu = new VoiceUser(user.userID, user.userID, user.name, user.name, false, false, false, false)
val nu = user.copy(voiceUser = vu) val nu = user.copy(voiceUser = vu)
users.addUser(nu) usersModel.addUser(nu)
// println("Received voice user left =[" + user.name + "] wid=[" + msg.userId + "]" ) // println("Received voice user left =[" + user.name + "] wid=[" + msg.userId + "]" )
log.info("Received user left voice for user [" + nu.name + "] userid=[" + msg.voiceUserId + "]") log.info("Received user left voice for user [" + nu.name + "] userid=[" + msg.voiceUserId + "]")
outGW.send(new UserLeftVoice(mProps.meetingID, mProps.recorded, mProps.voiceBridge, nu)) outGW.send(new UserLeftVoice(mProps.meetingID, mProps.recorded, mProps.voiceBridge, nu))
if (user.phoneUser) { if (user.phoneUser) {
if (users.hasUser(user.userID)) { if (usersModel.hasUser(user.userID)) {
val userLeaving = users.removeUser(user.userID) val userLeaving = usersModel.removeUser(user.userID)
userLeaving foreach (u => outGW.send(new UserLeft(mProps.meetingID, mProps.recorded, u))) userLeaving foreach (u => outGW.send(new UserLeft(mProps.meetingID, mProps.recorded, u)))
} }
} }
@ -417,21 +420,21 @@ trait UsersApp {
} }
def handleUserMutedInVoiceConfMessage(msg: UserMutedInVoiceConfMessage) { 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 talking: Boolean = if (msg.muted) false else user.voiceUser.talking
val nv = user.voiceUser.copy(muted = msg.muted, talking = talking) val nv = user.voiceUser.copy(muted = msg.muted, talking = talking)
val nu = user.copy(voiceUser = nv) val nu = user.copy(voiceUser = nv)
users.addUser(nu) usersModel.addUser(nu)
// println("Received voice muted=[" + msg.muted + "] wid=[" + msg.userId + "]" ) // println("Received voice muted=[" + msg.muted + "] wid=[" + msg.userId + "]" )
outGW.send(new UserVoiceMuted(mProps.meetingID, mProps.recorded, mProps.voiceBridge, nu)) outGW.send(new UserVoiceMuted(mProps.meetingID, mProps.recorded, mProps.voiceBridge, nu))
} }
} }
def handleUserTalkingInVoiceConfMessage(msg: UserTalkingInVoiceConfMessage) { 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 nv = user.voiceUser.copy(talking = msg.talking)
val nu = user.copy(voiceUser = nv) val nu = user.copy(voiceUser = nv)
users.addUser(nu) usersModel.addUser(nu)
// println("Received voice talking=[" + msg.talking + "] wid=[" + msg.userId + "]" ) // println("Received voice talking=[" + msg.talking + "] wid=[" + msg.userId + "]" )
outGW.send(new UserVoiceTalking(mProps.meetingID, mProps.recorded, mProps.voiceBridge, nu)) 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) { 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) => { 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)) outGW.send(new UserStatusChange(mProps.meetingID, mProps.recorded, curPres.userID, "presenter", false: java.lang.Boolean))
} }
case None => // do nothing case None => // do nothing
} }
users.getUser(newPresenterID) match { usersModel.getUser(newPresenterID) match {
case Some(newPres) => { case Some(newPres) => {
users.becomePresenter(newPres.userID) usersModel.becomePresenter(newPres.userID)
users.setCurrentPresenterInfo(new Presenter(newPresenterID, newPresenterName, assignedBy)) usersModel.setCurrentPresenterInfo(new Presenter(newPresenterID, newPresenterName, assignedBy))
outGW.send(new PresenterAssigned(mProps.meetingID, mProps.recorded, 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)) outGW.send(new UserStatusChange(mProps.meetingID, mProps.recorded, newPresenterID, "presenter", true: java.lang.Boolean))
} }