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 1c083591ef..3d851ae65a 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 @@ -111,4 +111,7 @@ public interface IBigBlueButtonInGW { void enableWhiteboard(String meetingID, String requesterID, Boolean enable); void isWhiteboardEnabled(String meetingID, String requesterID, String replyTo); + // Caption + void sendCaptionHistory(String meetingID, String requesterID); + void newCaptionLine(String meetingID, Integer lineNumber, String locale, Integer startTime, String text); } diff --git a/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/CaptionMessageReceiver.java b/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/CaptionMessageReceiver.java new file mode 100755 index 0000000000..f9500c2cec --- /dev/null +++ b/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/CaptionMessageReceiver.java @@ -0,0 +1,40 @@ +package org.bigbluebutton.core.pubsub.receivers; + +import org.bigbluebutton.common.messages.MessagingConstants; +import org.bigbluebutton.common.messages.NewCaptionLineMessage; +import org.bigbluebutton.common.messages.SendCaptionHistoryRequestMessage; + +import com.google.gson.JsonParser; +import com.google.gson.JsonObject; + +import org.bigbluebutton.core.api.IBigBlueButtonInGW; + +public class CaptionMessageReceiver implements MessageHandler{ + + private IBigBlueButtonInGW bbbGW; + + public CaptionMessageReceiver(IBigBlueButtonInGW bbbGW) { + this.bbbGW = bbbGW; + } + + @Override + public void handleMessage(String pattern, String channel, String message) { + if (channel.equalsIgnoreCase(MessagingConstants.TO_CAPTION_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 (NewCaptionLineMessage.NEW_CAPTION_LINE.equals(messageName)) { + NewCaptionLineMessage msg = NewCaptionLineMessage.fromJson(message); + bbbGW.newCaptionLine(msg.meetingID, msg.lineNumber, msg.locale, msg.startTime, msg.text); + } else if (SendCaptionHistoryRequestMessage.SEND_CAPTION_HISTORY_REQUEST.equals(messageName)){ + SendCaptionHistoryRequestMessage msg = SendCaptionHistoryRequestMessage.fromJson(message); + bbbGW.sendCaptionHistory(msg.meetingID, msg.requesterID); + } + } + } + } + } +} 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 3c932c0e4d..d8a439e08e 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 @@ -36,6 +36,9 @@ public class RedisMessageReceiver { MeetingMessageReceiver meetingRx = new MeetingMessageReceiver(bbbGW); receivers.add(meetingRx); + + CaptionMessageReceiver captionRx = new CaptionMessageReceiver(bbbGW); + receivers.add(captionRx); } public void handleMessage(String pattern, String channel, String message) { 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 c984984202..f4b2af8dcc 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 @@ -444,7 +444,12 @@ class BigBlueButtonInGW(val system: ActorSystem, recorderApp: RecorderApplicatio bbbActor ! new VoiceConfRecordingStartedMessage(voiceConfId, recordingFile, recording, timestamp) } - // Polling + /** + * ******************************************************************* + * Message Interface for Polling + * ***************************************************************** + */ + def votePoll(meetingId: String, userId: String, pollId: String, questionId: Integer, answerId: Integer) { bbbActor ! new RespondToPollRequest(meetingId, userId, pollId, questionId, answerId) } @@ -464,4 +469,18 @@ class BigBlueButtonInGW(val system: ActorSystem, recorderApp: RecorderApplicatio bbbActor ! new HidePollResultRequest(meetingId, requesterId, pollId) } } + + /** + * ******************************************************************* + * Message Interface for Caption + * ***************************************************************** + */ + + def sendCaptionHistory(meetingID: String, requesterID: String) { + bbbActor ! new SendCaptionHistoryRequest(meetingID, requesterID) + } + + def newCaptionLine(meetingID: String, lineNumber: Integer, locale: String, startTime: Integer, text: String) { + bbbActor ! new NewCaptionLineRequest(meetingID, lineNumber, locale, startTime, text) + } } diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MeetingActor.scala index 7b7fde789e..cc39b426cb 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MeetingActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MeetingActor.scala @@ -8,8 +8,8 @@ import org.bigbluebutton.core.api._ import java.util.concurrent.TimeUnit 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 } +import org.bigbluebutton.core.apps.{ PollApp, UsersApp, PresentationApp, LayoutApp, ChatApp, WhiteboardApp, CaptionApp } +import org.bigbluebutton.core.apps.{ ChatModel, LayoutModel, UsersModel, PollModel, WhiteboardModel, CaptionModel } import org.bigbluebutton.core.apps.PresentationModel object MeetingActor { @@ -19,7 +19,8 @@ object MeetingActor { class MeetingActor(val mProps: MeetingProperties, val outGW: OutMessageGateway) extends Actor with UsersApp with PresentationApp - with LayoutApp with ChatApp with WhiteboardApp with PollApp + with LayoutApp with ChatApp with WhiteboardApp + with PollApp with CaptionApp with ActorLogging { val chatModel = new ChatModel() @@ -29,6 +30,7 @@ class MeetingActor(val mProps: MeetingProperties, val outGW: OutMessageGateway) val pollModel = new PollModel() val wbModel = new WhiteboardModel() val presModel = new PresentationModel() + val captionModel = new CaptionModel() import context.dispatcher context.system.scheduler.schedule(2 seconds, 30 seconds, self, "MonitorNumberOfWebUsers") @@ -168,6 +170,10 @@ class MeetingActor(val mProps: MeetingProperties, val outGW: OutMessageGateway) handleGetPollRequest(msg) case msg: GetCurrentPollRequest => handleGetCurrentPollRequest(msg) + case msg: SendCaptionHistoryRequest => + handleSendCaptionHistoryRequest(msg) + case msg: NewCaptionLineRequest => + handleNewCaptionLineRequest(msg) case msg: EndMeeting => handleEndMeeting(msg) case StopMeetingActor => //exit diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MessageSenderActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MessageSenderActor.scala index 6b31329423..1d844e1830 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MessageSenderActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MessageSenderActor.scala @@ -11,6 +11,7 @@ import org.bigbluebutton.common.messages.StartRecordingVoiceConfRequestMessage import org.bigbluebutton.common.messages.StopRecordingVoiceConfRequestMessage import org.bigbluebutton.core.pubsub.senders.MeetingMessageToJsonConverter import org.bigbluebutton.core.pubsub.senders.PesentationMessageToJsonConverter +import org.bigbluebutton.core.pubsub.senders.CaptionMessageToJsonConverter import org.bigbluebutton.common.messages.GetPresentationInfoReplyMessage import org.bigbluebutton.common.messages.PresentationRemovedMessage import org.bigbluebutton.core.apps.Page @@ -112,6 +113,8 @@ class MessageSenderActor(val meetingId: String, val service: MessageSender) case msg: UndoWhiteboardEvent => handleUndoWhiteboardEvent(msg) case msg: WhiteboardEnabledEvent => handleWhiteboardEnabledEvent(msg) case msg: IsWhiteboardEnabledReply => handleIsWhiteboardEnabledReply(msg) + case msg: SendCaptionHistoryReply => handleSendCaptionHistoryReply(msg) + case msg: NewCaptionLineEvent => handleNewCaptionLineEvent(msg) case _ => // do nothing } @@ -644,4 +647,14 @@ class MessageSenderActor(val meetingId: String, val service: MessageSender) val json = WhiteboardMessageToJsonConverter.isWhiteboardEnabledReplyToJson(msg) service.send(MessagingConstants.FROM_WHITEBOARD_CHANNEL, json) } + + private def handleSendCaptionHistoryReply(msg: SendCaptionHistoryReply) { + val json = CaptionMessageToJsonConverter.sendCaptionHistoryReplyToJson(msg) + service.send(MessagingConstants.FROM_CAPTION_CHANNEL, json) + } + + private def handleNewCaptionLineEvent(msg: NewCaptionLineEvent) { + val json = CaptionMessageToJsonConverter.newCaptionLineEventToJson(msg) + service.send(MessagingConstants.FROM_CAPTION_CHANNEL, json) + } } diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/OutMessageGatewayActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/OutMessageGatewayActor.scala index 693e2d7c3b..d9851efec9 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/OutMessageGatewayActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/OutMessageGatewayActor.scala @@ -8,8 +8,8 @@ import org.bigbluebutton.core.api._ import java.util.concurrent.TimeUnit 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 } +import org.bigbluebutton.core.apps.{ PollApp, UsersApp, PresentationApp, LayoutApp, ChatApp, WhiteboardApp, CaptionApp } +import org.bigbluebutton.core.apps.{ ChatModel, LayoutModel, UsersModel, PollModel, WhiteboardModel, CaptionModel } import org.bigbluebutton.core.apps.PresentationModel import org.bigbluebutton.core.service.recorder.RecorderApplication diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala index 642c6a3be2..e37ff66b1f 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala @@ -115,3 +115,7 @@ case class UndoWhiteboardRequest(meetingID: String, requesterID: String, whitebo case class EnableWhiteboardRequest(meetingID: String, requesterID: String, enable: Boolean) extends InMessage case class IsWhiteboardEnabledRequest(meetingID: String, requesterID: String, replyTo: String) extends InMessage case class GetAllMeetingsRequest(meetingID: String /** Not used. Just to satisfy trait **/ ) extends InMessage + +// Caption +case class SendCaptionHistoryRequest(meetingID: String, requesterID: String) extends InMessage +case class NewCaptionLineRequest(meetingID: String, lineNumber: Integer, locale: String, startTime: Integer, text: String) extends InMessage \ No newline at end of file diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/MessageNames.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/MessageNames.scala index 5edf105068..f554b5ffcd 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/MessageNames.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/MessageNames.scala @@ -161,5 +161,7 @@ object MessageNames { val MEETING_DESTROYED_EVENT = "meeting_destroyed_event" val KEEP_ALIVE_REPLY = "keep_alive_reply" val USER_LISTEN_ONLY = "user_listening_only" - val GET_ALL_MEETINGS_REPLY = "get_all_meetings_reply" + val GET_ALL_MEETINGS_REPLY = "get_all_meetings_reply_message" + val NEW_CAPTION_LINE = "new_caption_line_message" + val SEND_CAPTION_HISTORY_REPLY = "send_caption_history_reply_message" } \ No newline at end of file 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 6facf5b5c0..86268b2f66 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 @@ -130,6 +130,10 @@ case class WhiteboardEnabledEvent(meetingID: String, recorded: Boolean, requeste case class IsWhiteboardEnabledReply(meetingID: String, recorded: Boolean, requesterID: String, enabled: Boolean, replyTo: String) extends IOutMessage case class GetAllMeetingsReply(meetings: Array[MeetingInfo]) extends IOutMessage +// Chat +case class SendCaptionHistoryReply(meetingID: String, recorded: Boolean, requesterID: String, history: Map[String, Array[String]]) extends IOutMessage +case class NewCaptionLineEvent(meetingID: String, recorded: Boolean, lineNumber: Integer, locale: String, startTime: Integer, text: String) extends IOutMessage + // Value Objects case class MeetingVO(id: String, recorded: Boolean) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/CaptionApp.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/CaptionApp.scala new file mode 100755 index 0000000000..4ad6c100e6 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/CaptionApp.scala @@ -0,0 +1,24 @@ +package org.bigbluebutton.core.apps + +import org.bigbluebutton.core.api._ +import scala.collection.mutable.ArrayBuffer +import org.bigbluebutton.core.MeetingActor +import org.bigbluebutton.core.OutMessageGateway + +trait CaptionApp { + this: MeetingActor => + + val outGW: OutMessageGateway + + def handleSendCaptionHistoryRequest(msg: SendCaptionHistoryRequest) { + var history = captionModel.getCaptionHistory() + + outGW.send(new SendCaptionHistoryReply(mProps.meetingID, mProps.recorded, msg.requesterID, history)) + } + + def handleNewCaptionLineRequest(msg: NewCaptionLineRequest) { + captionModel.addNewCaptionLine(msg.locale, msg.text) + + outGW.send(new NewCaptionLineEvent(mProps.meetingID, mProps.recorded, msg.lineNumber, msg.locale, msg.startTime, msg.text)) + } +} \ No newline at end of file diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/CaptionModel.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/CaptionModel.scala new file mode 100755 index 0000000000..187d9c4aa1 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/CaptionModel.scala @@ -0,0 +1,27 @@ +package org.bigbluebutton.core.apps + +import scala.collection.mutable.ArrayBuffer +import scala.collection.immutable.HashMap + +class CaptionModel { + var transcripts = Map[String, ArrayBuffer[String]]() + + def getCaptionHistory(): Map[String, Array[String]] = { + var history = Map[String, Array[String]]() + + transcripts.foreach(t => { + history += t._1 -> t._2.toArray + }) + + history + } + + def addNewCaptionLine(locale: String, text: String) { + if (transcripts contains locale) { + // do nothing + } else { + transcripts += locale -> new ArrayBuffer[String]() + } + transcripts(locale) append text + } +} \ No newline at end of file diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/CaptionMessageToJsonConverter.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/CaptionMessageToJsonConverter.scala new file mode 100755 index 0000000000..3ca45ea8d6 --- /dev/null +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/CaptionMessageToJsonConverter.scala @@ -0,0 +1,33 @@ +package org.bigbluebutton.core.pubsub.senders + +import org.bigbluebutton.common.messages.Constants +import scala.collection.mutable.HashMap +import org.bigbluebutton.core.api._ +import collection.JavaConverters._ +import scala.collection.JavaConversions._ +import org.bigbluebutton.core.messaging.Util + +object CaptionMessageToJsonConverter { + def sendCaptionHistoryReplyToJson(msg: SendCaptionHistoryReply): String = { + val payload = new java.util.HashMap[String, Any]() + payload.put(Constants.MEETING_ID, msg.meetingID) + payload.put(Constants.REQUESTER_ID, msg.requesterID) + + payload.put(Constants.CAPTION_HISTORY, mapAsJavaMap(msg.history)) + + val header = Util.buildHeader(MessageNames.SEND_CAPTION_HISTORY_REPLY, Some(msg.requesterID)) + Util.buildJson(header, payload) + } + + def newCaptionLineEventToJson(msg: NewCaptionLineEvent): String = { + val payload = new java.util.HashMap[String, Any]() + payload.put(Constants.MEETING_ID, msg.meetingID) + payload.put(Constants.LINE_NUMBER, msg.lineNumber) + payload.put(Constants.LOCALE, msg.locale) + payload.put(Constants.START_TIME, msg.startTime) + payload.put(Constants.TEXT, msg.text) + + val header = Util.buildHeader(MessageNames.NEW_CAPTION_LINE, None) + Util.buildJson(header, payload) + } +} \ No newline at end of file diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/Constants.java b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/Constants.java index 0ec0c7b8a6..57a938245d 100755 --- a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/Constants.java +++ b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/Constants.java @@ -128,4 +128,5 @@ public class Constants { public static final String LOCALE = "locale"; public static final String START_TIME = "start_time"; public static final String TEXT = "text"; + public static final String CAPTION_HISTORY = "caption_history"; } diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/MessagingConstants.java b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/MessagingConstants.java index 030643d150..e3e3ecc64a 100755 --- a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/MessagingConstants.java +++ b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/MessagingConstants.java @@ -29,6 +29,7 @@ public class MessagingConstants { public static final String FROM_USERS_CHANNEL = FROM_BBB_APPS_CHANNEL + ":users"; public static final String FROM_CHAT_CHANNEL = FROM_BBB_APPS_CHANNEL + ":chat"; public static final String FROM_WHITEBOARD_CHANNEL = FROM_BBB_APPS_CHANNEL + ":whiteboard"; + public static final String FROM_CAPTION_CHANNEL = FROM_BBB_APPS_CHANNEL + ":caption"; public static final String TO_BBB_APPS_CHANNEL = "bigbluebutton:to-bbb-apps"; public static final String TO_BBB_APPS_PATTERN = TO_BBB_APPS_CHANNEL + ":*"; diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/NewCaptionLineMessage.java b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/NewCaptionLineMessage.java index f0d928b17d..1e874c472d 100755 --- a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/NewCaptionLineMessage.java +++ b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/NewCaptionLineMessage.java @@ -25,7 +25,7 @@ public class NewCaptionLineMessage implements ISubscribedMessage { public String toJson() { HashMap payload = new HashMap(); - payload.put(Constants.MEETING_ID, meetingId); + payload.put(Constants.MEETING_ID, meetingID); payload.put(Constants.LINE_NUMBER, lineNumber); payload.put(Constants.LOCALE, locale); payload.put(Constants.START_TIME, startTime); @@ -49,7 +49,7 @@ public class NewCaptionLineMessage implements ISubscribedMessage { if (NEW_CAPTION_LINE.equals(messageName)) { if (payload.has(Constants.MEETING_ID) && payload.has(Constants.LINE_NUMBER) - && payload.has(Constants.LOCALE, locale) + && payload.has(Constants.LOCALE) && payload.has(Constants.START_TIME) && payload.has(Constants.TEXT)) { String meetingID = payload.get(Constants.MEETING_ID).getAsString(); diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/SendCaptionHistoryReplyMessage.java b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/SendCaptionHistoryReplyMessage.java new file mode 100755 index 0000000000..668ec151db --- /dev/null +++ b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/SendCaptionHistoryReplyMessage.java @@ -0,0 +1,64 @@ +package org.bigbluebutton.common.messages; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +public class SendCaptionHistoryReplyMessage implements ISubscribedMessage { + public static final String SEND_CAPTION_HISTORY_REPLY = "send_caption_history_reply_message"; + public static final String VERSION = "0.0.1"; + + public final String meetingID; + public final String requesterID; + public final Map> captionHistory; + + public SendCaptionHistoryReplyMessage(String meetingID, String requesterID, Map> captionHistory) { + this.meetingID = meetingID; + this.captionHistory = captionHistory; + this.requesterID = requesterID; + } + + public String toJson() { + HashMap payload = new HashMap(); + payload.put(Constants.MEETING_ID, meetingID); + payload.put(Constants.REQUESTER_ID, requesterID); + payload.put(Constants.CHAT_HISTORY, captionHistory); + + java.util.HashMap header = MessageBuilder.buildHeader(SEND_CAPTION_HISTORY_REPLY, VERSION, null); + return MessageBuilder.buildJson(header, payload); + } + + public static SendCaptionHistoryReplyMessage fromJson(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"); + JsonObject payload = (JsonObject) obj.get("payload"); + + if (header.has("name")) { + String messageName = header.get("name").getAsString(); + if (SEND_CAPTION_HISTORY_REPLY.equals(messageName)) { + if (payload.has(Constants.MEETING_ID) + && payload.has(Constants.CAPTION_HISTORY) + && payload.has(Constants.REQUESTER_ID)) { + String meetingID = payload.get(Constants.MEETING_ID).getAsString(); + String requesterID = payload.get(Constants.REQUESTER_ID).getAsString(); + + JsonObject history = (JsonObject) payload.get(Constants.CAPTION_HISTORY); + + Util util = new Util(); + + Map> captionHistory = util.extractCaptionHistory(history); + + return new SendCaptionHistoryReplyMessage(meetingID, requesterID, captionHistory); + } + } + } + } + return null; + } +} diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/SendCaptionHistoryMessage.java b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/SendCaptionHistoryRequestMessage.java similarity index 66% rename from bbb-common-message/src/main/java/org/bigbluebutton/common/messages/SendCaptionHistoryMessage.java rename to bbb-common-message/src/main/java/org/bigbluebutton/common/messages/SendCaptionHistoryRequestMessage.java index 7c0318e4c5..2e2133b874 100755 --- a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/SendCaptionHistoryMessage.java +++ b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/SendCaptionHistoryRequestMessage.java @@ -5,29 +5,29 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; -public class SendCaptionHistoryMessage implements ISubscribedMessage { - public static final String SEND_CAPTION_HISTORY = "send_caption_history_message"; +public class SendCaptionHistoryRequestMessage implements ISubscribedMessage { + public static final String SEND_CAPTION_HISTORY_REQUEST = "send_caption_history_request_message"; public static final String VERSION = "0.0.1"; public final String meetingID; public final String requesterID; - public SendCaptionHistoryMessage(String meetingID, String requesterID) { + public SendCaptionHistoryRequestMessage(String meetingID, String requesterID) { this.meetingID = meetingID; this.requesterID = requesterID; } public String toJson() { HashMap payload = new HashMap(); - payload.put(Constants.MEETING_ID, meetingId); + payload.put(Constants.MEETING_ID, meetingID); payload.put(Constants.REQUESTER_ID, requesterID); - java.util.HashMap header = MessageBuilder.buildHeader(SEND_CAPTION_HISTORY, VERSION, null); + java.util.HashMap header = MessageBuilder.buildHeader(SEND_CAPTION_HISTORY_REQUEST, VERSION, null); return MessageBuilder.buildJson(header, payload); } - public static SendCaptionHistoryMessage fromJson(String message) { + public static SendCaptionHistoryRequestMessage fromJson(String message) { JsonParser parser = new JsonParser(); JsonObject obj = (JsonObject) parser.parse(message); @@ -37,13 +37,13 @@ public class SendCaptionHistoryMessage implements ISubscribedMessage { if (header.has("name")) { String messageName = header.get("name").getAsString(); - if (SEND_CAPTION_HISTORY.equals(messageName)) { + if (SEND_CAPTION_HISTORY_REQUEST.equals(messageName)) { if (payload.has(Constants.MEETING_ID) && payload.has(Constants.REQUESTER_ID)) { String meetingID = payload.get(Constants.MEETING_ID).getAsString(); String requesterID = payload.get(Constants.REQUESTER_ID).getAsString(); - return new SendCaptionHistoryMessage(meetingID, requesterID); + return new SendCaptionHistoryRequestMessage(meetingID, requesterID); } } } diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/Util.java b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/Util.java index 6e79a3a7cc..13ef7d2b09 100755 --- a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/Util.java +++ b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/Util.java @@ -671,5 +671,22 @@ public class Util { return pollMap; } + public Map> extractCaptionHistory(JsonObject history) { + Map> collection = new HashMap>(); + + for (Map.Entry entry : history.entrySet()) { + String locale = entry.getKey(); + JsonArray linesJSON = entry.getValue().getAsJsonArray(); + + ArrayList lines = new ArrayList(); + for (JsonElement line : linesJSON) { + lines.add(line.getAsString()); + } + + collection.put(locale, lines); + } + + return collection; + } } \ No newline at end of file diff --git a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/CaptionClientMessageSender.java b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/CaptionClientMessageSender.java new file mode 100755 index 0000000000..7810bbd80c --- /dev/null +++ b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/CaptionClientMessageSender.java @@ -0,0 +1,73 @@ +package org.bigbluebutton.red5.client; + +import java.util.HashMap; +import java.util.Map; + +import org.bigbluebutton.common.messages.Constants; +import org.bigbluebutton.common.messages.NewCaptionLineMessage; +import org.bigbluebutton.common.messages.SendCaptionHistoryReplyMessage; +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 CaptionClientMessageSender { + private ConnectionInvokerService service; + + public CaptionClientMessageSender(ConnectionInvokerService service) { + this.service = service; + } + + public void handleCaptionMessage(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 NewCaptionLineMessage.NEW_CAPTION_LINE: + NewCaptionLineMessage ncl = NewCaptionLineMessage.fromJson(message); + + if (ncl != null) { + processNewCaptionLineMessage(ncl); + } + break; + case SendCaptionHistoryReplyMessage.SEND_CAPTION_HISTORY_REPLY: + SendCaptionHistoryReplyMessage sch = SendCaptionHistoryReplyMessage.fromJson(message); + + if (sch != null) { + processSendCaptionHistoryReplyMessage(sch); + } + break; + } + } + } + } + + private void processNewCaptionLineMessage(NewCaptionLineMessage msg) { + Map message = new HashMap(); + message.put(Constants.LINE_NUMBER, msg.lineNumber); + message.put(Constants.LOCALE, msg.locale); + message.put(Constants.START_TIME, msg.startTime); + message.put(Constants.TEXT, msg.text); + + BroadcastClientMessage m = new BroadcastClientMessage(msg.meetingID, "newCaptionLine", message); + service.sendMessage(m); + } + + private void processSendCaptionHistoryReplyMessage(SendCaptionHistoryReplyMessage msg) { + Map message = new HashMap(); + Gson gson = new Gson(); + message.put("msg", gson.toJson(msg.captionHistory)); + + DirectClientMessage m = new DirectClientMessage(msg.meetingID, msg.requesterID, "sendCaptionHistoryReply", message); + service.sendMessage(m); + } +} 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 7f6af7f824..c7d9c7c806 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 @@ -272,7 +272,7 @@ public class MessagePublisher { } public void sendCaptionHistory(String meetingID, String requesterID) { - SendCaptionHistoryMessage msg = new SendCaptionHistoryMessage(meetingID, requesterID); + SendCaptionHistoryRequestMessage msg = new SendCaptionHistoryRequestMessage(meetingID, requesterID); sender.send(MessagingConstants.TO_CAPTION_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 9c1d33831d..7a6a65dc13 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 @@ -7,6 +7,7 @@ import org.bigbluebutton.red5.client.PresentationClientMessageSender; import org.bigbluebutton.red5.client.UserClientMessageSender; import org.bigbluebutton.red5.client.ChatClientMessageSender; import org.bigbluebutton.red5.client.WhiteboardClientMessageSender; +import org.bigbluebutton.red5.client.CaptionClientMessageSender; import org.bigbluebutton.red5.client.messaging.ConnectionInvokerService; import org.bigbluebutton.red5.monitoring.BbbAppsIsKeepAliveHandler; @@ -20,6 +21,7 @@ public class RedisPubSubMessageHandler implements MessageHandler { private WhiteboardClientMessageSender whiteboardMessageSender; private BbbAppsIsKeepAliveHandler bbbAppsIsKeepAliveHandler; private PollingClientMessageSender pollingMessageSender; + private CaptionClientMessageSender captionMessageSender; public void setConnectionInvokerService(ConnectionInvokerService s) { this.service = s; @@ -29,6 +31,7 @@ public class RedisPubSubMessageHandler implements MessageHandler { presentationMessageSender = new PresentationClientMessageSender(service); whiteboardMessageSender = new WhiteboardClientMessageSender(service); pollingMessageSender = new PollingClientMessageSender(service); + captionMessageSender = new CaptionClientMessageSender(service); } public void setBbbAppsIsKeepAliveHandler(BbbAppsIsKeepAliveHandler handler) { @@ -51,6 +54,8 @@ public class RedisPubSubMessageHandler implements MessageHandler { bbbAppsIsKeepAliveHandler.handleKeepAliveMessage(message); } else if (channel.equalsIgnoreCase(MessagingConstants.FROM_POLLING_CHANNEL)) { pollingMessageSender.handlePollMessage(message); + } else if (channel.equalsIgnoreCase(MessagingConstants.FROM_CAPTION_CHANNEL)) { + captionMessageSender.handleCaptionMessage(message); } } diff --git a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/service/CaptionService.java b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/service/CaptionService.java index 7fd06df166..f883a121d9 100755 --- a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/service/CaptionService.java +++ b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/service/CaptionService.java @@ -28,7 +28,7 @@ import org.red5.server.api.Red5; import org.slf4j.Logger; public class CaptionService { - private static Logger log = Red5LoggerFactory.getLogger( ChatService.class, "bigbluebutton" ); + private static Logger log = Red5LoggerFactory.getLogger( CaptionService.class, "bigbluebutton" ); private MessagePublisher red5InGW; @@ -47,7 +47,7 @@ public class CaptionService { red5InGW.sendCaptionHistory(meetingID, requesterID); } - public void sendPublicMessage(Map msg) { + public void newCaptionLine(Map msg) { log.debug("Received new caption line request"); int lineNumber = (Integer) msg.get("lineNumber"); String locale = msg.get("locale").toString(); 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 56b16c64eb..cf47b3cb2a 100755 --- a/bigbluebutton-apps/src/main/webapp/WEB-INF/red5-web.xml +++ b/bigbluebutton-apps/src/main/webapp/WEB-INF/red5-web.xml @@ -96,6 +96,10 @@ with BigBlueButton; if not, see . + + + +