diff --git a/akka-bbb-apps/build.sbt b/akka-bbb-apps/build.sbt index b5474a81bb957e858b4ada9625a646bc65ad0dfa..b3328562cf3ec4aec17d5e9243eb47ad7aa06d99 100755 --- a/akka-bbb-apps/build.sbt +++ b/akka-bbb-apps/build.sbt @@ -50,7 +50,7 @@ libraryDependencies ++= { "com.google.code.gson" % "gson" % "1.7.1", "redis.clients" % "jedis" % "2.1.0", "org.apache.commons" % "commons-lang3" % "3.2", - "org.bigbluebutton" % "bbb-common-message" % "0.0.4" + "org.bigbluebutton" % "bbb-common-message" % "0.0.5" )} diff --git a/akka-bbb-apps/src/main/java/org/bigbluebutton/core/api/IBigBlueButtonInGW.java b/akka-bbb-apps/src/main/java/org/bigbluebutton/core/api/IBigBlueButtonInGW.java index f72392105a74e9e428d1c11b24884e6ba047b510..d7c0b3aafce5eb7c469e304a9a9aee98dbeb2c10 100755 --- a/akka-bbb-apps/src/main/java/org/bigbluebutton/core/api/IBigBlueButtonInGW.java +++ b/akka-bbb-apps/src/main/java/org/bigbluebutton/core/api/IBigBlueButtonInGW.java @@ -17,6 +17,11 @@ public interface IBigBlueButtonInGW { void getAllMeetings(String meetingID); void lockSettings(String meetingID, Boolean locked, Map<String, Boolean> lockSettigs); + // Polling + void votePoll(String meetingId, String userId, String pollId, Integer questionId, Integer answerId); + void startPoll(String meetingId, String requesterId, String pollId, String pollType); + void stopPoll(String meetingId, String userId, String pollId); + void showPollResult(String meetingId, String requesterId, String pollId, Boolean show); // Lock void initLockSettings(String meetingID, Map<String, Boolean> settings); diff --git a/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/PollingMessageReceiver.java b/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/PollingMessageReceiver.java new file mode 100755 index 0000000000000000000000000000000000000000..ba4f4f80ae88bd2c3bd111654bfe47e57f722221 --- /dev/null +++ b/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/PollingMessageReceiver.java @@ -0,0 +1,44 @@ +package org.bigbluebutton.core.pubsub.receivers; + +import org.bigbluebutton.common.messages.*; + +import com.google.gson.JsonParser; +import com.google.gson.JsonObject; + +import org.bigbluebutton.core.api.IBigBlueButtonInGW; + +public class PollingMessageReceiver implements MessageHandler{ + + private IBigBlueButtonInGW bbbGW; + + public PollingMessageReceiver(IBigBlueButtonInGW bbbGW) { + this.bbbGW = bbbGW; + } + + @Override + public void handleMessage(String pattern, String channel, String message) { + if (channel.equalsIgnoreCase(MessagingConstants.TO_POLLING_CHANNEL)) { + JsonParser parser = new JsonParser(); + JsonObject obj = (JsonObject) parser.parse(message); + if (obj.has("header") && obj.has("payload")) { + JsonObject header = (JsonObject) obj.get("header"); + if (header.has("name")) { + String messageName = header.get("name").getAsString(); + if (VotePollUserRequestMessage.VOTE_POLL_REQUEST.equals(messageName)) { + VotePollUserRequestMessage msg = VotePollUserRequestMessage.fromJson(message); + bbbGW.votePoll(msg.meetingId, msg.userId, msg.pollId, msg.questionId, msg.answerId); + } else if (StartPollRequestMessage.START_POLL_REQUEST.equals(messageName)){ + StartPollRequestMessage msg = StartPollRequestMessage.fromJson(message); + bbbGW.startPoll(msg.meetingId, msg.requesterId, msg.pollId, msg.pollType); + } else if (StopPollRequestMessage.STOP_POLL_REQUEST.equals(messageName)){ + StopPollRequestMessage msg = StopPollRequestMessage.fromJson(message); + bbbGW.stopPoll(msg.meetingId, msg.requesterId, msg.pollId); + } else if (ShowPollResultRequestMessage.SHOW_POLL_RESULT_REQUEST.equals(messageName)){ + ShowPollResultRequestMessage msg = ShowPollResultRequestMessage.fromJson(message); + bbbGW.showPollResult(msg.meetingId, msg.requesterId, msg.pollId, msg.show); + } + } + } + } + } +} diff --git a/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/RedisMessageReceiver.java b/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/RedisMessageReceiver.java index 0e6eeb5c4bf803d9069bbf86aacf4fef3117180b..3c932c0e4ddf059aef74dbb79e4c8a4224dbd4d8 100755 --- a/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/RedisMessageReceiver.java +++ b/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/RedisMessageReceiver.java @@ -31,6 +31,9 @@ public class RedisMessageReceiver { WhiteboardMessageReceiver whiteboardRx = new WhiteboardMessageReceiver(bbbGW); receivers.add(whiteboardRx); + PollingMessageReceiver pollRx = new PollingMessageReceiver(bbbGW); + receivers.add(pollRx); + MeetingMessageReceiver meetingRx = new MeetingMessageReceiver(bbbGW); receivers.add(meetingRx); } diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/Boot.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/Boot.scala index 30955b7101a50453f00bdd9522e738a154ab7406..081ded6075820ff8a040e978ca10c7ed3ff2ab32 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/Boot.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/Boot.scala @@ -46,6 +46,7 @@ object Boot extends App with SystemConfiguration { val presSender = new PresentationEventRedisPublisher(msgSender) val userSender = new UsersEventRedisPublisher(msgSender) val whiteboardSender = new WhiteboardEventRedisPublisher(msgSender) + val pollingSender = new PollingEventRedisPublisher(msgSender) val outMessageListeners = new java.util.ArrayList[OutMessageListener2]() outMessageListeners.add(chatSender) @@ -57,6 +58,7 @@ object Boot extends App with SystemConfiguration { outMessageListeners.add(presentationEventRecorder) outMessageListeners.add(usersEventRecorder) outMessageListeners.add(whiteboardEventRecorder) + outMessageListeners.add(pollingSender) val outGW = new MessageOutGateway(outMessageListeners) val bbbInGW = new BigBlueButtonInGW(system, outGW, voiceEventRecorder) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/BigBlueButtonInGW.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/BigBlueButtonInGW.scala index a924b633227f413f5105b064dab346682bbd0122..766711b344522510bcf336fcdcc4efed24d0c821 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/BigBlueButtonInGW.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/BigBlueButtonInGW.scala @@ -432,4 +432,25 @@ class BigBlueButtonInGW(val system: ActorSystem, outGW: MessageOutGateway, voice def voiceRecording(voiceConfId: String, recordingFile: String, timestamp: String, recording: java.lang.Boolean) { bbbActor ! new VoiceConfRecordingStartedMessage(voiceConfId, recordingFile, recording, timestamp) } + + // Polling + def votePoll(meetingId: String, userId: String, pollId: String, questionId: Integer, answerId: Integer) { + bbbActor ! new RespondToPollRequest(meetingId, userId, pollId, questionId, answerId) + } + + def startPoll(meetingId: String, requesterId: String, pollId: String, pollType: String) { + bbbActor ! new StartPollRequest(meetingId, requesterId, pollId, pollType) + } + + def stopPoll(meetingId: String, userId: String, pollId: String) { + bbbActor ! new StopPollRequest(meetingId, userId, pollId) + } + + def showPollResult(meetingId: String, requesterId: String, pollId: String, show: java.lang.Boolean) { + if (show) { + bbbActor ! new ShowPollResultRequest(meetingId, requesterId, pollId) + } else { + bbbActor ! new HidePollResultRequest(meetingId, requesterId, pollId) + } + } } diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/OutMessages.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/OutMessages.scala index c3ae721a85361e5267eddf55baf1d6f9de177736..265c989187542f8165a794f576e0ef2866c5f335 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/OutMessages.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/OutMessages.scala @@ -117,7 +117,7 @@ case class PollShowResultMessage(meetingID: String, recorded: Boolean, requester 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 HidePollResultReplyMessage(meetingID: String, recorded: Boolean, result: RequestResult, requesterId: String, pollId: String) extends IOutMessage -case class UserRespondedToPollMessage(meetingID: String, recorded: Boolean, requesterId: String, pollId: String, poll: SimplePollResultOutVO) extends IOutMessage +case class UserRespondedToPollMessage(meetingID: String, recorded: Boolean, presenterId: String, pollId: String, poll: SimplePollResultOutVO) extends IOutMessage case class RespondToPollReplyMessage(meetingID: String, recorded: Boolean, result: RequestResult, requesterId: String, pollId: String) extends IOutMessage case class GetCurrentPollReplyMessage(meetingID: String, recorded: Boolean, requesterId: String, hasPoll: Boolean, poll: Option[PollVO]) extends IOutMessage diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/Poll.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/Poll.scala index 1d3b355a2eb81eed80c131d9e2ad0a2fca211b96..f0df6862f449622ad8eddad8e44e61763ddc4d9b 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/Poll.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/Poll.scala @@ -113,8 +113,10 @@ case class Responder(val userId: String, name: String) case class ResponseOutVO(id: String, text: String, responders: Array[Responder] = Array[Responder]()) case class QuestionOutVO(id: String, multiResponse: Boolean, question: String, responses: Array[ResponseOutVO]) + case class SimpleAnswerOutVO(id: Int, key: String) case class SimplePollOutVO(id: String, answers: Array[SimpleAnswerOutVO]) + case class SimpleVoteOutVO(id: Int, key: String, numVotes: Int) case class SimplePollResultOutVO(id: String, answers: Array[SimpleVoteOutVO]) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/PollApp.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/PollApp.scala index ba93bc5296db4094f5c615f38ce6021099421fef..907d1314e58d4fb413fb68abb550ae998f67bb0d 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/PollApp.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/PollApp.scala @@ -127,7 +127,10 @@ trait PollApp { case Some(user) => { val responder = new Responder(user.userID, user.name) pollModel.respondToQuestion(poll.id, msg.questionId, msg.answerId, responder) - outGW.send(new UserRespondedToPollMessage(mProps.meetingID, mProps.recorded, msg.requesterId, msg.pollId, poll)) + users.getCurrentPresenter foreach { cp => + outGW.send(new UserRespondedToPollMessage(mProps.meetingID, mProps.recorded, cp.userID, msg.pollId, poll)) + } + } case None => { val result = new RequestResult(StatusCodes.FORBIDDEN, Some(Array(ErrorCodes.RESOURCE_NOT_FOUND))) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/PollingEventRedisPublisher.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/PollingEventRedisPublisher.scala new file mode 100755 index 0000000000000000000000000000000000000000..3c88afc2789ab51fd4c18a9ea41494754779f376 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/PollingEventRedisPublisher.scala @@ -0,0 +1,126 @@ +package org.bigbluebutton.core.pubsub.senders + +import org.bigbluebutton.core.api.OutMessageListener2 +import org.bigbluebutton.core.MessageSender +import org.bigbluebutton.core.api._ +import com.google.gson.Gson +import scala.collection.mutable.HashMap +import collection.JavaConverters._ +import scala.collection.JavaConversions._ +import java.util.ArrayList +import org.bigbluebutton.common.messages.MessagingConstants +import org.bigbluebutton.core.messaging.Util +import org.bigbluebutton.core.apps.SimplePollOutVO +import org.bigbluebutton.core.apps.SimplePollResultOutVO + +class PollingEventRedisPublisher(service: MessageSender) extends OutMessageListener2 { + def handleMessage(msg: IOutMessage) { + msg match { + case msg: PollStartedMessage => handlePollStartedMessage(msg) + case msg: PollStoppedMessage => handlePollStoppedMessage(msg) + case msg: PollShowResultMessage => handlePollShowResultMessage(msg) + case msg: PollHideResultMessage => handlePollHideResultMessage(msg) + case msg: UserRespondedToPollMessage => handleUserRespondedToPollMessage(msg) + case _ => // do nothing + } + } + + private def handlePollStartedMessage(msg: PollStartedMessage) { + val json = pollStartedMessageToJson(msg) + service.send(MessagingConstants.FROM_POLLING_CHANNEL, json) + } + + private def handlePollStoppedMessage(msg: PollStoppedMessage) { + val json = pollStoppedMessageToJson(msg) + service.send(MessagingConstants.FROM_POLLING_CHANNEL, json) + } + + private def handlePollShowResultMessage(msg: PollShowResultMessage) { + val json = pollShowResultMessageToJson(msg) + service.send(MessagingConstants.FROM_POLLING_CHANNEL, json) + } + + private def handlePollHideResultMessage(msg: PollHideResultMessage) { + val json = pollHideResultMessageToJson(msg) + service.send(MessagingConstants.FROM_POLLING_CHANNEL, json) + } + + private def handleUserRespondedToPollMessage(msg: UserRespondedToPollMessage) { + // val json = ChatMessageToJsonConverter.sendPrivateMessageEventToJson(msg) + // service.send(MessagingConstants.FROM_CHAT_CHANNEL, json) + } + + private def pollVOtoMap(msg: SimplePollOutVO): java.util.HashMap[String, Object] = { + val pollVO = new java.util.HashMap[String, Object]() + pollVO.put("id", msg.id) + + val answers = new java.util.ArrayList[java.util.Map[String, Any]]; + msg.answers.foreach(ans => { + val amap = new java.util.HashMap[String, Any]() + amap.put("id", ans.id) + amap.put("key", ans.key) + answers.add(amap) + }) + + pollVO.put("answers", answers) + + pollVO + } + + private def pollStartedMessageToJson(msg: PollStartedMessage): String = { + // val payload = new java.util.HashMap[String, Any]() + // payload.put(Constants.MEETING_ID, msg.meetingID) + // payload.put(org.bigbluebutton.common.messages.PollStartedMessage.REQUESTER_ID, msg.requesterId) + + // val pollVO = pollVOtoMap(msg.poll) + // payload.put(org.bigbluebutton.common.messages.PollStartedMessage.POLL, pollVO) + + // val header = Util.buildHeader(org.bigbluebutton.common.messages.PollStartedMessage.POLL_STARTED, None) + // Util.buildJson(header, payload) + + val pollVO = pollVOtoMap(msg.poll) + val psm = new org.bigbluebutton.common.messages.PollStartedMessage(msg.meetingID, msg.requesterId, pollVO) + psm.toJson + } + + private def pollStoppedMessageToJson(msg: PollStoppedMessage): String = { + val psm = new org.bigbluebutton.common.messages.PollStoppedMessage(msg.meetingID, msg.requesterId, msg.pollId) + psm.toJson + } + + private def pollResultVOtoMap(msg: SimplePollResultOutVO): java.util.HashMap[String, Object] = { + val pollVO = new java.util.HashMap[String, Object]() + pollVO.put("id", msg.id) + + val answers = new java.util.ArrayList[java.util.Map[String, Any]]; + msg.answers.foreach(ans => { + val amap = new java.util.HashMap[String, Any]() + amap.put("id", ans.id) + amap.put("key", ans.key) + amap.put("num_votes", ans.numVotes) + answers.add(amap) + }) + + pollVO.put("answers", answers) + + pollVO + } + + private def pollShowResultMessageToJson(msg: PollShowResultMessage): String = { + val pollResultVO = pollResultVOtoMap(msg.poll) + + val psm = new org.bigbluebutton.common.messages.PollShowResultMessage(msg.meetingID, pollResultVO) + psm.toJson + } + + private def pollHideResultMessageToJson(msg: PollHideResultMessage): String = { + val psm = new org.bigbluebutton.common.messages.PollHideResultMessage(msg.meetingID, msg.pollId) + psm.toJson + } + + private def UserRespondedToPollMessageTpJson(msg: UserRespondedToPollMessage): String = { + val pollResultVO = pollResultVOtoMap(msg.poll) + val psm = new org.bigbluebutton.common.messages.UserVotedPollMessage(msg.meetingID, msg.presenterId, pollResultVO) + psm.toJson + } +} \ No newline at end of file diff --git a/akka-bbb-fsesl/build.sbt b/akka-bbb-fsesl/build.sbt index 81333704a35b49ed78558d04242e171e4f0ceaea..d55a4f48642d68bfcc46ec215a14de20720de550 100755 --- a/akka-bbb-fsesl/build.sbt +++ b/akka-bbb-fsesl/build.sbt @@ -50,7 +50,7 @@ libraryDependencies ++= { "com.google.code.gson" % "gson" % "1.7.1", "redis.clients" % "jedis" % "2.1.0", "org.apache.commons" % "commons-lang3" % "3.2", - "org.bigbluebutton" % "bbb-common-message" % "0.0.4", + "org.bigbluebutton" % "bbb-common-message" % "0.0.5", "org.bigbluebutton" % "bbb-fsesl-client" % "0.0.2" )} diff --git a/bigbluebutton-apps/build.gradle b/bigbluebutton-apps/build.gradle index c85089a28f4499226a06231bb51c91cdee84c5c4..72478ee971a7953a70b8fc228deef0fcae9b3e1c 100755 --- a/bigbluebutton-apps/build.gradle +++ b/bigbluebutton-apps/build.gradle @@ -23,7 +23,7 @@ repositories { //url "${System.properties['user.home']}/.ivy2/local" url "/home/ubuntu/.ivy2/local" layout "pattern", { - artifact "[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" + artifact "[organisation]/[module]/[revision]/[artifact].[ext]" m2compatible = true } } @@ -41,7 +41,7 @@ repositories { name = "blindside-repos" addArtifactPattern "http://blindside.googlecode.com/svn/repository/[artifact](-[revision]).[ext]" addArtifactPattern "http://blindside.googlecode.com/svn/repository/[organisation]/[artifact](-[revision]).[ext]" - } + } add(new org.apache.ivy.plugins.resolver.URLResolver()) { name = "testng_ibiblio_maven2" m2compatible = true @@ -112,7 +112,7 @@ dependencies { compile 'com.google.code.gson:gson:1.7.1' providedCompile 'org.apache.commons:commons-lang3:3.2' - compile 'org.bigbluebutton:bbb-common-message:0.0.4' + compile 'org.bigbluebutton:bbb-common-message:0.0.5' } test { diff --git a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/PollingClientMessageSender.java b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/PollingClientMessageSender.java new file mode 100755 index 0000000000000000000000000000000000000000..9932eecb1fac5d70d79ee0b1232b205d5dcda7aa --- /dev/null +++ b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/PollingClientMessageSender.java @@ -0,0 +1,108 @@ +package org.bigbluebutton.red5.client; + + +import java.util.HashMap; +import java.util.Map; +import org.bigbluebutton.common.messages.*; +import org.bigbluebutton.red5.client.messaging.BroadcastClientMessage; +import org.bigbluebutton.red5.client.messaging.ConnectionInvokerService; +import org.bigbluebutton.red5.client.messaging.DirectClientMessage; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +public class PollingClientMessageSender { + private ConnectionInvokerService service; + + public PollingClientMessageSender(ConnectionInvokerService service) { + this.service = service; + } + + public void handlePollMessage(String message) { + JsonParser parser = new JsonParser(); + JsonObject obj = (JsonObject) parser.parse(message); + + if (obj.has("header") && obj.has("payload")) { + JsonObject header = (JsonObject) obj.get("header"); + + if (header.has("name")) { + String messageName = header.get("name").getAsString(); + + switch (messageName) { + case PollStartedMessage.POLL_STARTED: + processPollStartedMessage(message); + break; + case PollStoppedMessage.POLL_STOPPED: + processPollStoppedMessage(message); + break; + case PollShowResultMessage.POLL_SHOW_RESULT: + processPollShowResultMessage(message); + break; + case UserVotedPollMessage.USER_VOTED_POLL: + processUserVotedPollMessage(message); + break; + } + } + } + } + + private void processPollStartedMessage(String json) { + PollStartedMessage msg = PollStartedMessage.fromJson(json); + if (msg != null) { + Map<String, Object> args = new HashMap<String, Object>(); + args.put("poll", msg.poll); + + Map<String, Object> message = new HashMap<String, Object>(); + Gson gson = new Gson(); + message.put("msg", gson.toJson(args)); + + BroadcastClientMessage b = new BroadcastClientMessage(msg.meetingId, "pollStartedMessage", message); + service.sendMessage(b); + } + } + + private void processPollStoppedMessage(String json) { + PollStoppedMessage msg = PollStoppedMessage.fromJson(json); + if (msg != null) { + Map<String, Object> args = new HashMap<String, Object>(); + args.put("pollId", msg.pollId); + + Map<String, Object> message = new HashMap<String, Object>(); + Gson gson = new Gson(); + message.put("msg", gson.toJson(args)); + + BroadcastClientMessage b = new BroadcastClientMessage(msg.meetingId, "pollStoppedMessage", message); + service.sendMessage(b); + } + } + + private void processPollShowResultMessage(String json) { + PollShowResultMessage msg = PollShowResultMessage.fromJson(json); + if (msg != null) { + Map<String, Object> args = new HashMap<String, Object>(); + args.put("poll", msg.poll); + + Map<String, Object> message = new HashMap<String, Object>(); + Gson gson = new Gson(); + message.put("msg", gson.toJson(args)); + + BroadcastClientMessage b = new BroadcastClientMessage(msg.meetingId, "pollShowResultMessage", message); + service.sendMessage(b); + } + } + + private void processUserVotedPollMessage(String json) { + UserVotedPollMessage msg = UserVotedPollMessage.fromJson(json); + if (msg != null) { + Map<String, Object> args = new HashMap<String, Object>(); + args.put("poll", msg.poll); + + Map<String, Object> message = new HashMap<String, Object>(); + Gson gson = new Gson(); + message.put("msg", gson.toJson(args)); + + DirectClientMessage b = new DirectClientMessage(msg.meetingId, msg.presenterId, "pollUserVotedMessage", message); + service.sendMessage(b); + } + } +} diff --git a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/pubsub/MessagePublisher.java b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/pubsub/MessagePublisher.java index e312611e03e9fb6049e1b4d9a16b2f445eeca39a..4d9d731b802bb2ef2b90379f04aea28571df5d15 100755 --- a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/pubsub/MessagePublisher.java +++ b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/pubsub/MessagePublisher.java @@ -1,52 +1,8 @@ package org.bigbluebutton.red5.pubsub; import java.util.Map; -import org.bigbluebutton.common.messages.AssignPresenterRequestMessage; -import org.bigbluebutton.common.messages.BroadcastLayoutRequestMessage; -import org.bigbluebutton.common.messages.ClearWhiteboardRequestMessage; -import org.bigbluebutton.common.messages.EjectUserFromMeetingRequestMessage; -import org.bigbluebutton.common.messages.EjectUserFromVoiceRequestMessage; -import org.bigbluebutton.common.messages.EnableWhiteboardRequestMessage; -import org.bigbluebutton.common.messages.GetChatHistoryRequestMessage; -import org.bigbluebutton.common.messages.GetCurrentLayoutRequestMessage; -import org.bigbluebutton.common.messages.GetLockSettingsMessage; -import org.bigbluebutton.common.messages.GetPresentationInfoMessage; -import org.bigbluebutton.common.messages.GetRecordingStatusRequestMessage; -import org.bigbluebutton.common.messages.GetSlideInfoMessage; -import org.bigbluebutton.common.messages.GetUsersRequestMessage; -import org.bigbluebutton.common.messages.GoToSlideMessage; -import org.bigbluebutton.common.messages.InitAudioSettingsMessage; -import org.bigbluebutton.common.messages.InitPermissionsSettingMessage; -import org.bigbluebutton.common.messages.IsMeetingMutedRequestMessage; -import org.bigbluebutton.common.messages.IsWhiteboardEnabledRequestMessage; -import org.bigbluebutton.common.messages.LockLayoutRequestMessage; -import org.bigbluebutton.common.messages.LockMuteUserRequestMessage; -import org.bigbluebutton.common.messages.LockUserMessage; -import org.bigbluebutton.common.messages.MessagingConstants; -import org.bigbluebutton.common.messages.MuteAllExceptPresenterRequestMessage; -import org.bigbluebutton.common.messages.MuteAllRequestMessage; -import org.bigbluebutton.common.messages.MuteUserRequestMessage; -import org.bigbluebutton.common.messages.RemovePresentationMessage; -import org.bigbluebutton.common.messages.RequestWhiteboardAnnotationHistoryRequestMessage; -import org.bigbluebutton.common.messages.ResizeAndMoveSlideMessage; -import org.bigbluebutton.common.messages.SendConversionCompletedMessage; -import org.bigbluebutton.common.messages.SendConversionUpdateMessage; -import org.bigbluebutton.common.messages.SendCursorUpdateMessage; -import org.bigbluebutton.common.messages.SendLockSettingsMessage; -import org.bigbluebutton.common.messages.SendPageCountErrorMessage; -import org.bigbluebutton.common.messages.SendPrivateChatMessage; -import org.bigbluebutton.common.messages.SendPublicChatMessage; -import org.bigbluebutton.common.messages.SendSlideGeneratedMessage; -import org.bigbluebutton.common.messages.SendWhiteboardAnnotationRequestMessage; -import org.bigbluebutton.common.messages.SetRecordingStatusRequestMessage; -import org.bigbluebutton.common.messages.SetUserStatusRequestMessage; -import org.bigbluebutton.common.messages.SharePresentationMessage; -import org.bigbluebutton.common.messages.UserLeavingMessage; -import org.bigbluebutton.common.messages.UserLoweredHandMessage; -import org.bigbluebutton.common.messages.UserRaisedHandMessage; -import org.bigbluebutton.common.messages.UserShareWebcamRequestMessage; -import org.bigbluebutton.common.messages.UserUnshareWebcamRequestMessage; -import org.bigbluebutton.common.messages.ValidateAuthTokenMessage; + +import org.bigbluebutton.common.messages.*; import org.bigbluebutton.red5.pubsub.redis.MessageSender; public class MessagePublisher { @@ -57,6 +13,27 @@ public class MessagePublisher { this.sender = sender; } + // Polling + public void votePoll(String meetingId, String userId, String pollId, Integer questionId, Integer answerId) { + VotePollUserRequestMessage msg = new VotePollUserRequestMessage(meetingId, userId, pollId, questionId, answerId); + sender.send(MessagingConstants.TO_POLLING_CHANNEL, msg.toJson()); + } + + public void startPoll(String meetingId, String requesterId, String pollId, String pollType) { + StartPollRequestMessage msg = new StartPollRequestMessage(meetingId, requesterId, pollId, pollType); + sender.send(MessagingConstants.TO_POLLING_CHANNEL, msg.toJson()); + } + + public void stopPoll(String meetingId, String userId, String pollId) { + StopPollRequestMessage msg = new StopPollRequestMessage(meetingId, userId, pollId); + sender.send(MessagingConstants.TO_POLLING_CHANNEL, msg.toJson()); + } + + public void showPollResult(String meetingId, String requesterId, String pollId, Boolean show) { + ShowPollResultRequestMessage msg = new ShowPollResultRequestMessage(meetingId, requesterId, pollId, show); + sender.send(MessagingConstants.TO_POLLING_CHANNEL, msg.toJson()); + } + public void initLockSettings(String meetingID, Map<String, Boolean> permissions) { InitPermissionsSettingMessage msg = new InitPermissionsSettingMessage(meetingID, permissions); sender.send(MessagingConstants.TO_USERS_CHANNEL, msg.toJson()); diff --git a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/pubsub/redis/RedisPubSubMessageHandler.java b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/pubsub/redis/RedisPubSubMessageHandler.java index 3fa88efc2682109311bd1656a8c79b95a4be3ef0..e78a0a152d3dee3c4b08650bdc574240bde61485 100755 --- a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/pubsub/redis/RedisPubSubMessageHandler.java +++ b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/pubsub/redis/RedisPubSubMessageHandler.java @@ -2,6 +2,7 @@ package org.bigbluebutton.red5.pubsub.redis; import org.bigbluebutton.common.messages.MessagingConstants; import org.bigbluebutton.red5.client.MeetingClientMessageSender; +import org.bigbluebutton.red5.client.PollingClientMessageSender; import org.bigbluebutton.red5.client.PresentationClientMessageSender; import org.bigbluebutton.red5.client.UserClientMessageSender; import org.bigbluebutton.red5.client.ChatClientMessageSender; @@ -18,7 +19,7 @@ public class RedisPubSubMessageHandler implements MessageHandler { private PresentationClientMessageSender presentationMessageSender; private WhiteboardClientMessageSender whiteboardMessageSender; private BbbAppsIsKeepAliveHandler bbbAppsIsKeepAliveHandler; - + private PollingClientMessageSender pollingMessageSender; public void setConnectionInvokerService(ConnectionInvokerService s) { this.service = s; @@ -27,6 +28,7 @@ public class RedisPubSubMessageHandler implements MessageHandler { chatMessageSender = new ChatClientMessageSender(service); presentationMessageSender = new PresentationClientMessageSender(service); whiteboardMessageSender = new WhiteboardClientMessageSender(service); + pollingMessageSender = new PollingClientMessageSender(service); } public void setBbbAppsIsKeepAliveHandler(BbbAppsIsKeepAliveHandler handler) { @@ -47,6 +49,8 @@ public class RedisPubSubMessageHandler implements MessageHandler { whiteboardMessageSender.handleWhiteboardMessage(message); } else if (channel.equalsIgnoreCase(MessagingConstants.BBB_APPS_KEEP_ALIVE_CHANNEL)) { bbbAppsIsKeepAliveHandler.handleKeepAliveMessage(message); + } else if (channel.equalsIgnoreCase(MessagingConstants.FROM_POLLING_CHANNEL)) { + pollingMessageSender.handlePollMessage(message); } } diff --git a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/service/PollingService.java b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/service/PollingService.java new file mode 100755 index 0000000000000000000000000000000000000000..de5dafcf87578843168d520d60417e7226416a91 --- /dev/null +++ b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/service/PollingService.java @@ -0,0 +1,107 @@ +/** +* 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/>. +* Author: Felipe Cecagno <felipe@mconf.org> +*/ +package org.bigbluebutton.red5.service; + +import java.util.Map; + +import org.bigbluebutton.red5.BigBlueButtonSession; +import org.bigbluebutton.red5.Constants; +import org.bigbluebutton.red5.pubsub.MessagePublisher; +import org.red5.logging.Red5LoggerFactory; +import org.red5.server.api.Red5; +import org.slf4j.Logger; + +public class PollingService { + + private static Logger log = Red5LoggerFactory.getLogger( PollingService.class, "bigbluebutton" ); + + private MessagePublisher red5GW; + + public void setRed5Publisher(MessagePublisher inGW) { + red5GW = inGW; + } + + public void votePoll(Map<String, Object> message) { + log.debug("Received broadcast layout request"); + String meetingID = Red5.getConnectionLocal().getScope().getName(); + String userId = getBbbSession().getInternalUserID(); + String pollId = (String) message.get("pollId"); + Integer questionId = (Integer) message.get("questionId"); + Integer answerId = (Integer) message.get("answerId"); + + // red5GW.broadcastLayout(meetingID, getBbbSession().getInternalUserID(), newlayout); + } + + public void showPollResult(Map<String, Object> message) { + log.debug("Received broadcast layout request"); + String meetingID = Red5.getConnectionLocal().getScope().getName(); + String newlayout = (String) message.get("layout"); + + if (newlayout == null || newlayout.isEmpty()) { + log.error("Invalid Broadcast Layout message. layout is null or empty."); + return; + } + + red5GW.broadcastLayout(meetingID, getBbbSession().getInternalUserID(), newlayout); + } + + public void startPoll(Map<String, Object> message) { + log.debug("Received broadcast layout request"); + String meetingID = Red5.getConnectionLocal().getScope().getName(); + String newlayout = (String) message.get("layout"); + + if (newlayout == null || newlayout.isEmpty()) { + log.error("Invalid Broadcast Layout message. layout is null or empty."); + return; + } + + red5GW.broadcastLayout(meetingID, getBbbSession().getInternalUserID(), newlayout); + } + + public void stopPoll(Map<String, Object> message) { + log.debug("Received lock layout request"); + String meetingID = Red5.getConnectionLocal().getScope().getName(); + String newlayout = (String) message.get("layout"); + Boolean lock = (Boolean) message.get("lock"); + Boolean viewersOnly = (Boolean) message.get("viewersOnly"); + String layout; + + if (newlayout == null || newlayout.isEmpty()) { + layout = null; + } else { + layout = newlayout; + } + + if (lock == null) { + log.error("Invalid Lock Layout message. lock in null."); + return; + } + + if (viewersOnly == null) { + log.error("Invalid Lock Layout message. viewersOnly is null"); + return; + } + + red5GW.lockLayout(meetingID, getBbbSession().getInternalUserID(), lock, viewersOnly, layout); + } + + private BigBlueButtonSession getBbbSession() { + return (BigBlueButtonSession) Red5.getConnectionLocal().getAttribute(Constants.SESSION); + } +} diff --git a/bigbluebutton-apps/src/main/webapp/WEB-INF/red5-web.xml b/bigbluebutton-apps/src/main/webapp/WEB-INF/red5-web.xml index eff7a4ce80ba1479404b8f41b89db077604b0fb7..f9709f7d95c8adf0f2edf0f225a4bd2519fcc316 100755 --- a/bigbluebutton-apps/src/main/webapp/WEB-INF/red5-web.xml +++ b/bigbluebutton-apps/src/main/webapp/WEB-INF/red5-web.xml @@ -87,6 +87,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. <property name="red5Publisher"> <ref bean="red5Publisher"/></property> </bean> + <bean id="poll.service" class="org.bigbluebutton.red5.service.PollingService"> + <property name="red5Publisher"> <ref bean="red5Publisher"/></property> + </bean> + <bean id="whiteboard.service" class="org.bigbluebutton.red5.service.WhiteboardService"> <property name="whiteboardApplication"> <ref local="whiteboardApplication"/></property> </bean>