Merge branch 'master' of https://github.com/bigbluebutton/bigbluebutton into closed-captioning-ui
@ -111,8 +111,8 @@ public interface IBigBlueButtonInGW {
|
||||
|
||||
// Caption
|
||||
void sendCaptionHistory(String meetingID, String requesterID);
|
||||
void updateCaptionOwner(String meetingID, String locale, String ownerID);
|
||||
void editCaptionHistory(String meetingID, String userID, Integer startIndex, Integer endIndex, String locale, String text);
|
||||
void updateCaptionOwner(String meetingID, String locale, String localeCode, String ownerID);
|
||||
void editCaptionHistory(String meetingID, String userID, Integer startIndex, Integer endIndex, String locale, String localeCode, String text);
|
||||
|
||||
// DeskShare
|
||||
void deskShareStarted(String confId, String callerId, String callerIdName);
|
||||
|
@ -32,10 +32,10 @@ public class CaptionMessageReceiver implements MessageHandler{
|
||||
bbbGW.sendCaptionHistory(msg.meetingID, msg.requesterID);
|
||||
} else if (UpdateCaptionOwnerMessage.UPDATE_CAPTION_OWNER.equals(messageName)) {
|
||||
UpdateCaptionOwnerMessage msg = UpdateCaptionOwnerMessage.fromJson(message);
|
||||
bbbGW.updateCaptionOwner(msg.meetingID, msg.locale, msg.ownerID);
|
||||
bbbGW.updateCaptionOwner(msg.meetingID, msg.locale, msg.localeCode, msg.ownerID);
|
||||
} else if (EditCaptionHistoryMessage.EDIT_CAPTION_HISTORY.equals(messageName)) {
|
||||
EditCaptionHistoryMessage msg = EditCaptionHistoryMessage.fromJson(message);
|
||||
bbbGW.editCaptionHistory(msg.meetingID, msg.userID, msg.startIndex, msg.endIndex, msg.locale, msg.text);
|
||||
bbbGW.editCaptionHistory(msg.meetingID, msg.userID, msg.startIndex, msg.endIndex, msg.locale, msg.localeCode, msg.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ public class EditCaptionHistoryRecordEvent extends AbstractCaptionRecordEvent {
|
||||
private static final String START_INDEX = "startIndex";
|
||||
private static final String END_INDEX = "endIndex";
|
||||
private static final String LOCALE = "locale";
|
||||
private static final String LOCALE_CODE = "localeCode";
|
||||
private static final String TEXT = "text";
|
||||
|
||||
public EditCaptionHistoryRecordEvent() {
|
||||
@ -33,7 +34,7 @@ public class EditCaptionHistoryRecordEvent extends AbstractCaptionRecordEvent {
|
||||
public void setStartIndex(String startIndex) {
|
||||
eventMap.put(START_INDEX, startIndex);
|
||||
}
|
||||
|
||||
|
||||
public void setEndIndex(String endIndex) {
|
||||
eventMap.put(END_INDEX, endIndex);
|
||||
}
|
||||
@ -42,6 +43,10 @@ public class EditCaptionHistoryRecordEvent extends AbstractCaptionRecordEvent {
|
||||
eventMap.put(LOCALE, locale);
|
||||
}
|
||||
|
||||
public void setLocaleCode(String localeCode) {
|
||||
eventMap.put(LOCALE_CODE, localeCode);
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
eventMap.put(TEXT, text);
|
||||
}
|
||||
|
@ -28,6 +28,10 @@ public class ParticipantJoinRecordEvent extends AbstractParticipantRecordEvent {
|
||||
public void setUserId(String userId) {
|
||||
eventMap.put("userId", userId);
|
||||
}
|
||||
|
||||
public void setExternalUserId(String externalUserId) {
|
||||
eventMap.put("externalUserId", externalUserId);
|
||||
}
|
||||
|
||||
public void setName(String name){
|
||||
eventMap.put("name",name);
|
||||
|
@ -43,7 +43,6 @@ http {
|
||||
services {
|
||||
bbbWebAPI = "http://192.168.23.33/bigbluebutton/api"
|
||||
sharedSecret = "changeme"
|
||||
defaultPresentationURL = "http://localhost/default.pdf"
|
||||
}
|
||||
|
||||
red5 {
|
||||
|
@ -18,7 +18,6 @@ trait SystemConfiguration {
|
||||
lazy val bbbWebSharedSecret = Try(config.getString("services.sharedSecret")).getOrElse("changeme")
|
||||
lazy val bbbWebModeratorPassword = Try(config.getString("services.moderatorPassword")).getOrElse("changeme")
|
||||
lazy val bbbWebViewerPassword = Try(config.getString("services.viewerPassword")).getOrElse("changeme")
|
||||
lazy val bbbWebDefaultPresentationURL = Try(config.getString("services.defaultPresentationURL")).getOrElse("changeme")
|
||||
lazy val keysExpiresInSec = Try(config.getInt("redis.keyExpiry")).getOrElse(14 * 86400) // 14 days
|
||||
lazy val red5DeskShareIP = Try(config.getString("red5.deskshareip")).getOrElse("127.0.0.1")
|
||||
lazy val red5DeskShareApp = Try(config.getString("red5.deskshareapp")).getOrElse("")
|
||||
|
@ -39,7 +39,7 @@ class BigBlueButtonInGW(
|
||||
case msg: StartCustomPollRequestMessage => {
|
||||
eventBus.publish(
|
||||
BigBlueButtonEvent(
|
||||
"meeting-manager",
|
||||
msg.payload.meetingId,
|
||||
new StartCustomPollRequest(
|
||||
msg.payload.meetingId,
|
||||
msg.payload.requesterId,
|
||||
@ -558,11 +558,11 @@ class BigBlueButtonInGW(
|
||||
eventBus.publish(BigBlueButtonEvent(meetingID, new SendCaptionHistoryRequest(meetingID, requesterID)))
|
||||
}
|
||||
|
||||
def updateCaptionOwner(meetingID: String, locale: String, ownerID: String) {
|
||||
eventBus.publish(BigBlueButtonEvent(meetingID, new UpdateCaptionOwnerRequest(meetingID, locale, ownerID)))
|
||||
def updateCaptionOwner(meetingID: String, locale: String, localeCode: String, ownerID: String) {
|
||||
eventBus.publish(BigBlueButtonEvent(meetingID, new UpdateCaptionOwnerRequest(meetingID, locale, localeCode, ownerID)))
|
||||
}
|
||||
|
||||
def editCaptionHistory(meetingID: String, userID: String, startIndex: Integer, endIndex: Integer, locale: String, text: String) {
|
||||
eventBus.publish(BigBlueButtonEvent(meetingID, new EditCaptionHistoryRequest(meetingID, userID, startIndex, endIndex, locale, text)))
|
||||
def editCaptionHistory(meetingID: String, userID: String, startIndex: Integer, endIndex: Integer, locale: String, localeCode: String, text: String) {
|
||||
eventBus.publish(BigBlueButtonEvent(meetingID, new EditCaptionHistoryRequest(meetingID, userID, startIndex, endIndex, locale, localeCode, text)))
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ class JsonMessageSenderActor(val service: MessageSender)
|
||||
private def handleCreateBreakoutRoom(msg: CreateBreakoutRoom) {
|
||||
val payload = new CreateBreakoutRoomRequestPayload(msg.room.breakoutId, msg.room.parentId, msg.room.name,
|
||||
msg.room.voiceConfId, msg.room.viewerPassword, msg.room.moderatorPassword,
|
||||
msg.room.durationInMinutes, msg.room.defaultPresentationURL, msg.room.record)
|
||||
msg.room.durationInMinutes, msg.room.sourcePresentationId, msg.room.sourcePresentationSlide, msg.room.record)
|
||||
val request = new CreateBreakoutRoomRequest(payload)
|
||||
service.send(MessagingConstants.FROM_MEETING_CHANNEL, request.toJson())
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ class LiveMeeting(val mProps: MeetingProperties,
|
||||
meetingModel.meetingHasEnded
|
||||
|
||||
/**
|
||||
* See if this meeting has breakout rooms. If so, we also need to end them.
|
||||
* Check if this meeting has breakout rooms. If so, we also need to end them.
|
||||
*/
|
||||
handleEndAllBreakoutRooms(new EndAllBreakoutRooms(msg.meetingId))
|
||||
|
||||
|
@ -33,7 +33,7 @@ object UserMessagesProtocol extends DefaultJsonProtocol {
|
||||
implicit val inMsgHeaderFormat = jsonFormat1(InMessageHeader)
|
||||
implicit val outMsgHeaderFormat = jsonFormat1(OutMsgHeader)
|
||||
implicit val outMsgEnvelopeHeaderFormat = jsonFormat2(OutMsgEnvelopeHeader)
|
||||
implicit val createBreakoutRoomOutMsgPayloadFormat = jsonFormat8(CreateBreakoutRoomOutMsgPayload)
|
||||
implicit val createBreakoutRoomOutMsgPayloadFormat = jsonFormat10(CreateBreakoutRoomOutMsgPayload)
|
||||
implicit val createBreakoutRoomOutMsgEnvelopePayloadFormat = jsonFormat2(CreateBreakoutRoomOutMsgEnvelopePayload)
|
||||
implicit val createBreakoutRoomOutMsgEnvelopeFormat = jsonFormat2(CreateBreakoutRoomOutMsgEnvelope)
|
||||
|
||||
|
@ -5,12 +5,10 @@ case class OutMsgEnvelopeHeader(`type`: MessageType.MessageType, address: String
|
||||
|
||||
trait OutMessage
|
||||
|
||||
case class CreateBreakoutRoomOutMsgEnvelope(header: OutMsgEnvelopeHeader,
|
||||
payload: CreateBreakoutRoomOutMsgEnvelopePayload)
|
||||
case class CreateBreakoutRoomOutMsgEnvelopePayload(header: OutMsgHeader,
|
||||
payload: CreateBreakoutRoomOutMsgPayload)
|
||||
case class CreateBreakoutRoomOutMsgEnvelope(header: OutMsgEnvelopeHeader, payload: CreateBreakoutRoomOutMsgEnvelopePayload)
|
||||
case class CreateBreakoutRoomOutMsgEnvelopePayload(header: OutMsgHeader, payload: CreateBreakoutRoomOutMsgPayload)
|
||||
case class CreateBreakoutRoomOutMsgPayload(breakoutId: String, name: String, parentId: String,
|
||||
voiceConfId: String, durationInMinutes: Int,
|
||||
moderatorPassword: String, viewerPassword: String,
|
||||
defaultPresentationUrl: String)
|
||||
sourcePresentationId: String, sourcePresentationSlide: Int, record: Boolean)
|
||||
|
||||
|
@ -196,6 +196,7 @@ class RecorderActor(val recorder: RecorderApplication)
|
||||
val ev = new ParticipantJoinRecordEvent();
|
||||
ev.setTimestamp(TimestampGenerator.generateTimestamp);
|
||||
ev.setUserId(msg.user.userID);
|
||||
ev.setExternalUserId(msg.user.externUserID);
|
||||
ev.setName(msg.user.name);
|
||||
ev.setMeetingId(msg.meetingID);
|
||||
ev.setRole(msg.user.role.toString());
|
||||
@ -452,6 +453,7 @@ class RecorderActor(val recorder: RecorderApplication)
|
||||
ev.setStartIndex(msg.startIndex.toString());
|
||||
ev.setEndIndex(msg.endIndex.toString());
|
||||
ev.setLocale(msg.locale);
|
||||
ev.setLocaleCode(msg.localeCode);
|
||||
ev.setText(msg.text);
|
||||
recorder.record(msg.meetingID, ev);
|
||||
}
|
||||
|
@ -187,8 +187,8 @@ case class GetAllMeetingsRequest(meetingID: String /** Not used. Just to satisfy
|
||||
|
||||
// Caption
|
||||
case class SendCaptionHistoryRequest(meetingID: String, requesterID: String) extends InMessage
|
||||
case class UpdateCaptionOwnerRequest(meetingID: String, locale: String, ownerID: String) extends InMessage
|
||||
case class EditCaptionHistoryRequest(meetingID: String, userID: String, startIndex: Integer, endIndex: Integer, locale: String, text: String) extends InMessage
|
||||
case class UpdateCaptionOwnerRequest(meetingID: String, locale: String, localeCode: String, ownerID: String) extends InMessage
|
||||
case class EditCaptionHistoryRequest(meetingID: String, userID: String, startIndex: Integer, endIndex: Integer, locale: String, localeCode: String, text: String) extends InMessage
|
||||
// DeskShare
|
||||
case class DeskShareStartedRequest(conferenceName: String, callerId: String, callerIdName: String) extends InMessage
|
||||
case class DeskShareStoppedRequest(conferenceName: String, callerId: String, callerIdName: String) extends InMessage
|
||||
|
@ -33,7 +33,7 @@ case class CreateBreakoutRoom(meetingId: String, room: BreakoutRoomOutPayload) e
|
||||
case class EndBreakoutRoom(breakoutId: String) extends IOutMessage
|
||||
case class BreakoutRoomOutPayload(breakoutId: String, name: String, parentId: String,
|
||||
voiceConfId: String, durationInMinutes: Int, moderatorPassword: String, viewerPassword: String,
|
||||
defaultPresentationURL: String, record: Boolean)
|
||||
sourcePresentationId: String, sourcePresentationSlide: Int, record: Boolean)
|
||||
case class BreakoutRoomJoinURLOutMessage(meetingId: String, recorded: Boolean, breakoutId: String, userId: String, joinURL: String) extends IOutMessage
|
||||
case class BreakoutRoomStartedOutMessage(meetingId: String, recorded: Boolean, breakout: BreakoutRoomBody) extends IOutMessage
|
||||
case class BreakoutRoomBody(name: String, breakoutId: String)
|
||||
@ -146,10 +146,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
|
||||
// Caption
|
||||
case class SendCaptionHistoryReply(meetingID: String, recorded: Boolean, requesterID: String, history: Map[String, Array[String]]) extends IOutMessage
|
||||
case class UpdateCaptionOwnerReply(meetingID: String, recorded: Boolean, locale: String, ownerID: String) extends IOutMessage
|
||||
case class EditCaptionHistoryReply(meetingID: String, recorded: Boolean, userID: String, startIndex: Integer, endIndex: Integer, locale: String, text: String) extends IOutMessage
|
||||
case class UpdateCaptionOwnerReply(meetingID: String, recorded: Boolean, locale: String, localeCode: String, ownerID: String) extends IOutMessage
|
||||
case class EditCaptionHistoryReply(meetingID: String, recorded: Boolean, userID: String, startIndex: Integer, endIndex: Integer, locale: String, localeCode: String, text: String) extends IOutMessage
|
||||
// DeskShare
|
||||
case class DeskShareStartRTMPBroadcast(conferenceName: String, streamPath: String) extends IOutMessage
|
||||
case class DeskShareStopRTMPBroadcast(conferenceName: String, streamPath: String) extends IOutMessage
|
||||
|
@ -20,15 +20,6 @@ trait BreakoutRoomApp extends SystemConfiguration {
|
||||
val outGW: OutMessageGateway
|
||||
val eventBus: IncomingEventBus
|
||||
|
||||
def getDefaultPresentationURL(): String = {
|
||||
var presURL = bbbWebDefaultPresentationURL
|
||||
val page = presModel.getCurrentPage()
|
||||
page foreach { p =>
|
||||
presURL = BreakoutRoomsUtil.fromSWFtoPDF(p.swfUri)
|
||||
}
|
||||
presURL
|
||||
}
|
||||
|
||||
def handleBreakoutRoomsList(msg: BreakoutRoomsListMessage) {
|
||||
val breakoutRooms = breakoutModel.getRooms().toVector map { r => new BreakoutRoomBody(r.name, r.id) }
|
||||
outGW.send(new BreakoutRoomsListOutMessage(mProps.meetingID, breakoutRooms, breakoutModel.pendingRoomsNumber == 0 && breakoutRooms.length > 0));
|
||||
@ -40,17 +31,20 @@ trait BreakoutRoomApp extends SystemConfiguration {
|
||||
log.warning("CreateBreakoutRooms event received while {} are pending to be created for meeting {}", breakoutModel.pendingRoomsNumber, mProps.meetingID)
|
||||
return
|
||||
}
|
||||
|
||||
var i = 0
|
||||
val sourcePresentationId = presModel.getCurrentPresentation().get.id
|
||||
val sourcePresentationSlide = presModel.getCurrentPage().get.num
|
||||
breakoutModel.pendingRoomsNumber = msg.rooms.length;
|
||||
|
||||
for (room <- msg.rooms) {
|
||||
i += 1
|
||||
val presURL = bbbWebDefaultPresentationURL
|
||||
val breakoutMeetingId = BreakoutRoomsUtil.createMeetingId(mProps.meetingID, i)
|
||||
val voiceConfId = BreakoutRoomsUtil.createVoiceConfId(mProps.voiceBridge, i)
|
||||
val r = breakoutModel.createBreakoutRoom(breakoutMeetingId, room.name, voiceConfId, room.users, presURL)
|
||||
val r = breakoutModel.createBreakoutRoom(breakoutMeetingId, room.name, voiceConfId, room.users)
|
||||
val p = new BreakoutRoomOutPayload(r.id, r.name, mProps.meetingID,
|
||||
r.voiceConfId, msg.durationInMinutes, mProps.moderatorPass, mProps.viewerPass,
|
||||
r.defaultPresentationURL, msg.record)
|
||||
sourcePresentationId, sourcePresentationSlide, msg.record)
|
||||
outGW.send(new CreateBreakoutRoom(mProps.meetingID, p))
|
||||
}
|
||||
meetingModel.breakoutRoomsdurationInMinutes = msg.durationInMinutes;
|
||||
@ -85,7 +79,7 @@ trait BreakoutRoomApp extends SystemConfiguration {
|
||||
breakoutModel.getRooms().foreach { room =>
|
||||
breakoutModel.getAssignedUsers(room.id) foreach { users =>
|
||||
users.foreach { u =>
|
||||
log.debug("## Sending Join URL for users: {}", u);
|
||||
log.debug("Sending Join URL for users: {}", u);
|
||||
sendJoinURL(u, room.id)
|
||||
}
|
||||
}
|
||||
@ -181,7 +175,7 @@ object BreakoutRoomsUtil {
|
||||
}
|
||||
|
||||
def joinParams(username: String, userId: String, isBreakout: Boolean, breakoutId: String,
|
||||
password: String, redirect: Boolean): mutable.Map[String, String] = {
|
||||
password: String, redirect: Boolean): mutable.Map[String, String] = {
|
||||
val params = new collection.mutable.HashMap[String, String]
|
||||
params += "fullName" -> urlEncode(username)
|
||||
params += "userID" -> urlEncode(userId + "-" + breakoutId.substring(breakoutId.lastIndexOf("-") + 1));
|
||||
|
@ -5,7 +5,7 @@ import scala.collection.immutable.HashMap
|
||||
|
||||
case class BreakoutUser(id: String, name: String)
|
||||
case class BreakoutRoom(id: String, name: String, voiceConfId: String,
|
||||
assignedUsers: Vector[String], users: Vector[BreakoutUser], defaultPresentationURL: String)
|
||||
assignedUsers: Vector[String], users: Vector[BreakoutUser])
|
||||
|
||||
class BreakoutRoomModel {
|
||||
private var rooms = new collection.immutable.HashMap[String, BreakoutRoom]
|
||||
@ -22,8 +22,8 @@ class BreakoutRoomModel {
|
||||
}
|
||||
|
||||
def createBreakoutRoom(id: String, name: String, voiceConfId: String,
|
||||
assignedUsers: Vector[String], defaultPresentationURL: String): BreakoutRoom = {
|
||||
val room = new BreakoutRoom(id, name, voiceConfId, assignedUsers, Vector(), defaultPresentationURL)
|
||||
assignedUsers: Vector[String]): BreakoutRoom = {
|
||||
val room = new BreakoutRoom(id, name, voiceConfId, assignedUsers, Vector())
|
||||
add(room)
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ trait CaptionApp {
|
||||
|
||||
def handleSendCaptionHistoryRequest(msg: SendCaptionHistoryRequest) {
|
||||
var history = captionModel.getHistory()
|
||||
|
||||
//println("Caption history requested " + history)
|
||||
outGW.send(new SendCaptionHistoryReply(mProps.meetingID, mProps.recorded, msg.requesterID, history))
|
||||
}
|
||||
|
||||
@ -24,17 +24,17 @@ trait CaptionApp {
|
||||
captionModel.changeTranscriptOwner(t, "")
|
||||
|
||||
// send notification that owner has changed
|
||||
outGW.send(new UpdateCaptionOwnerReply(mProps.meetingID, mProps.recorded, t, ""))
|
||||
outGW.send(new UpdateCaptionOwnerReply(mProps.meetingID, mProps.recorded, t, captionModel.findLocaleCodeByLocale(t), ""))
|
||||
})
|
||||
}
|
||||
// create the locale if it doesn't exist
|
||||
if (captionModel.transcripts contains msg.locale) {
|
||||
captionModel.changeTranscriptOwner(msg.locale, msg.ownerID)
|
||||
} else { // change the owner if it does exist
|
||||
captionModel.newTranscript(msg.locale, msg.ownerID)
|
||||
captionModel.newTranscript(msg.locale, msg.localeCode, msg.ownerID)
|
||||
}
|
||||
|
||||
outGW.send(new UpdateCaptionOwnerReply(mProps.meetingID, mProps.recorded, msg.locale, msg.ownerID))
|
||||
outGW.send(new UpdateCaptionOwnerReply(mProps.meetingID, mProps.recorded, msg.locale, msg.localeCode, msg.ownerID))
|
||||
}
|
||||
|
||||
def handleEditCaptionHistoryRequest(msg: EditCaptionHistoryRequest) {
|
||||
@ -42,7 +42,7 @@ trait CaptionApp {
|
||||
if (t == msg.locale) {
|
||||
captionModel.editHistory(msg.startIndex, msg.endIndex, msg.locale, msg.text)
|
||||
|
||||
outGW.send(new EditCaptionHistoryReply(mProps.meetingID, mProps.recorded, msg.userID, msg.startIndex, msg.endIndex, msg.locale, msg.text))
|
||||
outGW.send(new EditCaptionHistoryReply(mProps.meetingID, mProps.recorded, msg.userID, msg.startIndex, msg.endIndex, msg.locale, msg.localeCode, msg.text))
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -52,7 +52,7 @@ trait CaptionApp {
|
||||
captionModel.changeTranscriptOwner(t, "")
|
||||
|
||||
// send notification that owner has changed
|
||||
outGW.send(new UpdateCaptionOwnerReply(mProps.meetingID, mProps.recorded, t, ""))
|
||||
outGW.send(new UpdateCaptionOwnerReply(mProps.meetingID, mProps.recorded, t, captionModel.findLocaleCodeByLocale(t), ""))
|
||||
})
|
||||
}
|
||||
}
|
@ -6,8 +6,8 @@ import scala.collection.immutable.HashMap
|
||||
class CaptionModel {
|
||||
var transcripts = Map[String, Array[String]]()
|
||||
|
||||
def newTranscript(locale: String, ownerId: String) {
|
||||
transcripts += locale -> Array(ownerId, "")
|
||||
def newTranscript(locale: String, localeCode: String, ownerId: String) {
|
||||
transcripts += locale -> Array(ownerId, "", localeCode)
|
||||
}
|
||||
|
||||
def findLocaleByOwnerId(userId: String): Option[String] = {
|
||||
@ -18,6 +18,14 @@ class CaptionModel {
|
||||
return None
|
||||
}
|
||||
|
||||
def findLocaleCodeByLocale(locale: String): String = {
|
||||
if (transcripts contains locale) {
|
||||
return transcripts(locale)(2)
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
def changeTranscriptOwner(locale: String, ownerId: String) {
|
||||
if (transcripts contains locale) {
|
||||
transcripts(locale)(0) = ownerId
|
||||
@ -28,25 +36,25 @@ class CaptionModel {
|
||||
var history = Map[String, Array[String]]()
|
||||
|
||||
transcripts.foreach(t => {
|
||||
history += t._1 -> Array(t._2(0), t._2(1))
|
||||
history += t._1 -> Array(t._2(0), t._2(1), t._2(2))
|
||||
})
|
||||
|
||||
history
|
||||
}
|
||||
|
||||
def editHistory(startIndex: Integer, endIndex: Integer, locale: String, text: String) {
|
||||
println("editHistory entered")
|
||||
//println("editHistory entered")
|
||||
if (transcripts contains locale) {
|
||||
println("editHistory found locale:" + locale)
|
||||
//println("editHistory found locale:" + locale)
|
||||
var oText: String = transcripts(locale)(1)
|
||||
|
||||
if (startIndex >= 0 && endIndex <= oText.length && startIndex <= endIndex) {
|
||||
println("editHistory passed index test")
|
||||
//println("editHistory passed index test")
|
||||
var sText: String = oText.substring(0, startIndex)
|
||||
var eText: String = oText.substring(endIndex)
|
||||
|
||||
transcripts(locale)(1) = (sText + text + eText)
|
||||
println("editHistory new history is: " + transcripts(locale)(1))
|
||||
//println("editHistory new history is: " + transcripts(locale)(1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,16 +94,10 @@ trait PresentationApp {
|
||||
}
|
||||
|
||||
def handleGotoSlide(msg: GotoSlide) {
|
||||
// println("Received GotoSlide for meeting=[" + msg.meetingID + "] page=[" + msg.page + "]")
|
||||
// println("*** Before change page ****")
|
||||
// printPresentations
|
||||
presModel.changePage(msg.page) foreach { page =>
|
||||
// println("Switching page for meeting=[" + msg.meetingID + "] page=[" + page.id + "]")
|
||||
log.debug("Switching page for meeting=[{}] page=[{}]", msg.meetingID, page.num);
|
||||
outGW.send(new GotoSlideOutMsg(mProps.meetingID, mProps.recorded, page))
|
||||
|
||||
}
|
||||
// println("*** After change page ****")
|
||||
// printPresentations
|
||||
|
||||
usersModel.getCurrentPresenter() foreach { pres =>
|
||||
handleStopPollRequest(StopPollRequest(mProps.meetingID, pres.userID))
|
||||
|
@ -23,6 +23,7 @@ object CaptionMessageToJsonConverter {
|
||||
val payload = new java.util.HashMap[String, Any]()
|
||||
payload.put(Constants.MEETING_ID, msg.meetingID)
|
||||
payload.put(Constants.LOCALE, msg.locale)
|
||||
payload.put(Constants.LOCALE_CODE, msg.localeCode)
|
||||
payload.put(Constants.OWNER_ID, msg.ownerID)
|
||||
|
||||
val header = Util.buildHeader(MessageNames.UPDATE_CAPTION_OWNER, None)
|
||||
@ -36,6 +37,7 @@ object CaptionMessageToJsonConverter {
|
||||
payload.put(Constants.START_INDEX, msg.startIndex)
|
||||
payload.put(Constants.END_INDEX, msg.endIndex)
|
||||
payload.put(Constants.LOCALE, msg.locale)
|
||||
payload.put(Constants.LOCALE_CODE, msg.localeCode)
|
||||
payload.put(Constants.TEXT, msg.text)
|
||||
|
||||
val header = Util.buildHeader(MessageNames.EDIT_CAPTION_HISTORY, None)
|
||||
|
@ -29,7 +29,7 @@ import org.bigbluebutton.freeswitch.voice.freeswitch.actions.EjectUserCommand;
|
||||
import org.bigbluebutton.freeswitch.voice.freeswitch.actions.GetAllUsersCommand;
|
||||
import org.bigbluebutton.freeswitch.voice.freeswitch.actions.MuteUserCommand;
|
||||
import org.bigbluebutton.freeswitch.voice.freeswitch.actions.RecordConferenceCommand;
|
||||
import org.bigbluebutton.freeswitch.voice.freeswitch.actions.TransferUsetToMeetingCommand;
|
||||
import org.bigbluebutton.freeswitch.voice.freeswitch.actions.TransferUserToMeetingCommand;
|
||||
import org.bigbluebutton.freeswitch.voice.freeswitch.actions.*;
|
||||
import org.freeswitch.esl.client.inbound.Client;
|
||||
import org.freeswitch.esl.client.inbound.InboundConnectionFailure;
|
||||
@ -128,7 +128,7 @@ public class ConnectionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void tranfer(TransferUsetToMeetingCommand tutmc) {
|
||||
public void tranfer(TransferUserToMeetingCommand tutmc) {
|
||||
Client c = manager.getESLClient();
|
||||
if (c.canSend()) {
|
||||
c.sendAsyncApiCommand(tutmc.getCommand(), tutmc.getCommandArgs());
|
||||
|
@ -31,7 +31,7 @@ import org.bigbluebutton.freeswitch.voice.freeswitch.actions.FreeswitchCommand;
|
||||
import org.bigbluebutton.freeswitch.voice.freeswitch.actions.GetAllUsersCommand;
|
||||
import org.bigbluebutton.freeswitch.voice.freeswitch.actions.MuteUserCommand;
|
||||
import org.bigbluebutton.freeswitch.voice.freeswitch.actions.RecordConferenceCommand;
|
||||
import org.bigbluebutton.freeswitch.voice.freeswitch.actions.TransferUsetToMeetingCommand;
|
||||
import org.bigbluebutton.freeswitch.voice.freeswitch.actions.TransferUserToMeetingCommand;
|
||||
import org.bigbluebutton.freeswitch.voice.freeswitch.actions.*;
|
||||
|
||||
public class FreeswitchApplication {
|
||||
@ -48,9 +48,12 @@ public class FreeswitchApplication {
|
||||
private final String USER = "0"; /* not used for now */
|
||||
|
||||
private volatile boolean sendMessages = false;
|
||||
|
||||
private final String audioProfile;
|
||||
|
||||
public FreeswitchApplication(ConnectionManager manager) {
|
||||
public FreeswitchApplication(ConnectionManager manager, String profile) {
|
||||
this.manager = manager;
|
||||
this.audioProfile = profile;
|
||||
}
|
||||
|
||||
private void queueMessage(FreeswitchCommand command) {
|
||||
@ -62,12 +65,13 @@ public class FreeswitchApplication {
|
||||
}
|
||||
}
|
||||
|
||||
public void transferUserToMeeting(String voiceConfId,
|
||||
String targetVoiceConfId, String voiceUserId) {
|
||||
TransferUsetToMeetingCommand tutmc = new TransferUsetToMeetingCommand(
|
||||
voiceConfId, targetVoiceConfId, voiceUserId, USER);
|
||||
queueMessage(tutmc);
|
||||
}
|
||||
public void transferUserToMeeting(String voiceConfId,
|
||||
String targetVoiceConfId, String voiceUserId) {
|
||||
TransferUserToMeetingCommand tutmc = new TransferUserToMeetingCommand(
|
||||
voiceConfId, targetVoiceConfId, voiceUserId, this.audioProfile,
|
||||
USER);
|
||||
queueMessage(tutmc);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
sendMessages = true;
|
||||
@ -153,8 +157,8 @@ public class FreeswitchApplication {
|
||||
EjectAllUsersCommand cmd = (EjectAllUsersCommand) command;
|
||||
System.out.println("Sending EjectAllUsersCommand for conference = [" + cmd.getRoom() + "]");
|
||||
manager.ejectAll(cmd);
|
||||
} else if (command instanceof TransferUsetToMeetingCommand) {
|
||||
TransferUsetToMeetingCommand cmd = (TransferUsetToMeetingCommand) command;
|
||||
} else if (command instanceof TransferUserToMeetingCommand) {
|
||||
TransferUserToMeetingCommand cmd = (TransferUserToMeetingCommand) command;
|
||||
System.out.println("Sending TransferUsetToMeetingCommand for conference = ["
|
||||
+ cmd.getRoom() + "]");
|
||||
manager.tranfer(cmd);
|
||||
|
@ -19,21 +19,23 @@
|
||||
|
||||
package org.bigbluebutton.freeswitch.voice.freeswitch.actions;
|
||||
|
||||
public class TransferUsetToMeetingCommand extends FreeswitchCommand {
|
||||
public class TransferUserToMeetingCommand extends FreeswitchCommand {
|
||||
|
||||
private final String targetRoom;
|
||||
private final String participant;
|
||||
private final String targetRoom;
|
||||
private final String participant;
|
||||
private final String audioProfile;
|
||||
|
||||
public TransferUsetToMeetingCommand(String room, String targetRoom,
|
||||
String participant, String requesterId) {
|
||||
super(room, requesterId);
|
||||
this.targetRoom = targetRoom;
|
||||
this.participant = participant;
|
||||
}
|
||||
public TransferUserToMeetingCommand(String room, String targetRoom,
|
||||
String participant, String profile, String requesterId) {
|
||||
super(room, requesterId);
|
||||
this.targetRoom = targetRoom;
|
||||
this.participant = participant;
|
||||
this.audioProfile = profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandArgs() {
|
||||
return room + SPACE + "transfer" + SPACE + targetRoom + SPACE
|
||||
+ participant;
|
||||
}
|
||||
@Override
|
||||
public String getCommandArgs() {
|
||||
return room + SPACE + "transfer" + SPACE + targetRoom + "@"
|
||||
+ this.audioProfile + SPACE + participant;
|
||||
}
|
||||
}
|
@ -24,6 +24,9 @@ freeswitch {
|
||||
port=8021
|
||||
password="ClueCon"
|
||||
}
|
||||
conf {
|
||||
profile="cdquality"
|
||||
}
|
||||
}
|
||||
|
||||
redis {
|
||||
|
@ -31,7 +31,7 @@ object Boot extends App with SystemConfiguration {
|
||||
|
||||
connManager.start()
|
||||
|
||||
val fsApplication = new FreeswitchApplication(connManager)
|
||||
val fsApplication = new FreeswitchApplication(connManager, fsProfile)
|
||||
fsApplication.start()
|
||||
|
||||
val redisMsgReceiver = new RedisMessageReceiver(fsApplication)
|
||||
|
@ -10,6 +10,7 @@ trait SystemConfiguration {
|
||||
lazy val eslHost = Try(config.getString("freeswitch.esl.host")).getOrElse("127.0.0.1")
|
||||
lazy val eslPort = Try(config.getInt("freeswitch.esl.port")).getOrElse(8021)
|
||||
lazy val eslPassword = Try(config.getString("freeswitch.esl.password")).getOrElse("ClueCon")
|
||||
lazy val fsProfile = Try(config.getString("freeswitch.conf.profile")).getOrElse("cdquality")
|
||||
|
||||
lazy val redisHost = Try(config.getString("redis.host")).getOrElse("127.0.0.1")
|
||||
lazy val redisPort = Try(config.getInt("redis.port")).getOrElse(6379)
|
||||
|
@ -128,6 +128,7 @@ public class Constants {
|
||||
public static final String START_INDEX = "start_index";
|
||||
public static final String END_INDEX = "end_index";
|
||||
public static final String LOCALE = "locale";
|
||||
public static final String LOCALE_CODE = "locale_code";
|
||||
public static final String TEXT = "text";
|
||||
public static final String OWNER_ID = "owner_id";
|
||||
public static final String CAPTION_HISTORY = "caption_history";
|
||||
|
@ -14,14 +14,16 @@ public class EditCaptionHistoryMessage implements ISubscribedMessage {
|
||||
public final Integer startIndex;
|
||||
public final Integer endIndex;
|
||||
public final String locale;
|
||||
public final String localeCode;
|
||||
public final String text;
|
||||
|
||||
public EditCaptionHistoryMessage(String meetingID, String userID, Integer startIndex, Integer endIndex, String locale, String text) {
|
||||
public EditCaptionHistoryMessage(String meetingID, String userID, Integer startIndex, Integer endIndex, String locale, String localeCode, String text) {
|
||||
this.meetingID = meetingID;
|
||||
this.userID = userID;
|
||||
this.startIndex = startIndex;
|
||||
this.endIndex = endIndex;
|
||||
this.locale = locale;
|
||||
this.localeCode = localeCode;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@ -32,6 +34,7 @@ public class EditCaptionHistoryMessage implements ISubscribedMessage {
|
||||
payload.put(Constants.START_INDEX, startIndex);
|
||||
payload.put(Constants.END_INDEX, endIndex);
|
||||
payload.put(Constants.LOCALE, locale);
|
||||
payload.put(Constants.LOCALE_CODE, localeCode);
|
||||
payload.put(Constants.TEXT, text);
|
||||
|
||||
java.util.HashMap<String, Object> header = MessageBuilder.buildHeader(EDIT_CAPTION_HISTORY, VERSION, null);
|
||||
@ -55,15 +58,17 @@ public class EditCaptionHistoryMessage implements ISubscribedMessage {
|
||||
&& payload.has(Constants.START_INDEX)
|
||||
&& payload.has(Constants.END_INDEX)
|
||||
&& payload.has(Constants.LOCALE)
|
||||
&& payload.has(Constants.LOCALE_CODE)
|
||||
&& payload.has(Constants.TEXT)) {
|
||||
String meetingID = payload.get(Constants.MEETING_ID).getAsString();
|
||||
String userID = payload.get(Constants.USER_ID).getAsString();
|
||||
Integer startIndex = payload.get(Constants.START_INDEX).getAsInt();
|
||||
Integer endIndex = payload.get(Constants.END_INDEX).getAsInt();
|
||||
String locale = payload.get(Constants.LOCALE).getAsString();
|
||||
String localeCode = payload.get(Constants.LOCALE_CODE).getAsString();
|
||||
String text = payload.get(Constants.TEXT).getAsString();
|
||||
|
||||
return new EditCaptionHistoryMessage(meetingID, userID, startIndex, endIndex, locale, text);
|
||||
return new EditCaptionHistoryMessage(meetingID, userID, startIndex, endIndex, locale, localeCode, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ public class SendCaptionHistoryReplyMessage implements ISubscribedMessage {
|
||||
HashMap<String, Object> payload = new HashMap<String, Object>();
|
||||
payload.put(Constants.MEETING_ID, meetingID);
|
||||
payload.put(Constants.REQUESTER_ID, requesterID);
|
||||
payload.put(Constants.CHAT_HISTORY, captionHistory);
|
||||
payload.put(Constants.CAPTION_HISTORY, captionHistory);
|
||||
|
||||
java.util.HashMap<String, Object> header = MessageBuilder.buildHeader(SEND_CAPTION_HISTORY_REPLY, VERSION, null);
|
||||
return MessageBuilder.buildJson(header, payload);
|
||||
|
@ -11,11 +11,13 @@ public class UpdateCaptionOwnerMessage implements ISubscribedMessage {
|
||||
|
||||
public final String meetingID;
|
||||
public final String locale;
|
||||
public final String localeCode;
|
||||
public final String ownerID;
|
||||
|
||||
public UpdateCaptionOwnerMessage(String meetingID, String locale, String ownerID) {
|
||||
public UpdateCaptionOwnerMessage(String meetingID, String locale, String localeCode, String ownerID) {
|
||||
this.meetingID = meetingID;
|
||||
this.locale = locale;
|
||||
this.localeCode = localeCode;
|
||||
this.ownerID = ownerID;
|
||||
}
|
||||
|
||||
@ -23,6 +25,7 @@ public class UpdateCaptionOwnerMessage implements ISubscribedMessage {
|
||||
HashMap<String, Object> payload = new HashMap<String, Object>();
|
||||
payload.put(Constants.MEETING_ID, meetingID);
|
||||
payload.put(Constants.LOCALE, locale);
|
||||
payload.put(Constants.LOCALE_CODE, localeCode);
|
||||
payload.put(Constants.OWNER_ID, ownerID);
|
||||
|
||||
java.util.HashMap<String, Object> header = MessageBuilder.buildHeader(UPDATE_CAPTION_OWNER, VERSION, null);
|
||||
@ -43,12 +46,14 @@ public class UpdateCaptionOwnerMessage implements ISubscribedMessage {
|
||||
if (UPDATE_CAPTION_OWNER.equals(messageName)) {
|
||||
if (payload.has(Constants.MEETING_ID)
|
||||
&& payload.has(Constants.LOCALE)
|
||||
&& payload.has(Constants.LOCALE_CODE)
|
||||
&& payload.has(Constants.OWNER_ID)) {
|
||||
String meetingID = payload.get(Constants.MEETING_ID).getAsString();
|
||||
String locale = payload.get(Constants.LOCALE).getAsString();
|
||||
String localeCode = payload.get(Constants.LOCALE_CODE). getAsString();
|
||||
String ownerID = payload.get(Constants.OWNER_ID).getAsString();
|
||||
|
||||
return new UpdateCaptionOwnerMessage(meetingID, locale, ownerID);
|
||||
return new UpdateCaptionOwnerMessage(meetingID, locale, localeCode, ownerID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -724,7 +724,7 @@ public class Util {
|
||||
for (Map.Entry<String,JsonElement> entry : history.entrySet()) {
|
||||
String locale = entry.getKey();
|
||||
JsonArray values = entry.getValue().getAsJsonArray();
|
||||
String[] localeValueArray = new String[2];
|
||||
String[] localeValueArray = new String[3];
|
||||
|
||||
int i = 0;
|
||||
Iterator<JsonElement> valuesIter = values.iterator();
|
||||
|
@ -1,27 +1,31 @@
|
||||
package org.bigbluebutton.messages.payload;
|
||||
|
||||
public class CreateBreakoutRoomRequestPayload {
|
||||
public final String breakoutId;
|
||||
public final String parentId; // The main meeting internal id
|
||||
public final String name; // The name of the breakout room
|
||||
public final String voiceConfId; // The voice conference id
|
||||
public final String viewerPassword;
|
||||
public final String moderatorPassword;
|
||||
public final Integer durationInMinutes; // The duration of the breakout room
|
||||
public final String defaultPresentationURL;
|
||||
public final Boolean record;
|
||||
|
||||
public CreateBreakoutRoomRequestPayload(String breakoutId, String parentId, String name,
|
||||
String voiceConfId, String viewerPassword, String moderatorPassword,
|
||||
Integer duration, String defaultPresentationURL, Boolean record) {
|
||||
this.breakoutId = breakoutId;
|
||||
this.parentId = parentId;
|
||||
this.name = name;
|
||||
this.voiceConfId = voiceConfId;
|
||||
this.viewerPassword = viewerPassword;
|
||||
this.moderatorPassword = moderatorPassword;
|
||||
this.durationInMinutes = duration;
|
||||
this.defaultPresentationURL = defaultPresentationURL;
|
||||
this.record = record;
|
||||
}
|
||||
public final String breakoutId;
|
||||
public final String parentId; // The main meeting internal id
|
||||
public final String name; // The name of the breakout room
|
||||
public final String voiceConfId; // The voice conference id
|
||||
public final String viewerPassword;
|
||||
public final String moderatorPassword;
|
||||
public final Integer durationInMinutes; // The duration of the breakout room
|
||||
public final String sourcePresentationId;
|
||||
public final Integer sourcePresentationSlide;
|
||||
public final Boolean record;
|
||||
|
||||
public CreateBreakoutRoomRequestPayload(String breakoutId, String parentId,
|
||||
String name, String voiceConfId, String viewerPassword,
|
||||
String moderatorPassword, Integer duration,
|
||||
String sourcePresentationId, Integer sourcePresentationSlide,
|
||||
Boolean record) {
|
||||
this.breakoutId = breakoutId;
|
||||
this.parentId = parentId;
|
||||
this.name = name;
|
||||
this.voiceConfId = voiceConfId;
|
||||
this.viewerPassword = viewerPassword;
|
||||
this.moderatorPassword = moderatorPassword;
|
||||
this.durationInMinutes = duration;
|
||||
this.sourcePresentationId = sourcePresentationId;
|
||||
this.sourcePresentationSlide = sourcePresentationSlide;
|
||||
this.record = record;
|
||||
}
|
||||
}
|
||||
|
@ -9,19 +9,20 @@ import com.google.gson.Gson;
|
||||
public class CreateBreakoutRoomRequestTest {
|
||||
@Test
|
||||
public void testCreateBreakoutRoomRequest() {
|
||||
String breakoutId = "abc123";
|
||||
String breakoutId = "183f0bf3a0982a127bdb8161e0c44eb696b3e75c-1474984695664";
|
||||
String parentId = "abc-123";
|
||||
Integer durationInMinutes = 20;
|
||||
String name = "Breakout room 1";
|
||||
String voiceConfId = "851153";
|
||||
String viewerPassword = "vp";
|
||||
String moderatorPassword = "mp";
|
||||
String defaultPresentationURL = "http://localhost/foo.pdf";
|
||||
String sourcePresentationId = "d2d9a672040fbde2a47a10bf6c37b6a4b5ae187f-1474984695907";
|
||||
Integer sourePresentationSlide = 5;
|
||||
Boolean record = false;
|
||||
|
||||
CreateBreakoutRoomRequestPayload payload =
|
||||
new CreateBreakoutRoomRequestPayload(breakoutId, parentId, name, voiceConfId,
|
||||
viewerPassword, moderatorPassword, durationInMinutes, defaultPresentationURL, record);
|
||||
viewerPassword, moderatorPassword, durationInMinutes, sourcePresentationId, sourePresentationSlide, record);
|
||||
CreateBreakoutRoomRequest msg = new CreateBreakoutRoomRequest(payload);
|
||||
Gson gson = new Gson();
|
||||
String json = gson.toJson(msg);
|
||||
@ -36,7 +37,8 @@ public class CreateBreakoutRoomRequestTest {
|
||||
Assert.assertEquals(rxMsg.payload.viewerPassword, viewerPassword);
|
||||
Assert.assertEquals(rxMsg.payload.moderatorPassword, moderatorPassword);
|
||||
Assert.assertEquals(rxMsg.payload.durationInMinutes, durationInMinutes);
|
||||
Assert.assertEquals(rxMsg.payload.defaultPresentationURL, defaultPresentationURL);
|
||||
Assert.assertEquals(rxMsg.payload.sourcePresentationId, sourcePresentationId);
|
||||
Assert.assertEquals(rxMsg.payload.sourcePresentationSlide, sourePresentationSlide);
|
||||
Assert.assertEquals(rxMsg.payload.record, record);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
<title><g:message code="tool.view.title" /></title>
|
||||
<link rel="shortcut icon" href="${assetPath(src: 'favicon.ico')}" type="image/x-icon">
|
||||
<asset:stylesheet src="bootstrap.css"/>
|
||||
<asset:stylesheet src="tool.css"/>
|
||||
<asset:stylesheet src="dataTables.bootstrap.min.css"/>
|
||||
<asset:javascript src="jquery.js"/>
|
||||
<asset:javascript src="jquery.dataTables.min.js"/>
|
||||
|
@ -4,7 +4,7 @@
|
||||
proxy_pass http://127.0.0.1:8080;
|
||||
proxy_redirect default;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# Allow 30M uploaded presentation document.
|
||||
client_max_body_size 30m;
|
||||
|
@ -119,7 +119,7 @@ class Screenshare(val sessionManager: ScreenshareManager,
|
||||
private var lastJwsStatusUpdate = 0L
|
||||
|
||||
private var sessionStartedTimestamp:Long = 0L
|
||||
private val JWS_START_TIMEOUT = 60
|
||||
private val JWS_START_TIMEOUT = 90
|
||||
|
||||
// The number of seconds we wait for the JWS to launch when
|
||||
// resuming sharing. Sometimes, on PAUSE, the JWS crashes but
|
||||
|
@ -1,8 +1,18 @@
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-linux-x86.jar
|
||||
cp $FFMPEG build/libs/ffmpeg-linux-x86-0.0.1.jar
|
||||
mkdir workdir
|
||||
cp $FFMPEG workdir/ffmpeg-linux-x86.jar
|
||||
rm -rf src
|
||||
rm -rf workdir
|
||||
mkdir -p src/main/resources
|
||||
mkdir -p src/main/java
|
||||
cd workdir
|
||||
jar xvf ffmpeg-linux-x86.jar
|
||||
cp org/bytedeco/javacpp/linux-x86/*.so* ../src/main/resources
|
||||
cd ..
|
||||
gradle jar
|
||||
cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../unsigned-jars/ffmpeg-linux-x86-unsigned.jar
|
||||
ant sign-jar
|
||||
cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../../../app/jws/lib/ffmpeg-linux-x86.jar
|
||||
rm -rf workdir
|
||||
rm -rf src
|
||||
|
||||
|
||||
|
@ -1,7 +1,17 @@
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-linux-x86_64.jar
|
||||
mkdir workdir
|
||||
rm -rf workdir
|
||||
cp $FFMPEG build/libs/ffmpeg-linux-x86_64-0.0.1.jar
|
||||
cp $FFMPEG workdir/ffmpeg-linux-x86_64.jar
|
||||
rm -rf src
|
||||
mkdir -p src/main/resources
|
||||
mkdir -p src/main/java
|
||||
cd workdir
|
||||
jar xvf ffmpeg-linux-x86_64.jar
|
||||
cp org/bytedeco/javacpp/linux-x86_64/*.so* ../src/main/resources
|
||||
cd ..
|
||||
gradle jar
|
||||
cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../unsigned-jars/ffmpeg-linux-x86_64-unsigned.jar
|
||||
ant sign-jar
|
||||
cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../../../app/jws/lib/ffmpeg-linux-x86_64.jar
|
||||
rm -rf workdir
|
||||
rm -rf src
|
||||
|
||||
|
@ -16,6 +16,7 @@ import org.bigbluebutton.screenshare.client.ExitCode;
|
||||
import org.bigbluebutton.screenshare.client.ScreenShareInfo;
|
||||
import org.bigbluebutton.screenshare.client.net.NetworkConnectionListener;
|
||||
import org.bytedeco.javacpp.Loader;
|
||||
import org.bytedeco.javacpp.avcodec;
|
||||
import org.bytedeco.javacv.FFmpegFrameGrabber;
|
||||
import org.bytedeco.javacv.FFmpegFrameRecorder;
|
||||
import org.bytedeco.javacv.Frame;
|
||||
@ -144,25 +145,27 @@ public class FfmpegScreenshare {
|
||||
frame = grabber.grabImage();
|
||||
if (frame != null) {
|
||||
try {
|
||||
long timestamp = now - startTime;
|
||||
// Override timestamp from system screen grabber. Otherwise, we will have skewed recorded file.
|
||||
// FfmpegFrameRecorder needs to propagate this timestamp into the avpacket sent to the server.
|
||||
// ralam - Sept. 14, 2016
|
||||
frame.timestamp = timestamp;
|
||||
//System.out.println("frame timestamp=[" + frame.timestamp + "] ");
|
||||
mainRecorder.record(frame);
|
||||
} catch (Exception e) {
|
||||
//System.out.println("CaptureScreen Exception 1");
|
||||
if (!ignoreDisconnect) {
|
||||
listener.networkConnectionException(ExitCode.INTERNAL_ERROR, null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} catch (Exception e1) {
|
||||
listener.networkConnectionException(ExitCode.INTERNAL_ERROR, null);
|
||||
}
|
||||
|
||||
|
||||
long sleepFramerate = (long) (1000 / frameRate);
|
||||
long timestamp = now - startTime;
|
||||
mainRecorder.setTimestamp(timestamp * 1000);
|
||||
|
||||
// System.out.println("i=[" + i + "] timestamp=[" + timestamp + "]");
|
||||
//System.out.println("timestamp=[" + timestamp + "]");
|
||||
mainRecorder.setFrameNumber(frameNumber);
|
||||
|
||||
// System.out.println("[ENCODER] encoded image " + frameNumber + " in " + (System.currentTimeMillis() - now));
|
||||
|
@ -45,7 +45,6 @@ public class NetworkHttpStreamSender {
|
||||
private String host = "localhost";
|
||||
private static final String SCREEN_CAPTURE__URL = "/tunnel/screenCapture";
|
||||
private URL url;
|
||||
private URLConnection conn;
|
||||
private String meetingId;
|
||||
private NetworkStreamListener listener;
|
||||
private final SequenceNumberGenerator seqNumGenerator;
|
||||
@ -113,7 +112,7 @@ public class NetworkHttpStreamSender {
|
||||
sendMessages = false;
|
||||
}
|
||||
|
||||
private void openConnection() throws ConnectionException {
|
||||
private URLConnection openConnection() throws ConnectionException {
|
||||
/**
|
||||
* Need to re-establish connection each time, otherwise,
|
||||
* we get java.net.ProtocolException: Cannot write output after reading input.
|
||||
@ -121,13 +120,13 @@ public class NetworkHttpStreamSender {
|
||||
* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4382944
|
||||
*
|
||||
*/
|
||||
long start = System.currentTimeMillis();
|
||||
//long start = System.currentTimeMillis();
|
||||
try {
|
||||
url = new URL(host + SCREEN_CAPTURE__URL);
|
||||
if (host.toLowerCase().startsWith("https://")) {
|
||||
conn = (HttpsURLConnection)url.openConnection();
|
||||
return (HttpsURLConnection)url.openConnection();
|
||||
} else {
|
||||
conn = url.openConnection();
|
||||
return url.openConnection();
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
@ -136,27 +135,20 @@ public class NetworkHttpStreamSender {
|
||||
e.printStackTrace();
|
||||
throw new ConnectionException("IOException while connecting to " + url.toString());
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
//long end = System.currentTimeMillis();
|
||||
//System.out.println("Http Open connection took [" + (end-start) + " ms]");
|
||||
}
|
||||
|
||||
private void sendStartStreamMessage(ShareStartedMessage message) {
|
||||
try {
|
||||
//System.out.println("Http Open connection. In sendStartStreamMessage");
|
||||
openConnection();
|
||||
sendCaptureStartEvent(message.width, message.height, message.streamId, message.session);
|
||||
} catch (ConnectionException e) {
|
||||
System.out.println("Exception in sendStartStreamMessage");
|
||||
System.out.print(e.toString());
|
||||
//e.printStackTrace();
|
||||
notifyNetworkStreamListener(ExitCode.DESKSHARE_SERVICE_UNAVAILABLE, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendCaptureStartEvent(int width, int height, String streamId, String session) throws ConnectionException {
|
||||
private void sendCaptureStartEvent(int width, int height, String streamId, String session) {
|
||||
ClientHttpRequest chr;
|
||||
try {
|
||||
System.out.println(getTimeStamp() + " - Sending Start Sharing Event.");
|
||||
URLConnection conn = openConnection();
|
||||
chr = new ClientHttpRequest(conn);
|
||||
chr.setParameter(MEETING_ID, meetingId);
|
||||
chr.setParameter(STREAM_ID, streamId);
|
||||
@ -173,28 +165,23 @@ public class NetworkHttpStreamSender {
|
||||
//System.out.println("******* sendCaptureStartEvent response code = [" + status + "] ***************");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new ConnectionException("IOException while sending capture start event.");
|
||||
notifyNetworkStreamListener(ExitCode.DESKSHARE_SERVICE_UNAVAILABLE, null);
|
||||
} catch (ConnectionException e) {
|
||||
e.printStackTrace();
|
||||
notifyNetworkStreamListener(ExitCode.DESKSHARE_SERVICE_UNAVAILABLE, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnect(String streamId, String session) throws ConnectionException {
|
||||
try {
|
||||
System.out.println("Http Open connection. In disconnect");
|
||||
openConnection();
|
||||
sendCaptureEndEvent(new ShareStoppedMessage(meetingId, streamId, session));
|
||||
} catch (ConnectionException e) {
|
||||
e.printStackTrace();
|
||||
notifyNetworkStreamListener(ExitCode.DESKSHARE_SERVICE_UNAVAILABLE, null);
|
||||
throw e;
|
||||
} finally {
|
||||
|
||||
}
|
||||
System.out.println("Http Open connection. In disconnect");
|
||||
sendCaptureEndEvent(new ShareStoppedMessage(meetingId, streamId, session));
|
||||
}
|
||||
|
||||
private void sendCaptureEndEvent(ShareStoppedMessage message) {
|
||||
ClientHttpRequest chr;
|
||||
try {
|
||||
//System.out.println(getTimeStamp() + " - Sending End Sharing Event.");
|
||||
URLConnection conn = openConnection();
|
||||
chr = new ClientHttpRequest(conn);
|
||||
chr.setParameter(MEETING_ID, meetingId);
|
||||
chr.setParameter(STREAM_ID, message.streamId);
|
||||
@ -210,6 +197,10 @@ public class NetworkHttpStreamSender {
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
notifyNetworkStreamListener(ExitCode.DESKSHARE_SERVICE_UNAVAILABLE, null);
|
||||
} catch (ConnectionException e) {
|
||||
e.printStackTrace();
|
||||
notifyNetworkStreamListener(ExitCode.DESKSHARE_SERVICE_UNAVAILABLE, null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,7 +211,7 @@ public class NetworkHttpStreamSender {
|
||||
// Open a connection to the web server and create a request that has
|
||||
// the room and event type.
|
||||
// System.out.println(getTimeStamp() + " - Sending Update Sharing Event.");
|
||||
openConnection();
|
||||
URLConnection conn = openConnection();
|
||||
chr = new ClientHttpRequest(conn);
|
||||
chr.setParameter(MEETING_ID, meetingId);
|
||||
chr.setParameter(STREAM_ID, message.streamId);
|
||||
|
@ -688,7 +688,7 @@ public class FFmpegFrameRecorder extends FrameRecorder {
|
||||
if (oc != null) {
|
||||
try {
|
||||
/* flush all the buffers */
|
||||
while (video_st != null && ifmt_ctx == null && recordImage(0, 0, 0, 0, 0, AV_PIX_FMT_NONE, (Buffer[])null));
|
||||
while (video_st != null && ifmt_ctx == null && recordImage(0, 0, 0, 0, 0, AV_PIX_FMT_NONE, 0, (Buffer[])null));
|
||||
while (audio_st != null && ifmt_ctx == null && recordSamples(0, 0, (Buffer[])null));
|
||||
|
||||
if (interleaved && video_st != null && audio_st != null) {
|
||||
@ -710,11 +710,11 @@ public class FFmpegFrameRecorder extends FrameRecorder {
|
||||
}
|
||||
public void record(Frame frame, int pixelFormat) throws Exception {
|
||||
if (frame == null || (frame.image == null && frame.samples == null)) {
|
||||
recordImage(0, 0, 0, 0, 0, pixelFormat, (Buffer[])null);
|
||||
recordImage(0, 0, 0, 0, 0, pixelFormat, frame.timestamp, (Buffer[])null);
|
||||
} else {
|
||||
if (frame.image != null) {
|
||||
frame.keyFrame = recordImage(frame.imageWidth, frame.imageHeight, frame.imageDepth,
|
||||
frame.imageChannels, frame.imageStride, pixelFormat, frame.image);
|
||||
frame.imageChannels, frame.imageStride, pixelFormat, frame.timestamp, frame.image);
|
||||
}
|
||||
if (frame.samples != null) {
|
||||
frame.keyFrame = recordSamples(frame.sampleRate, frame.audioChannels, frame.samples);
|
||||
@ -722,7 +722,8 @@ public class FFmpegFrameRecorder extends FrameRecorder {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean recordImage(int width, int height, int depth, int channels, int stride, int pixelFormat, Buffer ... image) throws Exception {
|
||||
public boolean recordImage(int width, int height, int depth, int channels, int stride,
|
||||
int pixelFormat, long frameTimestamp, Buffer ... image) throws Exception {
|
||||
if (video_st == null) {
|
||||
throw new Exception("No video output stream (Is imageWidth > 0 && imageHeight > 0 and has start() been called?)");
|
||||
}
|
||||
@ -808,10 +809,15 @@ public class FFmpegFrameRecorder extends FrameRecorder {
|
||||
/* if zero size, it means the image was buffered */
|
||||
if (got_video_packet[0] != 0) {
|
||||
if (video_pkt.pts() != AV_NOPTS_VALUE) {
|
||||
video_pkt.pts(av_rescale_q(video_pkt.pts(), video_c.time_base(), video_st.time_base()));
|
||||
// Override timestamp from system screen grabber. Otherwise, we will have skewed recorded file.
|
||||
// FfmpegFrameRecorder needs to propagate this timestamp into the avpacket sent to the server.
|
||||
// ralam - Sept. 14, 2016
|
||||
video_pkt.pts(frameTimestamp);
|
||||
//video_pkt.pts(av_rescale_q(video_pkt.pts(), video_c.time_base(), video_st.time_base()));
|
||||
}
|
||||
if (video_pkt.dts() != AV_NOPTS_VALUE) {
|
||||
video_pkt.dts(av_rescale_q(video_pkt.dts(), video_c.time_base(), video_st.time_base()));
|
||||
video_pkt.dts(frameTimestamp);
|
||||
//video_pkt.dts(av_rescale_q(video_pkt.dts(), video_c.time_base(), video_st.time_base()));
|
||||
}
|
||||
video_pkt.stream_index(video_st.index());
|
||||
} else {
|
||||
|
@ -40,14 +40,14 @@ public class CaptionClientMessageSender {
|
||||
processSendCaptionHistoryReplyMessage(sch);
|
||||
}
|
||||
break;
|
||||
case UpdateCaptionOwnerMessage.UPDATE_CAPTION_OWNER:
|
||||
case UpdateCaptionOwnerMessage.UPDATE_CAPTION_OWNER:
|
||||
UpdateCaptionOwnerMessage uco = UpdateCaptionOwnerMessage.fromJson(message);
|
||||
|
||||
if (uco != null) {
|
||||
processUpdateCaptionOwnerMessage(uco);
|
||||
}
|
||||
break;
|
||||
case EditCaptionHistoryMessage.EDIT_CAPTION_HISTORY:
|
||||
case EditCaptionHistoryMessage.EDIT_CAPTION_HISTORY:
|
||||
EditCaptionHistoryMessage ech = EditCaptionHistoryMessage.fromJson(message);
|
||||
|
||||
if (ech != null) {
|
||||
@ -71,6 +71,7 @@ public class CaptionClientMessageSender {
|
||||
private void processUpdateCaptionOwnerMessage(UpdateCaptionOwnerMessage msg) {
|
||||
Map<String, Object> message = new HashMap<String, Object>();
|
||||
message.put(Constants.LOCALE, msg.locale);
|
||||
message.put(Constants.LOCALE_CODE, msg.localeCode);
|
||||
message.put(Constants.OWNER_ID, msg.ownerID);
|
||||
|
||||
BroadcastClientMessage m = new BroadcastClientMessage(msg.meetingID, "updateCaptionOwner", message);
|
||||
@ -82,6 +83,7 @@ public class CaptionClientMessageSender {
|
||||
message.put(Constants.START_INDEX, msg.startIndex);
|
||||
message.put(Constants.END_INDEX, msg.endIndex);
|
||||
message.put(Constants.LOCALE, msg.locale);
|
||||
message.put(Constants.LOCALE_CODE, msg.localeCode);
|
||||
message.put(Constants.TEXT, msg.text);
|
||||
|
||||
BroadcastClientMessage m = new BroadcastClientMessage(msg.meetingID, "editCaptionHistory", message);
|
||||
|
@ -298,14 +298,14 @@ public class MessagePublisher {
|
||||
SendCaptionHistoryRequestMessage msg = new SendCaptionHistoryRequestMessage(meetingID, requesterID);
|
||||
sender.send(MessagingConstants.TO_CAPTION_CHANNEL, msg.toJson());
|
||||
}
|
||||
|
||||
public void updateCaptionOwner(String meetingID, String locale, String ownerID) {
|
||||
UpdateCaptionOwnerMessage msg = new UpdateCaptionOwnerMessage(meetingID, locale, ownerID);
|
||||
sender.send(MessagingConstants.TO_CAPTION_CHANNEL, msg.toJson());
|
||||
}
|
||||
|
||||
public void editCaptionHistory(String meetingID, String userID, Integer startIndex, Integer endIndex, String locale, String text) {
|
||||
EditCaptionHistoryMessage msg = new EditCaptionHistoryMessage(meetingID, userID, startIndex, endIndex, locale, text);
|
||||
public void updateCaptionOwner(String meetingID, String locale, String localeCode, String ownerID) {
|
||||
UpdateCaptionOwnerMessage msg = new UpdateCaptionOwnerMessage(meetingID, locale, localeCode, ownerID);
|
||||
sender.send(MessagingConstants.TO_CAPTION_CHANNEL, msg.toJson());
|
||||
}
|
||||
|
||||
public void editCaptionHistory(String meetingID, String userID, Integer startIndex, Integer endIndex, String locale, String localeCode, String text) {
|
||||
EditCaptionHistoryMessage msg = new EditCaptionHistoryMessage(meetingID, userID, startIndex, endIndex, locale, localeCode, text);
|
||||
sender.send(MessagingConstants.TO_CAPTION_CHANNEL, msg.toJson());
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import org.bigbluebutton.red5.pubsub.MessagePublisher;
|
||||
import org.red5.logging.Red5LoggerFactory;
|
||||
import org.red5.server.api.Red5;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
|
||||
public class CaptionService {
|
||||
private static Logger log = Red5LoggerFactory.getLogger( CaptionService.class, "bigbluebutton" );
|
||||
|
||||
@ -46,26 +46,42 @@ public class CaptionService {
|
||||
|
||||
red5InGW.sendCaptionHistory(meetingID, requesterID);
|
||||
}
|
||||
|
||||
public void sendUpdateCaptionOwner(Map<String, Object> msg) {
|
||||
String locale = msg.get("locale").toString();
|
||||
Boolean claim = (Boolean) msg.get("claim");
|
||||
|
||||
String meetingID = Red5.getConnectionLocal().getScope().getName();
|
||||
|
||||
public void sendUpdateCaptionOwner(Map<String, Object> msg) {
|
||||
String locale = msg.get("locale").toString();
|
||||
String localeCode = msg.get("localeCode").toString();
|
||||
Boolean claim = (Boolean) msg.get("claim");
|
||||
|
||||
String meetingID = Red5.getConnectionLocal().getScope().getName();
|
||||
String ownerID = (claim ? getBbbSession().getInternalUserID() : "");
|
||||
|
||||
red5InGW.updateCaptionOwner(meetingID, locale, ownerID);
|
||||
}
|
||||
|
||||
red5InGW.updateCaptionOwner(meetingID, locale, localeCode, ownerID);
|
||||
}
|
||||
|
||||
public void editCaptionHistory(Map<String, Object> msg) {
|
||||
int startIndex = (Integer) msg.get("startIndex");
|
||||
int endIndex = (Integer) msg.get("endIndex");
|
||||
String locale = msg.get("locale").toString();
|
||||
String localeCode = msg.get("localeCode").toString();
|
||||
String text = msg.get("text").toString();
|
||||
|
||||
String meetingID = Red5.getConnectionLocal().getScope().getName();
|
||||
String userID = getBbbSession().getInternalUserID();
|
||||
|
||||
red5InGW.editCaptionHistory(meetingID, userID, startIndex, endIndex, locale, text);
|
||||
|
||||
Integer startIndex;
|
||||
if (msg.get("startIndex") instanceof Double) {
|
||||
Double tempStartIndex = (Double) msg.get("startIndex");
|
||||
startIndex = tempStartIndex.intValue();
|
||||
} else {
|
||||
startIndex = (Integer) msg.get("startIndex");
|
||||
}
|
||||
|
||||
Integer endIndex;
|
||||
if (msg.get("endIndex") instanceof Double) {
|
||||
Double tempEndIndex = (Double) msg.get("endIndex");
|
||||
endIndex = tempEndIndex.intValue();
|
||||
} else {
|
||||
endIndex = (Integer) msg.get("endIndex");
|
||||
}
|
||||
|
||||
red5InGW.editCaptionHistory(meetingID, userID, startIndex, endIndex, locale, localeCode, text);
|
||||
}
|
||||
}
|
||||
|
@ -41,9 +41,23 @@ public class PollingService {
|
||||
String meetingID = Red5.getConnectionLocal().getScope().getName();
|
||||
String userId = getBbbSession().getInternalUserID();
|
||||
String pollId = (String) message.get("pollId");
|
||||
Integer questionId = (Integer) message.get("answerId");
|
||||
Integer answerId = (Integer) message.get("answerId");
|
||||
|
||||
|
||||
Integer questionId;
|
||||
if (message.get("answerId") instanceof Double) {
|
||||
Double tempQuestionId = (Double) message.get("answerId");
|
||||
questionId = tempQuestionId.intValue();
|
||||
} else {
|
||||
questionId = (Integer) message.get("answerId");
|
||||
}
|
||||
|
||||
Integer answerId;
|
||||
if (message.get("answerId") instanceof Double) {
|
||||
Double tempAnswerId = (Double) message.get("answerId");
|
||||
answerId = tempAnswerId.intValue();
|
||||
} else {
|
||||
answerId = (Integer) message.get("answerId");
|
||||
}
|
||||
|
||||
red5GW.votePoll(meetingID, userId, pollId, questionId, answerId);
|
||||
}
|
||||
|
||||
|
@ -570,6 +570,10 @@ TitleWindow {
|
||||
imageSource: Embed(source='assets/images/bbb_mac_safari_3.png');
|
||||
}
|
||||
|
||||
.publishHelpMacSafari4 {
|
||||
imageSource: Embed(source='assets/images/bbb_mac_safari_4.png');
|
||||
}
|
||||
|
||||
.publishHelpMacFirefox1 {
|
||||
imageSource: Embed(source='assets/images/bbb_mac_firefox_1.png');
|
||||
}
|
||||
@ -582,6 +586,10 @@ TitleWindow {
|
||||
imageSource: Embed(source='assets/images/bbb_mac_firefox_3.png');
|
||||
}
|
||||
|
||||
.publishHelpMacFirefox4 {
|
||||
imageSource: Embed(source='assets/images/bbb_mac_firefox_4.png');
|
||||
}
|
||||
|
||||
.publishHelpMacChrome1 {
|
||||
imageSource: Embed(source='assets/images/bbb_mac_chrome_1.png');
|
||||
}
|
||||
@ -594,6 +602,10 @@ TitleWindow {
|
||||
imageSource: Embed(source='assets/images/bbb_mac_chrome_3.png');
|
||||
}
|
||||
|
||||
.publishHelpMacChrome4 {
|
||||
imageSource: Embed(source='assets/images/bbb_mac_chrome_4.png');
|
||||
}
|
||||
|
||||
.publishHelpLinuxFirefox1 {
|
||||
imageSource: Embed(source='assets/images/bbb_linux_firefox_1.png');
|
||||
}
|
||||
@ -1049,6 +1061,10 @@ EmojiGrid {
|
||||
horizontalGap: 6;
|
||||
}
|
||||
|
||||
.breakoutRoomUserWindowHeadingStyle {
|
||||
fontWeight: bold;
|
||||
}
|
||||
|
||||
.breakoutRoomSettingTitleStyle {
|
||||
fontFamily: Arial;
|
||||
fontSize: 20;
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 391 B |
After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
@ -313,18 +313,21 @@ bbb.screensharePublish.helpText.PCChrome3 = 3. Accept the certificate
|
||||
bbb.screensharePublish.helpText.MacSafari1 = 1. Locate 'screenshare.jnlp'
|
||||
bbb.screensharePublish.helpText.MacSafari2 = 2. Select 'Show In Finder'
|
||||
bbb.screensharePublish.helpText.MacSafari3 = 3. Right-click and select 'Open'
|
||||
bbb.screensharePublish.helpText.MacFirefox1 = 1. Locate 'screenshare.jnlp'
|
||||
bbb.screensharePublish.helpText.MacSafari4 = 4. Select 'Open' (if prompted)
|
||||
bbb.screensharePublish.helpText.MacFirefox1 = 1. Choose 'Save File' (if asked)
|
||||
bbb.screensharePublish.helpText.MacFirefox2 = 2. Select 'Show In Finder'
|
||||
bbb.screensharePublish.helpText.MacFirefox3 = 3. Right-click and select 'Open'
|
||||
bbb.screensharePublish.helpText.MacFirefox4 = 4. Select 'Open' (if prompted)
|
||||
bbb.screensharePublish.helpText.MacChrome1 = 1. Locate 'screenshare.jnlp'
|
||||
bbb.screensharePublish.helpText.MacChrome2 = 2. Select 'Show In Finder'
|
||||
bbb.screensharePublish.helpText.MacChrome3 = 3. Right-click and select 'Open'
|
||||
bbb.screensharePublish.helpText.LinuxFirefox1 = Placeholder linuxFirefox1
|
||||
bbb.screensharePublish.helpText.LinuxFirefox2 = Placeholder linuxFirefox2
|
||||
bbb.screensharePublish.helpText.LinuxFirefox3 = Placeholder linuxFirefox3
|
||||
bbb.screensharePublish.helpText.LinuxChrome1 = Placeholder linuxChrome1
|
||||
bbb.screensharePublish.helpText.LinuxChrome2 = Placeholder linuxChrome2
|
||||
bbb.screensharePublish.helpText.LinuxChrome3 = Placeholder linuxChrome3
|
||||
bbb.screensharePublish.helpText.MacChrome4 = 4. Select 'Open' (if prompted)
|
||||
bbb.screensharePublish.helpText.LinuxFirefox1 = 1. Click 'OK' to run
|
||||
bbb.screensharePublish.helpText.LinuxFirefox2 = 2. Accept the certificate
|
||||
bbb.screensharePublish.helpText.LinuxFirefox3 =
|
||||
bbb.screensharePublish.helpText.LinuxChrome1 = 1. Locate 'screenshare.jnlp'
|
||||
bbb.screensharePublish.helpText.LinuxChrome2 = 2. Click to open
|
||||
bbb.screensharePublish.helpText.LinuxChrome3 = 3. Accept the certificate
|
||||
bbb.screensharePublish.shareTypeLabel.text = Share:
|
||||
bbb.screensharePublish.shareType.fullScreen = Full screen
|
||||
bbb.screensharePublish.shareType.region = Region
|
||||
@ -421,6 +424,7 @@ bbb.logout.rejected = The connection to the server has been rejected
|
||||
bbb.logout.invalidapp = The red5 app does not exist
|
||||
bbb.logout.unknown = Your client has lost connection with the server
|
||||
bbb.logout.usercommand = You have logged out of the conference
|
||||
bbb.logour.breakoutRoomClose = Your browser window will be closed
|
||||
bbb.logout.ejectedFromMeeting = A moderator has kicked you out of the meeting.
|
||||
bbb.logout.refresh.message = If this logout was unexpected click the button below to reconnect.
|
||||
bbb.logout.refresh.label = Reconnect
|
||||
@ -645,6 +649,7 @@ bbb.users.settings.lockAll=Lock All Users
|
||||
bbb.users.settings.lockAllExcept=Lock Users Except Presenter
|
||||
bbb.users.settings.lockSettings=Lock Viewers ...
|
||||
bbb.users.settings.breakoutRooms=Breakout Rooms ...
|
||||
bbb.users.settings.sendBreakoutRoomsInvitations=Send Breakout Rooms Invitations ...
|
||||
bbb.users.settings.unlockAll=Unlock All Viewers
|
||||
bbb.users.settings.roomIsLocked=Locked by default
|
||||
bbb.users.settings.roomIsMuted=Muted by default
|
||||
@ -666,19 +671,24 @@ bbb.lockSettings.locked=Locked
|
||||
bbb.lockSettings.lockOnJoin=Lock On Join
|
||||
|
||||
bbb.users.breakout.breakoutRooms = Breakout Rooms
|
||||
bbb.users.breakout.updateBreakoutRooms = Update Breakout Rooms
|
||||
bbb.users.breakout.remainingTimeBreakout = {0}: <b>{1} remaining</b>
|
||||
bbb.users.breakout.remainingTimeParent = <b>{1} remaining</b>
|
||||
bbb.users.breakout.calculatingRemainingTime = Calculating remaining time...
|
||||
bbb.users.breakout.remainingTimeEnded = Time ended, breakout room will close.
|
||||
bbb.users.breakout.rooms = Rooms
|
||||
bbb.users.breakout.roomsCombo.accessibilityName = Number of rooms to create
|
||||
bbb.users.breakout.room = Room
|
||||
bbb.users.breakout.randomAssign = Randomly Assign Users
|
||||
bbb.users.breakout.timeLimit = Time Limit
|
||||
bbb.users.breakout.durationStepper.accessibilityName = Time limit in minutes
|
||||
bbb.users.breakout.minutes = Minutes
|
||||
bbb.users.breakout.record = Record
|
||||
bbb.users.breakout.recordCheckbox.accessibilityName = Record breakout rooms
|
||||
bbb.users.breakout.notAssigned = Not Assigned
|
||||
bbb.users.breakout.dragAndDropToolTip = Tip: You can drag and drop users between rooms
|
||||
bbb.users.breakout.start = Start
|
||||
bbb.users.breakout.invite = Invite
|
||||
bbb.users.breakout.close = Close
|
||||
bbb.users.breakout.closeAllRooms = Close All Breakout Rooms
|
||||
bbb.users.breakout.insufficientUsers = Insufficient users. You should place at least one user in one breakout room.
|
||||
|
@ -47,7 +47,7 @@
|
||||
uri="rtmp://HOST/screenshare"
|
||||
showButton="true"
|
||||
baseTabIndex="201"
|
||||
useWebRTCIfAvailable="false"
|
||||
tryWebRTCFirst="false"
|
||||
chromeExtensionKey=""
|
||||
help="http://HOST/client/help/screenshare-help.html"
|
||||
/>
|
||||
|
@ -1,30 +1,55 @@
|
||||
<h1>Desktop Sharing Help</h1>
|
||||
<p>This page contains a list of videos that let you quickly get started using BigBlueButton's desktop sharing.</p>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
h1,h2 {
|
||||
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Launching Screen Sharing</h1>
|
||||
|
||||
<p>Desktop sharing requires Java 1.8. If you don't have Java 1.8 installed (or are not sure if you have it installed), first visit <a href="http://java.com/">java.com</a> and install Java.</p>
|
||||
<p>As the presenter, before you launch screen sharing you need Java installed on your computer (we recommend Java 1.8, though it might work on older versions). If you don't have Java 1.8 installed (or are not sure if you have it installed), visit <a href="http://java.com/">java.com</a> to install Java.</p>
|
||||
|
||||
<p>Choose the video below that corresponds to your operating system and browser.<p>
|
||||
<h2>Tutorial Video</h2>
|
||||
<p>The video below demonstrates how to launch screen sharing on both Windows and Mac OS X.</p>
|
||||
|
||||
<h2>Windows + Internet Explorer</h2>
|
||||
<iframe width="420" height="315" src="https://www.youtube.com/embed/xTFuEvmEqB0" frameborder="0" allowfullscreen></iframe>
|
||||
|
||||
<iframe width="420" height="315" src="https://www.youtube.com/embed/w0qei2-uDpI" frameborder="0" allowfullscreen></iframe>
|
||||
<p>When you start screen sharing, it will download a file called <b>screenshare (N).jnlp</b>. It might be called screenshare.jnlp, screenshare (1).jnlp, screenshare (2).jnlp, and so on. As shown in the above video, you open downloaded file to launch screen sharing. The steps to open are different depending on your operating system.</p>
|
||||
|
||||
<h2>Windows + Firefox</h2>
|
||||
<h2>Windows</h2>
|
||||
<p>As decribed in the above video, on Windows, the steps to open <b>screenshare (N).jnlp</b> are:</p>
|
||||
|
||||
<iframe width="420" height="315" src="https://www.youtube.com/embed/7ZuunBQbmj8" frameborder="0" allowfullscreen></iframe>
|
||||
<ol>
|
||||
<li>Locate where the browser has downloaded screenshare (N).jnlp (the images will guide you)
|
||||
<li>Click to open
|
||||
</ol>
|
||||
|
||||
<h2>Windows + Chrome</h2>
|
||||
<h2>Mac OS X</h2>
|
||||
<p>As shown in the above video, on Mac OS X, the steps to open <b>screenshare (N).jnlp</b> in Chrome are:</p>
|
||||
|
||||
<iframe width="420" height="315" src="https://www.youtube.com/embed/bx9Tupfro_I" frameborder="0" allowfullscreen></iframe>
|
||||
<ol>
|
||||
<li>Locate where the browser has downloaded screenshare (N).jnlp (the images will guide you)
|
||||
<li>Open in Finder
|
||||
<li>Right-click and choose "Open"
|
||||
</ol>
|
||||
|
||||
<h2>Mac OS X + Chrome<h2>
|
||||
<p>For FireFox, the steps are:</p>
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/Xezw2moXZQE" frameborder="0" allowfullscreen></iframe>
|
||||
<ol>
|
||||
<li>Choose "Save File" (if asked)
|
||||
<li>Open in Finder
|
||||
<li>Right-click and choose "Open"
|
||||
</ol>
|
||||
|
||||
<h2>Mac OS X + FireFox</h2>
|
||||
<h2>Notes</h2>
|
||||
<p>The extension .jnlp stands for Java Network Launch Protocol. When you open the downloaded <b>screenshare (N).jnlp</b>, your computer launchs Java with, in turn, downloads and launchs the BigBlueButton screen share application. You then control the screen sharing application within the BigBlueButton client.</p>
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/FmTJOB4SODc" frameborder="0" allowfullscreen></iframe>
|
||||
<p>The presenter and only the presenter needs to have Java installed. Students view your desktop within BigBlueButton client. On Windows, screen share supports sharing full screen and region. On Mac OS X, screen schare only supports full screen. In both platforms, full screen will share your home screen.</p>
|
||||
|
||||
<p>For more vidoes on using BigBlueButton, see <a href="http://bigbluebutton.org/videos/">http://bigbluebutton.org/videos/</a>.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -97,7 +97,7 @@
|
||||
iframe.onload = function() {
|
||||
iframe.isLoaded = true;
|
||||
};
|
||||
iframe.src = 'https://www.webrtc-experiment.com/getSourceId/';
|
||||
// iframe.src = 'https://www.webrtc-experiment.com/getSourceId/';
|
||||
iframe.style.display = 'none';
|
||||
(document.body || document.documentElement).appendChild(iframe);
|
||||
})();
|
||||
})();
|
||||
|
@ -1,13 +1,13 @@
|
||||
/**
|
||||
* 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.
|
||||
@ -16,49 +16,56 @@
|
||||
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package org.bigbluebutton.core
|
||||
{
|
||||
package org.bigbluebutton.core {
|
||||
|
||||
import flash.system.Capabilities;
|
||||
|
||||
import mx.core.FlexGlobals;
|
||||
import mx.utils.URLUtil;
|
||||
|
||||
import org.bigbluebutton.core.managers.ConfigManager2;
|
||||
import org.bigbluebutton.core.managers.ConnectionManager;
|
||||
import org.bigbluebutton.core.managers.UserConfigManager;
|
||||
import org.bigbluebutton.core.managers.UserManager;
|
||||
import org.bigbluebutton.core.managers.VideoProfileManager;
|
||||
import org.bigbluebutton.core.model.Session;
|
||||
import org.bigbluebutton.core.model.VideoProfile;
|
||||
import org.bigbluebutton.util.SessionTokenUtil;
|
||||
|
||||
import org.bigbluebutton.util.SessionTokenUtil;
|
||||
|
||||
public class BBB {
|
||||
private static var configManager:ConfigManager2 = null;
|
||||
|
||||
private static var connectionManager:ConnectionManager = null;
|
||||
|
||||
private static var session:Session = null;
|
||||
|
||||
private static var userConfigManager:UserConfigManager = null;
|
||||
|
||||
private static var videoProfileManager:VideoProfileManager = null;
|
||||
|
||||
private static var sessionTokenUtil:SessionTokenUtil = null;
|
||||
|
||||
|
||||
public static function getSessionTokenUtil():SessionTokenUtil {
|
||||
if (sessionTokenUtil == null) {
|
||||
sessionTokenUtil = new SessionTokenUtil();
|
||||
}
|
||||
return sessionTokenUtil;
|
||||
}
|
||||
|
||||
|
||||
public static function initUserConfigManager():UserConfigManager {
|
||||
if (userConfigManager == null) {
|
||||
userConfigManager = new UserConfigManager();
|
||||
}
|
||||
return userConfigManager;
|
||||
}
|
||||
|
||||
|
||||
public static function getConfigManager():ConfigManager2 {
|
||||
if (configManager == null) {
|
||||
configManager = new ConfigManager2();
|
||||
}
|
||||
return configManager;
|
||||
}
|
||||
|
||||
|
||||
public static function loadConfig():void {
|
||||
configManager.loadConfig();
|
||||
}
|
||||
@ -86,7 +93,7 @@ package org.bigbluebutton.core
|
||||
public static function get defaultVideoProfile():VideoProfile {
|
||||
return initVideoProfileManager().defaultVideoProfile;
|
||||
}
|
||||
|
||||
|
||||
public static function get fallbackVideoProfile():VideoProfile {
|
||||
return initVideoProfileManager().fallbackVideoProfile;
|
||||
}
|
||||
@ -96,47 +103,54 @@ package org.bigbluebutton.core
|
||||
connectionManager = new ConnectionManager();
|
||||
}
|
||||
return connectionManager;
|
||||
}
|
||||
}
|
||||
|
||||
public static function initSession():Session {
|
||||
if (session == null) {
|
||||
session = new Session();
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static function getFlashPlayerVersion():Number {
|
||||
var versionString:String = Capabilities.version;
|
||||
var pattern:RegExp = /^(\w*) (\d*),(\d*),(\d*),(\d*)$/;
|
||||
var result:Object = pattern.exec(versionString);
|
||||
if (result != null) {
|
||||
// trace("input: " + result.input);
|
||||
// trace("platform: " + result[1]);
|
||||
// trace("majorVersion: " + result[2]);
|
||||
// trace("minorVersion: " + result[3]);
|
||||
// trace("buildNumber: " + result[4]);
|
||||
// trace("internalBuildNumber: " + result[5]);
|
||||
// trace("input: " + result.input);
|
||||
// trace("platform: " + result[1]);
|
||||
// trace("majorVersion: " + result[2]);
|
||||
// trace("minorVersion: " + result[3]);
|
||||
// trace("buildNumber: " + result[4]);
|
||||
// trace("internalBuildNumber: " + result[5]);
|
||||
return Number(result[2] + "." + result[3]);
|
||||
} else {
|
||||
// trace("Unable to match RegExp.");
|
||||
// trace("Unable to match RegExp.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function getLogoutURL():String {
|
||||
var logoutUrl:String = BBB.initUserConfigManager().getLogoutUrl();
|
||||
if (logoutUrl == null) {
|
||||
var pageHost:String = FlexGlobals.topLevelApplication.url.split("/")[0];
|
||||
var pageURL:String = FlexGlobals.topLevelApplication.url.split("/")[2];
|
||||
var sessionToken:String = BBB.sessionTokenUtil.getSessionToken();
|
||||
logoutUrl = pageHost + "//" + pageURL;
|
||||
if (sessionToken != "") {
|
||||
logoutUrl = pageHost + "//" + pageURL + "/bigbluebutton/api/signOut?sessionToken=" + sessionToken;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
logoutUrl = getBaseURL();
|
||||
}
|
||||
return logoutUrl;
|
||||
}
|
||||
|
||||
public static function getSignoutURL():String {
|
||||
var sessionToken:String = BBB.sessionTokenUtil.getSessionToken();
|
||||
var logoutUrl:String = getBaseURL();
|
||||
if (sessionToken != "") {
|
||||
logoutUrl += "/bigbluebutton/api/signOut?sessionToken=" + sessionToken;
|
||||
}
|
||||
return logoutUrl;
|
||||
}
|
||||
|
||||
public static function getBaseURL():String {
|
||||
var protocol:String = URLUtil.getProtocol(FlexGlobals.topLevelApplication.url);
|
||||
var serverName:String = URLUtil.getServerNameWithPort(FlexGlobals.topLevelApplication.url);
|
||||
return protocol + "://" + serverName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,16 +36,12 @@ package org.bigbluebutton.core.managers
|
||||
}
|
||||
|
||||
|
||||
public function setUri(uri:String):void {
|
||||
connDelegate.setUri(uri);
|
||||
}
|
||||
|
||||
public function get connection():NetConnection {
|
||||
return connDelegate.connection;
|
||||
}
|
||||
|
||||
public function connect(params:ConferenceParameters):void {
|
||||
connDelegate.connect(params);
|
||||
public function connect():void {
|
||||
connDelegate.connect();
|
||||
}
|
||||
|
||||
public function disconnect(onUserAction:Boolean):void {
|
||||
|
@ -18,18 +18,15 @@
|
||||
*/
|
||||
package org.bigbluebutton.core.managers
|
||||
{
|
||||
import com.asfusion.mate.events.Dispatcher;
|
||||
|
||||
import com.asfusion.mate.events.Dispatcher;
|
||||
import flash.display.DisplayObject;
|
||||
import flash.events.TimerEvent;
|
||||
import flash.utils.Dictionary;
|
||||
import flash.utils.Timer;
|
||||
|
||||
import flash.utils.Timer;
|
||||
import mx.collections.ArrayCollection;
|
||||
import mx.core.FlexGlobals;
|
||||
import mx.core.IFlexDisplayObject;
|
||||
import mx.managers.PopUpManager;
|
||||
|
||||
import mx.managers.PopUpManager;
|
||||
import org.as3commons.logging.api.ILogger;
|
||||
import org.as3commons.logging.api.getClassLogger;
|
||||
import org.bigbluebutton.core.UsersUtil;
|
||||
@ -76,7 +73,6 @@ package org.bigbluebutton.core.managers
|
||||
}
|
||||
|
||||
private function timeout(e:TimerEvent = null):void {
|
||||
LOGGER.debug("timeout");
|
||||
_dispatcher.dispatchEvent(new BBBEvent(BBBEvent.CANCEL_RECONNECTION_EVENT));
|
||||
_dispatcher.dispatchEvent(new LogoutEvent(LogoutEvent.USER_LOGGED_OUT));
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
/**
|
||||
* 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.
|
||||
@ -16,33 +16,38 @@
|
||||
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package org.bigbluebutton.core.managers
|
||||
{
|
||||
package org.bigbluebutton.core.managers {
|
||||
|
||||
import org.bigbluebutton.main.model.ConferenceParameters;
|
||||
|
||||
public class UserConfigManager
|
||||
{
|
||||
public class UserConfigManager {
|
||||
private var conferenceParameters:ConferenceParameters = null;
|
||||
|
||||
|
||||
public function setConferenceParameters(c:ConferenceParameters):void {
|
||||
conferenceParameters = c;
|
||||
}
|
||||
|
||||
|
||||
public function getConfParams():ConferenceParameters {
|
||||
return conferenceParameters;
|
||||
}
|
||||
|
||||
public function getLogoutUrl():String {
|
||||
if (conferenceParameters == null) return null;
|
||||
if (conferenceParameters == null)
|
||||
return null;
|
||||
return conferenceParameters.logoutUrl;
|
||||
}
|
||||
|
||||
public function getWelcomeMessage():String {
|
||||
if (conferenceParameters == null) return null;
|
||||
return conferenceParameters.welcome;
|
||||
}
|
||||
|
||||
public function getMeetingTitle():String {
|
||||
if (conferenceParameters)
|
||||
return conferenceParameters.meetingName;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getWelcomeMessage():String {
|
||||
if (conferenceParameters == null)
|
||||
return null;
|
||||
return conferenceParameters.welcome;
|
||||
}
|
||||
|
||||
public function getMeetingTitle():String {
|
||||
if (conferenceParameters)
|
||||
return conferenceParameters.meetingName;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,40 +17,44 @@
|
||||
*
|
||||
*/
|
||||
package org.bigbluebutton.main.events {
|
||||
|
||||
|
||||
import flash.events.Event;
|
||||
|
||||
|
||||
public class BreakoutRoomEvent extends Event {
|
||||
public static const OPEN_BREAKOUT_ROOMS_PANEL:String = "OPEN_BREAKOUT_ROOMS_PANEL";
|
||||
|
||||
|
||||
public static const CREATE_BREAKOUT_ROOMS:String = "CREATE_BREAKOUT_ROOMS";
|
||||
|
||||
|
||||
public static const REQUEST_BREAKOUT_JOIN_URL:String = "REQUEST_BREAKOUT_JOIN_URL";
|
||||
|
||||
|
||||
public static const BREAKOUT_JOIN_URL:String = "BREAKOUT_JOIN_URL";
|
||||
|
||||
|
||||
public static const LISTEN_IN:String = "LISTEN_IN";
|
||||
|
||||
|
||||
public static const END_ALL_BREAKOUT_ROOMS:String = "END_ALL_BREAKOUT_ROOMS";
|
||||
|
||||
|
||||
public static const UPDATE_REMAINING_TIME_PARENT:String = "UPDATE_REMAINING_TIME_PARENT";
|
||||
|
||||
public static const UPDATE_REMAINING_TIME_BREAKOUT:String = "UPDATE_REMAINING_TIME_BREAKOUT";
|
||||
|
||||
|
||||
public var meetingId:String;
|
||||
|
||||
|
||||
public var breakoutId:String;
|
||||
|
||||
|
||||
public var rooms:Array;
|
||||
|
||||
|
||||
public var durationInMinutes:int;
|
||||
|
||||
|
||||
public var record:Boolean;
|
||||
|
||||
|
||||
public var joinURL:String;
|
||||
|
||||
|
||||
public var listen:Boolean;
|
||||
|
||||
|
||||
public var joinMode:String;
|
||||
|
||||
public var userId:String;
|
||||
|
||||
public function BreakoutRoomEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false) {
|
||||
super(type, bubbles, cancelable);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ package org.bigbluebutton.main.events
|
||||
public static const PORT_TEST_UPDATE:String = "PORT_TEST_UPDATE";
|
||||
public static const TUNNELING_FAILED:String = "RTMTP_ALSO_FAILED";
|
||||
|
||||
public var protocol:String;
|
||||
public var tunnel:Boolean;
|
||||
public var hostname:String;
|
||||
public var port:String;
|
||||
public var app:String;
|
||||
|
@ -24,13 +24,7 @@ package org.bigbluebutton.main.events
|
||||
{
|
||||
public static const START_USER_SERVICES:String = "START_USER_SERVICES";
|
||||
public static const USER_SERVICES_STARTED:String = "USER_SERVICES_STARTED";
|
||||
|
||||
public var applicationURI:String;
|
||||
public var hostURI:String;
|
||||
public var isTunnelling:Boolean = false;
|
||||
|
||||
public var user:Object;
|
||||
|
||||
|
||||
public function UserServicesEvent(type:String)
|
||||
{
|
||||
super(type, true, false);
|
||||
|
@ -46,11 +46,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
</EventHandlers>
|
||||
|
||||
<EventHandlers type="{PortTestEvent.PORT_TEST_SUCCESS}" >
|
||||
<MethodInvoker generator="{ModulesProxy}" method="portTestSuccess" arguments="{event.protocol}" />
|
||||
<MethodInvoker generator="{ModulesProxy}" method="portTestSuccess" arguments="{event.tunnel}" />
|
||||
</EventHandlers>
|
||||
|
||||
<EventHandlers type="{PortTestEvent.PORT_TEST_FAILED}" >
|
||||
<MethodInvoker generator="{ModulesProxy}" method="testRTMPT" arguments="{event.protocol}" />
|
||||
<MethodInvoker generator="{ModulesProxy}" method="testRTMPT" arguments="{event.tunnel}" />
|
||||
</EventHandlers>
|
||||
|
||||
<EventHandlers type="{SuccessfulLoginEvent.USER_LOGGED_IN}" >
|
||||
|
@ -1,3 +1,3 @@
|
||||
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.main.model
{
import flash.events.NetStatusEvent;
import flash.events.TimerEvent;
import flash.net.NetConnection;
import flash.net.ObjectEncoding;
import flash.utils.Timer;
import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger;
[Bindable]
/**
* Test RTMP port.
*
* @author Thijs Triemstra ( info@collab.nl )
*/
public class PortTest
{
private static const LOGGER:ILogger = getClassLogger(PortTest);
/**
* Protocol name.
*/
private var protocol : String;
/**
* Protocol name (uppercase).
*/
public var protocolName : String;
/**
* RTMP hostname.
*/
private var hostname : String;
/**
* RTMP port.
*/
public var port : String;
/**
* RTMP port.
*/
public var portName : String = "Default";
/**
* RTMP application.
*/
private var application : String;
/**
* Base RTMP URI.
*/
private var baseURI : String;
/**
* RTMP connection.
*/
public var nc : NetConnection;
/**
* Connection status.
*/
public var status : String;
private var _connectionListener:Function;
/**
* Timer to control timeout of connection test
*/
private var testTimeout:Number = 0;
/**
* Timer to control timeout of connection test
*/
private var connectionTimer:Timer;
/**
* Set default encoding to AMF0 so FMS also understands.
*/
NetConnection.defaultObjectEncoding = ObjectEncoding.AMF0;
/**
* Create new port test and connect to the RTMP server.
*
* @param protocol
* @param hostname
* @param port
* @param application
* @testTimeout timeout of test in milliseconds
*/
public function PortTest( protocol : String = "",
hostname : String = "",
port : String = "",
application : String = "",
testTimeout : Number = 10000
)
{
this.protocol = protocol;
this.protocolName = protocol.toUpperCase();
this.hostname = hostname;
this.application = application;
this.testTimeout = testTimeout;
if ( port.length > 0 )
protocol : String = "",
testTimeout : Number = 10000
protocol : String = "",
)
protocol : String = "",
{
}
protocol : String = "",
this.protocolName = protocol.toUpperCase();
{
hostname : String = "",
protocol : String = "",
this.protocol = protocol;
hostname : String = "",
protocol : String = "",
this.baseURI = this.protocol + "://" + this.hostname + this.port + "/" + this.application;
//
}
/**
* Start connection.
*/
public function connect() : void
{
this.nc = new NetConnection();
this.nc.client = this;
|
||||
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.main.model
{
import flash.events.NetStatusEvent;
import flash.events.TimerEvent;
import flash.net.NetConnection;
import flash.net.ObjectEncoding;
import flash.utils.Timer;
import org.as3commons.logging.api.ILogger;
import org.as3commons.logging.api.getClassLogger;
[Bindable]
/**
* Test RTMP port.
*
* @author Thijs Triemstra ( info@collab.nl )
*/
public class PortTest
{
private static const LOGGER:ILogger = getClassLogger(PortTest);
/**
* Connect using rtmp or rtmpt.
*/
private var tunnel: Boolean;
/**
* RTMP hostname.
*/
private var hostname : String;
/**
* RTMP port.
*/
public var port : String;
/**
* RTMP port.
*/
public var portName : String = "Default";
/**
* RTMP application.
*/
private var application : String;
/**
* Base RTMP URI.
*/
private var baseURI : String;
/**
* RTMP connection.
*/
public var nc : NetConnection;
/**
* Connection status.
*/
public var status : String;
private var _connectionListener:Function;
/**
* Timer to control timeout of connection test
*/
private var testTimeout:Number = 0;
/**
* Timer to control timeout of connection test
*/
private var connectionTimer:Timer;
/**
* Set default encoding to AMF0 so FMS also understands.
*/
NetConnection.defaultObjectEncoding = ObjectEncoding.AMF0;
/**
* Create new port test and connect to the RTMP server.
*
* @param protocol
* @param hostname
* @param port
* @param application
* @testTimeout timeout of test in milliseconds
*/
public function PortTest( tunnel : Boolean,
hostname : String = "",
port : String = "",
application : String = "",
testTimeout : Number = 10000) {
this.tunnel = tunnel;
this.hostname = hostname;
this.application = application;
this.testTimeout = testTimeout;
if ( port.length > 0 ) {
protocol : String = "",
)
protocol : String = "",
{
hostname : String = "",
{
this.port = port;
}
hostname : String = "",
protocol : String = "",
if (tunnel) {
hostname : String = "",
this.protocolName = protocol.toUpperCase();
port : String = "",
port : String = "",
protocol : String = "",
port : String = "",
hostname : String = "",
//
}
/**
* Start connection.
*/
public function connect() : void
{
this.nc = new NetConnection();
this.nc.client = this;
|
||||
this.nc.proxyType = "best";
|
||||
this.nc.addEventListener( NetStatusEvent.NET_STATUS, netStatus );
// connect to server
try
{
// Create connection with the server.
this.nc.connect( this.baseURI, "portTestMeetingId", "portTestDummyUserId" );
status = "Connecting...";
connectionTimer = new Timer(testTimeout, 1);
connectionTimer.addEventListener(TimerEvent.TIMER, connectionTimeout);
connectionTimer.start();
}
catch( e : ArgumentError )
{
// Invalid parameters.
status = "ERROR: " + e.message;
}
}
/**
* Method called when connection timed out
*/
public function connectionTimeout (e:TimerEvent) : void
{
status = "FAILED";
_connectionListener(status, protocol, hostname, port, application);
close();
}
/**
* Close connection.
*/
public function close() : void
{
//Stop timeout timer when connected/rejected
connectionTimer.stop();
// Remove listener.
this.nc.removeEventListener( NetStatusEvent.NET_STATUS, netStatus );
// Close the NetConnection.
this.nc.close();
}
/**
* Catch NetStatusEvents.
*
* @param event
*/
protected function netStatus( event : NetStatusEvent ) : void
{
var info : Object = event.info;
var statusCode : String = info.code;
//
if ( statusCode == "NetConnection.Connect.Success" )
{
status = "SUCCESS";
_connectionListener(status, protocol, hostname, port, application);
}
connectionTimer = new Timer(testTimeout, 1);
connectionTimer.addEventListener(TimerEvent.TIMER, connectionTimeout);
statusCode == "NetConnection.Connect.Closed" )
// Create connection with the server.
}
_connectionListener(status, protocol, hostname, port, application);
}
catch( e : ArgumentError )
connectionTimer = new Timer(testTimeout, 1);
}
public function onBWCheck(... rest):Number {
return 0;
}
public function onBWDone(... rest):void {
var p_bw:Number;
if (rest.length > 0) p_bw = rest[0];
// your application should do something here
// when the bandwidth check is complete
LOGGER.debug("bandwidth = {0} Kbps.", [p_bw]);
}
public function addConnectionSuccessListener(listener:Function):void {
_connectionListener = listener;
}
}
}
|
||||
this.nc.addEventListener( NetStatusEvent.NET_STATUS, netStatus );
// connect to server
try
{
LOGGER.debug("Testing connection to " + this.baseURI);
// Create connection with the server.
this.nc.connect( this.baseURI, "portTestMeetingId", "portTestDummyUserId" );
status = "Connecting...";
connectionTimer = new Timer(testTimeout, 1);
connectionTimer.addEventListener(TimerEvent.TIMER, connectionTimeout);
connectionTimer.start();
}
catch( e : ArgumentError )
{
// Invalid parameters.
status = "ERROR: " + e.message;
}
}
/**
* Method called when connection timed out
*/
public function connectionTimeout (e:TimerEvent) : void
{
LOGGER.debug("Timedout trying to connect to " + this.baseURI);
status = "FAILED";
_connectionListener(status, tunnel, hostname, port, application);
close();
}
/**
* Close connection.
*/
public function close() : void
{
//Stop timeout timer when connected/rejected
connectionTimer.stop();
// Remove listener.
this.nc.removeEventListener( NetStatusEvent.NET_STATUS, netStatus );
// Close the NetConnection.
this.nc.close();
}
/**
* Catch NetStatusEvents.
*
* @param event
*/
protected function netStatus( event : NetStatusEvent ) : void
{
var info : Object = event.info;
var statusCode : String = info.code;
//
// Close NetConnection.
close();
connectionTimer = new Timer(testTimeout, 1);
}
status = "Connecting...";
connectionTimer = new Timer(testTimeout, 1);
catch( e : ArgumentError )
connectionTimer.addEventListener(TimerEvent.TIMER, connectionTimeout);
connectionTimer.addEventListener(TimerEvent.TIMER, connectionTimeout);
// Create connection with the server.
connectionTimer.addEventListener(TimerEvent.TIMER, connectionTimeout);
statusCode == "NetConnection.Connect.Closed" ) {
LOGGER.debug("Failed to connect to " + this.baseURI);
}
connectionTimer.addEventListener(TimerEvent.TIMER, connectionTimeout);
}
}
public function onBWCheck(... rest):Number {
return 0;
}
public function onBWDone(... rest):void {
var p_bw:Number;
if (rest.length > 0) p_bw = rest[0];
// your application should do something here
// when the bandwidth check is complete
LOGGER.debug("bandwidth = {0} Kbps.", [p_bw]);
}
public function addConnectionSuccessListener(listener:Function):void {
_connectionListener = listener;
}
}
}
|
||||
|
25
bigbluebutton-client/src/org/bigbluebutton/main/model/PortTestProxy.as
Normal file → Executable file
@ -28,31 +28,29 @@ package org.bigbluebutton.main.model {
|
||||
private static const LOGGER:ILogger = getClassLogger(PortTestProxy);
|
||||
|
||||
private var nc:NetConnection;
|
||||
private var protocol:String;
|
||||
private var tunnel:Boolean;
|
||||
private var port:String;
|
||||
private var hostname:String;
|
||||
private var application:String;
|
||||
private var uri:String;
|
||||
private var modulesDispatcher:ModulesDispatcher;
|
||||
|
||||
public function PortTestProxy(modulesDispatcher: ModulesDispatcher) {
|
||||
this.modulesDispatcher = modulesDispatcher;
|
||||
}
|
||||
|
||||
public function connect(protocol:String = "", hostname:String = "", port:String = "", application:String = "", testTimeout:Number = 10000):void {
|
||||
var portTest:PortTest = new PortTest(protocol,hostname,port,application, testTimeout);
|
||||
public function connect(tunnel:Boolean, hostname:String = "", port:String = "", application:String = "", testTimeout:Number = 10000):void {
|
||||
this.tunnel = tunnel;
|
||||
var portTest:PortTest = new PortTest(tunnel, hostname, port, application, testTimeout);
|
||||
portTest.addConnectionSuccessListener(connectionListener);
|
||||
var red5Url:String = protocol + "://" + hostname + "/" + application;
|
||||
|
||||
|
||||
portTest.connect();
|
||||
}
|
||||
|
||||
private function connectionListener(status:String, protocol:String, hostname:String, port:String, application:String):void {
|
||||
uri = protocol + "://" + hostname + "/" + application;
|
||||
private function connectionListener(status:String, tunnel:Boolean, hostname:String, port:String, application:String):void {
|
||||
if (status == "SUCCESS") {
|
||||
modulesDispatcher.sendPortTestSuccessEvent(port, hostname, protocol, application);
|
||||
modulesDispatcher.sendPortTestSuccessEvent(port, hostname, tunnel, application);
|
||||
} else {
|
||||
modulesDispatcher.sendPortTestFailedEvent(port, hostname, protocol, application);
|
||||
modulesDispatcher.sendPortTestFailedEvent(port, hostname, tunnel, application);
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,14 +64,13 @@ package org.bigbluebutton.main.model {
|
||||
var statusCode : String = info.code;
|
||||
|
||||
if (statusCode == "NetConnection.Connect.Success") {
|
||||
modulesDispatcher.sendPortTestSuccessEvent(port, hostname, protocol, application);
|
||||
modulesDispatcher.sendPortTestSuccessEvent(port, hostname, tunnel, application);
|
||||
} else if (statusCode == "NetConnection.Connect.Rejected" ||
|
||||
statusCode == "NetConnection.Connect.Failed" ||
|
||||
statusCode == "NetConnection.Connect.Closed" ) {
|
||||
LOGGER.error("::netStatusEventHandler - Failed to connect to {0}", [uri]);
|
||||
modulesDispatcher.sendPortTestFailedEvent(port, hostname, protocol, application);
|
||||
modulesDispatcher.sendPortTestFailedEvent(port, hostname, tunnel, application);
|
||||
} else {
|
||||
LOGGER.error("Failed to connect to {0} due to {1}", [uri, statusCode]);
|
||||
modulesDispatcher.sendPortTestFailedEvent(port, hostname, tunnel, application);
|
||||
}
|
||||
// Close NetConnection.
|
||||
close();
|
||||
|
@ -18,15 +18,19 @@
|
||||
*/
|
||||
package org.bigbluebutton.main.model.modules
|
||||
{
|
||||
import com.asfusion.mate.events.Dispatcher;
|
||||
import com.asfusion.mate.events.Dispatcher;
|
||||
|
||||
import flash.system.ApplicationDomain;
|
||||
import flash.utils.Dictionary;
|
||||
import mx.collections.ArrayCollection;
|
||||
import flash.utils.Dictionary;
|
||||
|
||||
import mx.collections.ArrayCollection;
|
||||
|
||||
import org.as3commons.logging.api.ILogger;
|
||||
import org.as3commons.logging.api.getClassLogger;
|
||||
import org.bigbluebutton.common.IBigBlueButtonModule;
|
||||
import org.bigbluebutton.common.Role;
|
||||
import org.bigbluebutton.core.BBB;
|
||||
import org.bigbluebutton.core.model.MeetingModel;
|
||||
import org.bigbluebutton.main.events.AppVersionEvent;
|
||||
import org.bigbluebutton.main.model.ConferenceParameters;
|
||||
|
||||
@ -44,8 +48,6 @@ package org.bigbluebutton.main.model.modules
|
||||
private var _applicationDomain:ApplicationDomain;
|
||||
private var conferenceParameters:ConferenceParameters;
|
||||
|
||||
private var _protocol:String;
|
||||
|
||||
private var modulesDispatcher:ModulesDispatcher;
|
||||
|
||||
public function ModuleManager(modulesDispatcher: ModulesDispatcher)
|
||||
@ -72,8 +74,8 @@ package org.bigbluebutton.main.model.modules
|
||||
BBB.loadConfig();
|
||||
}
|
||||
|
||||
public function useProtocol(protocol:String):void {
|
||||
_protocol = protocol;
|
||||
public function useProtocol(tunnel:Boolean):void {
|
||||
BBB.initConnectionManager().isTunnelling = tunnel;
|
||||
}
|
||||
|
||||
public function get portTestHost():String {
|
||||
@ -96,7 +98,11 @@ package org.bigbluebutton.main.model.modules
|
||||
var m:ModuleDescriptor = getModule(name);
|
||||
if (m != null) {
|
||||
var bbb:IBigBlueButtonModule = m.module as IBigBlueButtonModule;
|
||||
m.loadConfigAttributes(conferenceParameters, _protocol);
|
||||
var protocol:String = "rtmp";
|
||||
if (BBB.initConnectionManager().isTunnelling) {
|
||||
protocol = "rtmpt";
|
||||
}
|
||||
m.loadConfigAttributes(conferenceParameters, protocol);
|
||||
bbb.start(m.attributes);
|
||||
}
|
||||
}
|
||||
@ -155,8 +161,7 @@ package org.bigbluebutton.main.model.modules
|
||||
}
|
||||
|
||||
public function startUserServices():void {
|
||||
var appURL:String = BBB.getConfigManager().config.application.uri.replace(/rtmp:/gi, _protocol + ":");
|
||||
modulesDispatcher.sendStartUserServicesEvent(appURL, BBB.getConfigManager().config.application.host, _protocol.toUpperCase() == "RTMPT");
|
||||
modulesDispatcher.sendStartUserServicesEvent();
|
||||
}
|
||||
|
||||
public function loadAllModules(parameters:ConferenceParameters):void{
|
||||
|
@ -18,10 +18,8 @@
|
||||
*/
|
||||
package org.bigbluebutton.main.model.modules
|
||||
{
|
||||
import com.asfusion.mate.events.Dispatcher;
|
||||
|
||||
import flash.events.TimerEvent;
|
||||
|
||||
import com.asfusion.mate.events.Dispatcher;
|
||||
import flash.events.TimerEvent;
|
||||
import org.as3commons.logging.api.ILogger;
|
||||
import org.as3commons.logging.api.getClassLogger;
|
||||
import org.as3commons.logging.util.jsonXify;
|
||||
@ -71,11 +69,8 @@ package org.bigbluebutton.main.model.modules
|
||||
dispatcher.dispatchEvent(loginEvent);
|
||||
}
|
||||
|
||||
public function sendStartUserServicesEvent(application:String, host:String, isTunnelling:Boolean):void{
|
||||
public function sendStartUserServicesEvent():void{
|
||||
var e:UserServicesEvent = new UserServicesEvent(UserServicesEvent.START_USER_SERVICES);
|
||||
e.applicationURI = application;
|
||||
e.hostURI = host;
|
||||
e.isTunnelling = isTunnelling;
|
||||
dispatcher.dispatchEvent(e);
|
||||
}
|
||||
|
||||
@ -130,11 +125,11 @@ package org.bigbluebutton.main.model.modules
|
||||
dispatcher.dispatchEvent(new PortTestEvent(PortTestEvent.TUNNELING_FAILED));
|
||||
}
|
||||
|
||||
public function sendPortTestSuccessEvent(port:String, host:String, protocol:String, app:String):void{
|
||||
public function sendPortTestSuccessEvent(port:String, host:String, tunnel:Boolean, app:String):void{
|
||||
var logData:Object = new Object();
|
||||
logData.port = port;
|
||||
logData.server = host;
|
||||
logData.protocol = protocol;
|
||||
logData.tunnel = tunnel;
|
||||
logData.app = app;
|
||||
logData.userId = meetingInfo.userId;
|
||||
logData.username = meetingInfo.username;
|
||||
@ -145,17 +140,17 @@ package org.bigbluebutton.main.model.modules
|
||||
var portEvent:PortTestEvent = new PortTestEvent(PortTestEvent.PORT_TEST_SUCCESS);
|
||||
portEvent.port = port;
|
||||
portEvent.hostname = host;
|
||||
portEvent.protocol = protocol;
|
||||
portEvent.tunnel = tunnel;
|
||||
portEvent.app = app;
|
||||
dispatcher.dispatchEvent(portEvent);
|
||||
|
||||
}
|
||||
|
||||
public function sendPortTestFailedEvent(port:String, host:String, protocol:String, app:String):void{
|
||||
public function sendPortTestFailedEvent(port:String, host:String, tunnel:Boolean, app:String):void{
|
||||
var portFailEvent:PortTestEvent = new PortTestEvent(PortTestEvent.PORT_TEST_FAILED);
|
||||
portFailEvent.port = port;
|
||||
portFailEvent.hostname = host;
|
||||
portFailEvent.protocol = protocol;
|
||||
portFailEvent.tunnel = tunnel;
|
||||
portFailEvent.app = app;
|
||||
dispatcher.dispatchEvent(portFailEvent);
|
||||
|
||||
|
@ -42,8 +42,9 @@ package org.bigbluebutton.main.model.modules
|
||||
return _user.username;
|
||||
}
|
||||
|
||||
public function portTestSuccess(protocol:String):void {
|
||||
modulesManager.useProtocol(protocol);
|
||||
public function portTestSuccess(tunnel:Boolean):void {
|
||||
LOGGER.debug("Successfully tested connection to server. isTunnelling=" + tunnel);
|
||||
modulesManager.useProtocol(tunnel);
|
||||
modulesManager.startUserServices();
|
||||
}
|
||||
|
||||
@ -72,12 +73,16 @@ package org.bigbluebutton.main.model.modules
|
||||
}
|
||||
|
||||
public function testRTMP():void{
|
||||
portTestProxy.connect("RTMP", getPortTestHost(), "1935", getPortTestApplication(), getPortTestTimeout());
|
||||
portTestProxy.connect(false /*"RTMP"*/, getPortTestHost(), "1935", getPortTestApplication(), getPortTestTimeout());
|
||||
}
|
||||
|
||||
public function testRTMPT(protocol:String):void{
|
||||
if (protocol == "RTMP") portTestProxy.connect("RTMPT", getPortTestHost(), "", getPortTestApplication(), getPortTestTimeout());
|
||||
else modulesDispatcher.sendTunnelingFailedEvent(getPortTestHost(), getPortTestApplication());
|
||||
public function testRTMPT(tunnel:Boolean):void{
|
||||
if (! tunnel) {
|
||||
// Try to test using rtmpt as rtmp failed.
|
||||
portTestProxy.connect(true /*"RTMPT"*/, getPortTestHost(), "", getPortTestApplication(), getPortTestTimeout());
|
||||
} else {
|
||||
modulesDispatcher.sendTunnelingFailedEvent(getPortTestHost(), getPortTestApplication());
|
||||
}
|
||||
}
|
||||
|
||||
public function loadAllModules(params:ConferenceParameters):void{
|
||||
|
@ -389,6 +389,7 @@ package org.bigbluebutton.main.model.users
|
||||
n.disableMyMic = user.disableMyMic;
|
||||
n.disableMyPrivateChat = user.disableMyPrivateChat;
|
||||
n.disableMyPublicChat = user.disableMyPublicChat;
|
||||
n.breakoutRooms = user.breakoutRooms.concat(); // concatenate an array with nothing to deliver a new array.
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -633,6 +633,16 @@ package org.bigbluebutton.main.model.users {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getBreakoutRoomInListen() : BreakoutRoom {
|
||||
for (var i:int = 0; i < breakoutRooms.length; i++) {
|
||||
var br:BreakoutRoom = BreakoutRoom(breakoutRooms.getItemAt(i));
|
||||
if (br.listenStatus == BreakoutRoom.SELF) {
|
||||
return br;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function resetBreakoutRooms():void {
|
||||
for (var i:int = 0; i < breakoutRooms.length; i++) {
|
||||
|
@ -18,8 +18,7 @@
|
||||
*/
|
||||
package org.bigbluebutton.main.model.users
|
||||
{
|
||||
import com.asfusion.mate.events.Dispatcher;
|
||||
|
||||
import com.asfusion.mate.events.Dispatcher;
|
||||
import flash.events.AsyncErrorEvent;
|
||||
import flash.events.IOErrorEvent;
|
||||
import flash.events.NetStatusEvent;
|
||||
@ -30,6 +29,7 @@ package org.bigbluebutton.main.model.users
|
||||
import flash.utils.Timer;
|
||||
import org.as3commons.logging.api.ILogger;
|
||||
import org.as3commons.logging.api.getClassLogger;
|
||||
import org.bigbluebutton.core.BBB;
|
||||
import org.bigbluebutton.core.UsersUtil;
|
||||
import org.bigbluebutton.core.managers.ReconnectionManager;
|
||||
import org.bigbluebutton.core.services.BandwidthMonitor;
|
||||
@ -39,7 +39,7 @@ package org.bigbluebutton.main.model.users
|
||||
import org.bigbluebutton.main.model.ConferenceParameters;
|
||||
import org.bigbluebutton.main.model.users.events.ConnectionFailedEvent;
|
||||
import org.bigbluebutton.main.model.users.events.UsersConnectionEvent;
|
||||
|
||||
|
||||
public class NetConnectionDelegate
|
||||
{
|
||||
private static const LOGGER:ILogger = getClassLogger(NetConnectionDelegate);
|
||||
@ -50,17 +50,8 @@ package org.bigbluebutton.main.model.users
|
||||
|
||||
private var _userid:Number = -1;
|
||||
private var _role:String = "unknown";
|
||||
private var _applicationURI:String;
|
||||
private var _conferenceParameters:ConferenceParameters;
|
||||
|
||||
// These two are just placeholders. We'll get this from the server later and
|
||||
// then pass to other modules.
|
||||
private var _authToken:String = "AUTHORIZED";
|
||||
private var _room:String;
|
||||
private var tried_tunneling:Boolean = false;
|
||||
private var logoutOnUserCommand:Boolean = false;
|
||||
private var backoff:Number = 2000;
|
||||
|
||||
private var dispatcher:Dispatcher;
|
||||
private var _messageListeners:Array = new Array();
|
||||
|
||||
@ -70,24 +61,10 @@ package org.bigbluebutton.main.model.users
|
||||
|
||||
private var _validateTokenTimer:Timer = null;
|
||||
|
||||
public function NetConnectionDelegate():void
|
||||
{
|
||||
public function NetConnectionDelegate():void {
|
||||
dispatcher = new Dispatcher();
|
||||
|
||||
_netConnection = new NetConnection();
|
||||
_netConnection.proxyType = "best";
|
||||
_netConnection.client = this;
|
||||
_netConnection.addEventListener( NetStatusEvent.NET_STATUS, netStatus );
|
||||
_netConnection.addEventListener( AsyncErrorEvent.ASYNC_ERROR, netASyncError );
|
||||
_netConnection.addEventListener( SecurityErrorEvent.SECURITY_ERROR, netSecurityError );
|
||||
_netConnection.addEventListener( IOErrorEvent.IO_ERROR, netIOError );
|
||||
}
|
||||
|
||||
public function setUri(uri:String):void {
|
||||
_applicationURI = uri;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function get connection():NetConnection {
|
||||
return _netConnection;
|
||||
}
|
||||
@ -136,9 +113,11 @@ package org.bigbluebutton.main.model.users
|
||||
}
|
||||
|
||||
private function validateToken():void {
|
||||
var confParams:ConferenceParameters = BBB.initUserConfigManager().getConfParams();
|
||||
|
||||
var message:Object = new Object();
|
||||
message["userId"] = _conferenceParameters.internalUserID;
|
||||
message["authToken"] = _conferenceParameters.authToken;
|
||||
message["userId"] = confParams.internalUserID;
|
||||
message["authToken"] = confParams.authToken;
|
||||
|
||||
_validateTokenTimer = new Timer(7000, 1);
|
||||
_validateTokenTimer.addEventListener(TimerEvent.TIMER, validataTokenTimerHandler);
|
||||
@ -265,18 +244,39 @@ package org.bigbluebutton.main.model.users
|
||||
* mode: LIVE/PLAYBACK - Live:when used to collaborate, Playback:when being used to playback a recorded conference.
|
||||
* room: Need the room number when playing back a recorded conference. When LIVE, the room is taken from the URI.
|
||||
*/
|
||||
public function connect(params:ConferenceParameters, tunnel:Boolean = false):void {
|
||||
_conferenceParameters = params;
|
||||
public function connect():void {
|
||||
var confParams:ConferenceParameters = BBB.initUserConfigManager().getConfParams();
|
||||
|
||||
tried_tunneling = tunnel;
|
||||
_netConnection = new NetConnection();
|
||||
_netConnection.proxyType = "best";
|
||||
_netConnection.client = this;
|
||||
_netConnection.addEventListener( NetStatusEvent.NET_STATUS, netStatus );
|
||||
_netConnection.addEventListener( AsyncErrorEvent.ASYNC_ERROR, netASyncError );
|
||||
_netConnection.addEventListener( SecurityErrorEvent.SECURITY_ERROR, netSecurityError );
|
||||
_netConnection.addEventListener( IOErrorEvent.IO_ERROR, netIOError );
|
||||
|
||||
try {
|
||||
var uri:String = _applicationURI + "/" + _conferenceParameters.room;
|
||||
|
||||
_netConnection.connect(uri, _conferenceParameters.username, _conferenceParameters.role,
|
||||
_conferenceParameters.room, _conferenceParameters.voicebridge,
|
||||
_conferenceParameters.record, _conferenceParameters.externUserID,
|
||||
_conferenceParameters.internalUserID, _conferenceParameters.muteOnStart, _conferenceParameters.lockSettings);
|
||||
var appURL:String = BBB.getConfigManager().config.application.uri;
|
||||
var pattern:RegExp = /(?P<protocol>.+):\/\/(?P<server>.+)\/(?P<app>.+)/;
|
||||
var result:Array = pattern.exec(appURL);
|
||||
|
||||
var protocol:String = "rtmp";
|
||||
var uri:String = appURL + "/" + confParams.room;
|
||||
|
||||
if (BBB.initConnectionManager().isTunnelling) {
|
||||
uri = "rtmpt://" + result.server + "/" + result.app + "/" + confParams.room;
|
||||
} else {
|
||||
uri = "rtmp://" + result.server + ":1935/" + result.app + "/" + confParams.room;
|
||||
}
|
||||
|
||||
|
||||
LOGGER.debug("BBB Apps URI=" + uri);
|
||||
|
||||
_netConnection.connect(uri, confParams.username, confParams.role,
|
||||
confParams.room, confParams.voicebridge,
|
||||
confParams.record, confParams.externUserID,
|
||||
confParams.internalUserID, confParams.muteOnStart, confParams.lockSettings);
|
||||
|
||||
} catch(e:ArgumentError) {
|
||||
// Invalid parameters.
|
||||
switch (e.errorID) {
|
||||
@ -304,17 +304,6 @@ package org.bigbluebutton.main.model.users
|
||||
handleResult( event );
|
||||
}
|
||||
|
||||
private var _bwMon:BandwidthMonitor = new BandwidthMonitor();
|
||||
|
||||
private function startMonitoringBandwidth():void {
|
||||
LOGGER.info("Start monitoring bandwidth.");
|
||||
var pattern:RegExp = /(?P<protocol>.+):\/\/(?P<server>.+)\/(?P<app>.+)/;
|
||||
var result:Array = pattern.exec(_applicationURI);
|
||||
_bwMon.serverURL = result.server;
|
||||
_bwMon.serverApplication = "video";
|
||||
_bwMon.start();
|
||||
}
|
||||
|
||||
public function handleResult(event:Object):void {
|
||||
var info : Object = event.info;
|
||||
var statusCode : String = info.code;
|
||||
@ -326,29 +315,18 @@ package org.bigbluebutton.main.model.users
|
||||
case "NetConnection.Connect.Success":
|
||||
numNetworkChangeCount = 0;
|
||||
JSLog.debug("Successfully connected to BBB App.", logData);
|
||||
|
||||
validateToken();
|
||||
|
||||
break;
|
||||
|
||||
case "NetConnection.Connect.Failed":
|
||||
if (tried_tunneling) {
|
||||
LOGGER.error(":Connection to viewers application failed...even when tunneling");
|
||||
sendConnectionFailedEvent(ConnectionFailedEvent.CONNECTION_FAILED);
|
||||
} else {
|
||||
disconnect(false);
|
||||
LOGGER.error(":Connection to viewers application failed...try tunneling");
|
||||
var rtmptRetryTimer:Timer = new Timer(1000, 1);
|
||||
rtmptRetryTimer.addEventListener("timer", rtmptRetryTimerHandler);
|
||||
rtmptRetryTimer.start();
|
||||
}
|
||||
sendConnectionFailedEvent(ConnectionFailedEvent.CONNECTION_FAILED);
|
||||
break;
|
||||
|
||||
case "NetConnection.Connect.Closed":
|
||||
logData.message = "NetConnection.Connect.Closed on bbb-apps";
|
||||
LOGGER.info(JSON.stringify(logData));
|
||||
sendConnectionFailedEvent(ConnectionFailedEvent.CONNECTION_CLOSED);
|
||||
|
||||
break;
|
||||
|
||||
case "NetConnection.Connect.InvalidApp":
|
||||
@ -362,7 +340,8 @@ package org.bigbluebutton.main.model.users
|
||||
break;
|
||||
|
||||
case "NetConnection.Connect.Rejected":
|
||||
LOGGER.debug(":Connection to the server rejected. Uri: {0}. Check if the red5 specified in the uri exists and is running", [_applicationURI]);
|
||||
var appURL:String = BBB.getConfigManager().config.application.uri
|
||||
LOGGER.debug(":Connection to the server rejected. Uri: {0}. Check if the red5 specified in the uri exists and is running", [appURL]);
|
||||
sendConnectionFailedEvent(ConnectionFailedEvent.CONNECTION_REJECTED);
|
||||
break;
|
||||
|
||||
@ -381,11 +360,6 @@ package org.bigbluebutton.main.model.users
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function rtmptRetryTimerHandler(event:TimerEvent):void {
|
||||
LOGGER.debug("rtmptRetryTimerHandler: {0}", [event]);
|
||||
connect(_conferenceParameters, true);
|
||||
}
|
||||
|
||||
protected function netSecurityError(event: SecurityErrorEvent):void {
|
||||
LOGGER.error("Security error - {0}", [event.text]);
|
||||
@ -402,44 +376,50 @@ package org.bigbluebutton.main.model.users
|
||||
sendConnectionFailedEvent(ConnectionFailedEvent.UNKNOWN_REASON);
|
||||
}
|
||||
|
||||
private function sendConnectionFailedEvent(reason:String):void{
|
||||
var logData:Object = new Object();
|
||||
private function sendConnectionFailedEvent(reason:String):void{
|
||||
var logData:Object = new Object();
|
||||
|
||||
if (this.logoutOnUserCommand) {
|
||||
logData.reason = "User requested.";
|
||||
logData.user = UsersUtil.getUserData();
|
||||
JSLog.debug("User logged out from BBB App.", logData);
|
||||
sendUserLoggedOutEvent();
|
||||
} else if (reason == ConnectionFailedEvent.CONNECTION_CLOSED && !UsersUtil.isUserEjected()) {
|
||||
// do not try to reconnect if the connection failed is different than CONNECTION_CLOSED
|
||||
logData.reason = reason;
|
||||
logData.user = UsersUtil.getUserData();
|
||||
JSLog.warn("User disconnected from BBB App.", logData);
|
||||
if (this.logoutOnUserCommand) {
|
||||
logData.reason = "User requested.";
|
||||
logData.user = UsersUtil.getUserData();
|
||||
logData.message = "User logged out from BBB App.";
|
||||
LOGGER.info(JSON.stringify(logData));
|
||||
|
||||
sendUserLoggedOutEvent();
|
||||
} else if (reason == ConnectionFailedEvent.CONNECTION_CLOSED && !UsersUtil.isUserEjected()) {
|
||||
// do not try to reconnect if the connection failed is different than CONNECTION_CLOSED
|
||||
logData.reason = reason;
|
||||
logData.user = UsersUtil.getUserData();
|
||||
logData.message = "User disconnected from BBB App.";
|
||||
LOGGER.info(JSON.stringify(logData));
|
||||
|
||||
if (reconnecting) {
|
||||
var attemptFailedEvent:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_CONNECTION_ATTEMPT_FAILED_EVENT);
|
||||
attemptFailedEvent.payload.type = ReconnectionManager.BIGBLUEBUTTON_CONNECTION;
|
||||
dispatcher.dispatchEvent(attemptFailedEvent);
|
||||
} else {
|
||||
reconnecting = true;
|
||||
authenticated = false;
|
||||
if (reconnecting) {
|
||||
var attemptFailedEvent:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_CONNECTION_ATTEMPT_FAILED_EVENT);
|
||||
attemptFailedEvent.payload.type = ReconnectionManager.BIGBLUEBUTTON_CONNECTION;
|
||||
dispatcher.dispatchEvent(attemptFailedEvent);
|
||||
} else {
|
||||
reconnecting = true;
|
||||
authenticated = false;
|
||||
|
||||
var disconnectedEvent:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_DISCONNECTED_EVENT);
|
||||
disconnectedEvent.payload.type = ReconnectionManager.BIGBLUEBUTTON_CONNECTION;
|
||||
disconnectedEvent.payload.callback = connect;
|
||||
disconnectedEvent.payload.callbackParameters = new Array(_conferenceParameters, tried_tunneling);
|
||||
dispatcher.dispatchEvent(disconnectedEvent);
|
||||
var disconnectedEvent:BBBEvent = new BBBEvent(BBBEvent.RECONNECT_DISCONNECTED_EVENT);
|
||||
disconnectedEvent.payload.type = ReconnectionManager.BIGBLUEBUTTON_CONNECTION;
|
||||
disconnectedEvent.payload.callback = connect;
|
||||
disconnectedEvent.payload.callbackParameters = new Array();
|
||||
dispatcher.dispatchEvent(disconnectedEvent);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (UsersUtil.isUserEjected()) {
|
||||
logData.user = UsersUtil.getUserData();
|
||||
logData.message = "User has been ejected from meeting.";
|
||||
LOGGER.info(JSON.stringify(logData));
|
||||
reason = ConnectionFailedEvent.USER_EJECTED_FROM_MEETING;
|
||||
}
|
||||
LOGGER.debug("Connection failed event - " + reason);
|
||||
var e:ConnectionFailedEvent = new ConnectionFailedEvent(reason);
|
||||
dispatcher.dispatchEvent(e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (UsersUtil.isUserEjected()) {
|
||||
LOGGER.debug("User has been ejected from meeting.");
|
||||
reason = ConnectionFailedEvent.USER_EJECTED_FROM_MEETING;
|
||||
}
|
||||
LOGGER.debug("Connection failed event - " + reason);
|
||||
var e:ConnectionFailedEvent = new ConnectionFailedEvent(reason);
|
||||
dispatcher.dispatchEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
private function sendUserLoggedOutEvent():void{
|
||||
var e:ConnectionFailedEvent = new ConnectionFailedEvent(ConnectionFailedEvent.USER_LOGGED_OUT);
|
||||
|
@ -18,11 +18,9 @@
|
||||
*/
|
||||
package org.bigbluebutton.main.model.users
|
||||
{
|
||||
import com.asfusion.mate.events.Dispatcher;
|
||||
|
||||
import com.asfusion.mate.events.Dispatcher;
|
||||
import flash.external.ExternalInterface;
|
||||
import flash.net.NetConnection;
|
||||
|
||||
import flash.net.NetConnection;
|
||||
import mx.collections.ArrayCollection;
|
||||
|
||||
import org.as3commons.logging.api.ILogger;
|
||||
@ -67,14 +65,10 @@ package org.bigbluebutton.main.model.users
|
||||
dispatcher = new Dispatcher();
|
||||
}
|
||||
|
||||
public function startService(e:UserServicesEvent):void {
|
||||
applicationURI = e.applicationURI;
|
||||
hostURI = e.hostURI;
|
||||
BBB.initConnectionManager().isTunnelling = e.isTunnelling;
|
||||
|
||||
public function startService(e:UserServicesEvent):void {
|
||||
joinService = new JoinService();
|
||||
joinService.addJoinResultListener(joinListener);
|
||||
joinService.load(e.hostURI);
|
||||
joinService.load(BBB.getConfigManager().config.application.host);
|
||||
}
|
||||
|
||||
private function joinListener(success:Boolean, result:Object):void {
|
||||
@ -110,7 +104,7 @@ package org.bigbluebutton.main.model.users
|
||||
_conferenceParameters.username = result.username;
|
||||
_conferenceParameters.role = result.role;
|
||||
_conferenceParameters.room = result.room;
|
||||
_conferenceParameters.authToken = result.authToken;
|
||||
_conferenceParameters.authToken = result.authToken;
|
||||
_conferenceParameters.webvoiceconf = result.webvoiceconf;
|
||||
_conferenceParameters.voicebridge = result.voicebridge;
|
||||
_conferenceParameters.welcome = result.welcome;
|
||||
@ -148,8 +142,7 @@ package org.bigbluebutton.main.model.users
|
||||
|
||||
private function connect():void{
|
||||
_connectionManager = BBB.initConnectionManager();
|
||||
_connectionManager.setUri(applicationURI);
|
||||
_connectionManager.connect(_conferenceParameters);
|
||||
_connectionManager.connect();
|
||||
}
|
||||
|
||||
public function logoutUser():void {
|
||||
@ -210,7 +203,7 @@ package org.bigbluebutton.main.model.users
|
||||
}
|
||||
|
||||
public function requestBreakoutJoinUrl(e:BreakoutRoomEvent):void{
|
||||
sender.requestBreakoutJoinUrl(_conferenceParameters.meetingID, e.breakoutId, _conferenceParameters.userid);
|
||||
sender.requestBreakoutJoinUrl(_conferenceParameters.meetingID, e.breakoutId, e.userId);
|
||||
}
|
||||
|
||||
public function listenInOnBreakout(e:BreakoutRoomEvent):void {
|
||||
|
@ -26,7 +26,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
x="168" y="86" layout="vertical" width="400" height="110" horizontalAlign="center">
|
||||
<mx:Script>
|
||||
<![CDATA[
|
||||
import mx.core.FlexGlobals;
|
||||
import flash.net.navigateToURL;
|
||||
|
||||
import mx.managers.PopUpManager;
|
||||
|
||||
import org.as3commons.logging.api.ILogger;
|
||||
@ -35,52 +36,57 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
import org.bigbluebutton.core.managers.UserManager;
|
||||
import org.bigbluebutton.main.model.users.events.ConnectionFailedEvent;
|
||||
import org.bigbluebutton.util.i18n.ResourceUtil;
|
||||
|
||||
private static const LOGGER:ILogger = getClassLogger(LoggedOutWindow);
|
||||
|
||||
[Bindable] private var message:String = "You have logged out of the conference";
|
||||
|
||||
private static const LOGGER:ILogger = getClassLogger(LoggedOutWindow);
|
||||
|
||||
[Bindable]
|
||||
private var message:String;
|
||||
|
||||
private var urlLoader:URLLoader;
|
||||
|
||||
|
||||
private function init():void {
|
||||
addEventListener(Event.CLOSE, onUserLoggedOutWindowClose);
|
||||
}
|
||||
|
||||
private function redirect():void {
|
||||
private function callSignOut():void {
|
||||
var logoutURL:String = BBB.getSignoutURL();
|
||||
var request:URLRequest = new URLRequest(logoutURL);
|
||||
LOGGER.debug("Log out url: " + logoutURL);
|
||||
request.method = URLRequestMethod.GET;
|
||||
urlLoader = new URLLoader();
|
||||
// If the redirect value is set to false handleComplete will be triggered
|
||||
urlLoader.addEventListener(Event.COMPLETE, handleComplete);
|
||||
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, handleRedirectError);
|
||||
urlLoader.load(request);
|
||||
}
|
||||
|
||||
private function exitApplication():void {
|
||||
if (!UserManager.getInstance().getConference().isBreakout) {
|
||||
var logoutURL:String = BBB.getLogoutURL();
|
||||
var request:URLRequest = new URLRequest(logoutURL);
|
||||
LOGGER.debug("Log out url: " + logoutURL);
|
||||
request.method = URLRequestMethod.GET;
|
||||
urlLoader = new URLLoader();
|
||||
urlLoader.addEventListener(Event.COMPLETE, handleComplete);
|
||||
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, handleRedirectError);
|
||||
urlLoader.load(request);
|
||||
navigateToURL(new URLRequest(BBB.getLogoutURL()), "_self");
|
||||
} else {
|
||||
ExternalInterface.call("window.close");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function handleComplete(e:Event):void {
|
||||
LOGGER.debug("Client URL=[{0}]", [FlexGlobals.topLevelApplication.url]);
|
||||
var logoutURL:String = BBB.getLogoutURL();
|
||||
var request:URLRequest = new URLRequest(logoutURL);
|
||||
LOGGER.debug("Logging out to: {0}", [logoutURL]);
|
||||
navigateToURL(request, '_self');
|
||||
|
||||
PopUpManager.removePopUp(this);
|
||||
PopUpManager.removePopUp(this);
|
||||
exitApplication();
|
||||
}
|
||||
|
||||
|
||||
private function handleRedirectError(e:IOErrorEvent):void {
|
||||
LOGGER.error("Log out redirection returned with error.");
|
||||
PopUpManager.removePopUp(this);
|
||||
exitApplication();
|
||||
}
|
||||
|
||||
private function onUserLoggedOutWindowClose(e:Event):void {
|
||||
LOGGER.debug("Closing UserLoggedOutWindow");
|
||||
PopUpManager.removePopUp(this);
|
||||
}
|
||||
|
||||
private function onUserLoggedOutWindowClose(e:Event):void {
|
||||
PopUpManager.removePopUp(this);
|
||||
}
|
||||
|
||||
public function setReason(reason:String):void{
|
||||
switch(reason){
|
||||
public function setReason(reason:String):void {
|
||||
LOGGER.debug("Received ConnectionFailedEvent with reason: " + reason);
|
||||
switch (reason) {
|
||||
case ConnectionFailedEvent.APP_SHUTDOWN:
|
||||
message = ResourceUtil.getInstance().getString('bbb.logout.appshutdown');
|
||||
break;
|
||||
@ -102,19 +108,21 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
case ConnectionFailedEvent.UNKNOWN_REASON:
|
||||
message = ResourceUtil.getInstance().getString('bbb.logout.unknown');
|
||||
break;
|
||||
case ConnectionFailedEvent.USER_EJECTED_FROM_MEETING:
|
||||
message = ResourceUtil.getInstance().getString('bbb.logout.ejectedFromMeeting');
|
||||
break;
|
||||
case ConnectionFailedEvent.USER_EJECTED_FROM_MEETING:
|
||||
message = ResourceUtil.getInstance().getString('bbb.logout.ejectedFromMeeting');
|
||||
break;
|
||||
case ConnectionFailedEvent.USER_LOGGED_OUT:
|
||||
message = ResourceUtil.getInstance().getString('bbb.logout.usercommand');
|
||||
redirect(); // we know that the disconnect was requested so automatically redirect
|
||||
break;
|
||||
}
|
||||
if (message && UserManager.getInstance().getConference().isBreakout) {
|
||||
message += "\n" + ResourceUtil.getInstance().getString('bbb.logour.breakoutRoomClose');
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</mx:Script>
|
||||
<mx:VBox width="100%" height="100%" horizontalAlign="center">
|
||||
<mx:Text text="{message}"/>
|
||||
<mx:Button id="okBtn" label="{ResourceUtil.getInstance().getString('bbb.logout.button.label')}" click="redirect()"/>
|
||||
<mx:Text text="{message}" textAlign="center"/>
|
||||
<mx:Button id="okBtn" label="{ResourceUtil.getInstance().getString('bbb.logout.button.label')}" click="callSignOut()"/>
|
||||
</mx:VBox>
|
||||
</mx:TitleWindow>
|
||||
|
@ -624,9 +624,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
ls.y = point1.y - (ls.height/2);
|
||||
}
|
||||
|
||||
private function openBreakoutRoomsWindow(e:Event = null):void {
|
||||
private function openBreakoutRoomsWindow(e:BreakoutRoomEvent):void {
|
||||
var popUp:IFlexDisplayObject = PopUpManager.createPopUp(mdiCanvas, BreakoutRoomSettings, true);
|
||||
PopUpManager.centerPopUp(popUp);
|
||||
BreakoutRoomSettings(popUp).initCreateBreakoutRooms(e.joinMode);
|
||||
}
|
||||
|
||||
private function onFooterLinkClicked(e:TextEvent):void{
|
||||
|
@ -94,6 +94,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
messages.push(obj);
|
||||
showNotification();
|
||||
LOGGER.warn("ClientNotification:" + e.title + " " + e.message);
|
||||
}
|
||||
|
||||
private function showNotification():void {
|
||||
|
@ -99,13 +99,17 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
private function yesButtonClicked():void {
|
||||
userClosed = true;
|
||||
LOGGER.debug("Echo test passed.");
|
||||
|
||||
|
||||
var logData:Object = new Object();
|
||||
logData.reason = "User requested.";
|
||||
logData.user = UsersUtil.getUserData();
|
||||
logData.message = "WebRtc Echo test passed.";
|
||||
|
||||
JSLog.info("WebRtc Echo test passed.", logData);
|
||||
|
||||
|
||||
LOGGER.info(JSON.stringify(logData));
|
||||
|
||||
setCurrentState("connecting");
|
||||
lblConnectMessage.text = lblConnectMessageMock.text = ResourceUtil.getInstance().getString('bbb.micSettings.webrtc.endingecho');
|
||||
|
||||
@ -115,7 +119,13 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
private function noButtonClicked():void {
|
||||
userClosed = true;
|
||||
LOGGER.warn("Echo test failed.");
|
||||
|
||||
var logData:Object = new Object();
|
||||
logData.reason = "User requested.";
|
||||
logData.user = UsersUtil.getUserData();
|
||||
logData.message = "WebRtc Echo test failed.";
|
||||
|
||||
LOGGER.info(JSON.stringify(logData));
|
||||
|
||||
var dispatcher:Dispatcher = new Dispatcher();
|
||||
dispatcher.dispatchEvent(new WebRTCEchoTestEvent(WebRTCEchoTestEvent.WEBRTC_ECHO_TEST_NO_AUDIO));
|
||||
@ -123,7 +133,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
}
|
||||
|
||||
private function handleWebRTCEchoTestStartedEvent(e:WebRTCEchoTestStartedEvent):void {
|
||||
webRTCEchoTestStarted();
|
||||
webRTCEchoTestStarted();
|
||||
}
|
||||
|
||||
private function webRTCEchoTestStarted():void {
|
||||
@ -183,7 +193,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
var logData:Object = new Object();
|
||||
logData.reason = "User requested.";
|
||||
logData.user = UsersUtil.getUserData();
|
||||
JSLog.info("WebRtc call started.", logData);
|
||||
logData.message = "WebRtc call started.";
|
||||
|
||||
LOGGER.info(JSON.stringify(logData));
|
||||
|
||||
onCancelClicked();
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ package org.bigbluebutton.modules.caption.events {
|
||||
public var startIndex:int = -1;
|
||||
public var endIndex:int = -1;
|
||||
public var locale:String = "";
|
||||
public var localeCode:String = "";
|
||||
public var text:String = "";
|
||||
|
||||
public function ReceiveEditCaptionHistoryEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
|
||||
|
@ -24,6 +24,7 @@ package org.bigbluebutton.modules.caption.events {
|
||||
public static const RECEIVE_UPDATE_CAPTION_OWNER_EVENT:String = "RECEIVE_UPDATE_CAPTION_OWNER_EVENT";
|
||||
|
||||
public var locale:String = "";
|
||||
public var localeCode:String = "";
|
||||
public var ownerID:String = "";
|
||||
|
||||
public function ReceiveUpdateCaptionOwnerEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
|
||||
|
@ -26,6 +26,7 @@ package org.bigbluebutton.modules.caption.events {
|
||||
public var startIndex:int = -1;
|
||||
public var endIndex:int = -1;
|
||||
public var locale:String = "";
|
||||
public var localeCode:String = "";
|
||||
public var text:String = "";
|
||||
|
||||
public function SendEditCaptionHistoryEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
|
||||
|
@ -24,6 +24,7 @@ package org.bigbluebutton.modules.caption.events {
|
||||
public static const SEND_UPDATE_CAPTION_OWNER_EVENT:String = "SEND_UPDATE_CAPTION_OWNER_EVENT";
|
||||
|
||||
public var locale:String = "";
|
||||
public var localeCode:String = "";
|
||||
public var claim:Boolean = false;
|
||||
|
||||
public function SendUpdateCaptionOwnerEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
|
||||
|
@ -56,11 +56,11 @@ package org.bigbluebutton.modules.caption.managers {
|
||||
}
|
||||
|
||||
public function receiveUpdateCaptionOwner(event:ReceiveUpdateCaptionOwnerEvent):void {
|
||||
_transcripts.updateCaptionOwner(event.locale, event.ownerID);
|
||||
_transcripts.updateCaptionOwner(event.locale, event.localeCode, event.ownerID);
|
||||
}
|
||||
|
||||
public function receiveEditCaptionHistory(event:ReceiveEditCaptionHistoryEvent):void {
|
||||
_transcripts.editCaptionHistory(event.locale, event.startIndex, event.endIndex, event.text);
|
||||
_transcripts.editCaptionHistory(event.locale, event.localeCode, event.startIndex, event.endIndex, event.text);
|
||||
}
|
||||
|
||||
public function openWindow():void {
|
||||
|
@ -31,8 +31,12 @@ package org.bigbluebutton.modules.caption.model {
|
||||
[Bindable]
|
||||
public var locale:String;
|
||||
|
||||
public function Transcript(l:String) {
|
||||
[Bindable]
|
||||
public var localeCode:String;
|
||||
|
||||
public function Transcript(l:String, c:String) {
|
||||
locale = l;
|
||||
localeCode = c;
|
||||
transcript = "";
|
||||
ownerID = "";
|
||||
}
|
||||
|
@ -49,29 +49,29 @@ package org.bigbluebutton.modules.caption.model {
|
||||
var localeClassName:String = flash.utils.getQualifiedClassName(locale);
|
||||
var localeClass:Class = flash.utils.getDefinitionByName(localeClassName) as Class;
|
||||
|
||||
var t:Transcript = findLocale((locale as localeClass).toString());
|
||||
var t:Transcript = findLocale((locale as localeClass).toString(), history[locale][2]);
|
||||
t.ownerID = history[locale][0];
|
||||
t.editHistory(0,0,history[locale][1]);
|
||||
}
|
||||
_historyInited = true;
|
||||
}
|
||||
|
||||
public function updateCaptionOwner(locale:String, ownerID:String):void {
|
||||
findLocale(locale).ownerID = ownerID;
|
||||
public function updateCaptionOwner(locale:String, code:String, ownerID:String):void {
|
||||
findLocale(locale, code).ownerID = ownerID;
|
||||
}
|
||||
|
||||
public function editCaptionHistory(locale:String, startIndex:int, endIndex:int, text:String):void {
|
||||
public function editCaptionHistory(locale:String, code:String, startIndex:int, endIndex:int, text:String):void {
|
||||
if (_historyInited) { // ignore updates until after history has been loaded
|
||||
findLocale(locale).editHistory(startIndex, endIndex, text);
|
||||
findLocale(locale, code).editHistory(startIndex, endIndex, text);
|
||||
}
|
||||
}
|
||||
|
||||
public function findLocale(locale:String):Transcript {
|
||||
public function findLocale(locale:String, code:String):Transcript {
|
||||
for each (var t:Transcript in transcriptCollection) {
|
||||
if (t.locale == locale) return t;
|
||||
}
|
||||
|
||||
var newTranscript:Transcript = new Transcript(locale);
|
||||
var newTranscript:Transcript = new Transcript(locale, code);
|
||||
transcriptCollection.addItem(newTranscript);
|
||||
return newTranscript;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ package org.bigbluebutton.modules.caption.services {
|
||||
public function sendUpdateCaptionOwner(e:SendUpdateCaptionOwnerEvent):void {
|
||||
var msg:Object = new Object();
|
||||
msg.locale = e.locale;
|
||||
msg.localeCode = e.localeCode;
|
||||
msg.claim = e.claim;
|
||||
|
||||
sender.sendUpdateCaptionOwner(msg);
|
||||
@ -47,6 +48,7 @@ package org.bigbluebutton.modules.caption.services {
|
||||
msg.startIndex = e.startIndex;
|
||||
msg.endIndex = e.endIndex;
|
||||
msg.locale = e.locale;
|
||||
msg.localeCode = e.localeCode;
|
||||
msg.text = e.text;
|
||||
|
||||
sender.sendEditCaptionHistory(msg);
|
||||
|
@ -65,19 +65,21 @@ package org.bigbluebutton.modules.caption.services {
|
||||
|
||||
var event:ReceiveUpdateCaptionOwnerEvent = new ReceiveUpdateCaptionOwnerEvent(ReceiveUpdateCaptionOwnerEvent.RECEIVE_UPDATE_CAPTION_OWNER_EVENT);
|
||||
event.locale = message.locale;
|
||||
event.localeCode = message.localeCode;
|
||||
event.ownerID = message.owner_id;
|
||||
var dispatcher:Dispatcher = new Dispatcher();
|
||||
dispatcher.dispatchEvent(event);
|
||||
}
|
||||
|
||||
private function editCaptionHistory(message:Object):void {
|
||||
//LOGGER.debug("editCaptionHistory {start_index:" + message.start_index+",end_index:"+message.end_index+",locale:"+message.locale+",text:'"+message.text+"'}");
|
||||
//LOGGER.debug("editCaptionHistory {start_index:" + message.start_index+",end_index:"+message.end_index+",locale:"+message.locale+",locale_code"+message.locale_code+",text:'"+message.text+"'}");
|
||||
//var map:Object = JSON.parse(message);
|
||||
|
||||
var event:ReceiveEditCaptionHistoryEvent = new ReceiveEditCaptionHistoryEvent(ReceiveEditCaptionHistoryEvent.RECEIVE_EDIT_CAPTION_HISTORY);
|
||||
event.startIndex = int(message.start_index);
|
||||
event.endIndex = int(message.end_index);
|
||||
event.locale = message.locale;
|
||||
event.localeCode = message.locale_code;
|
||||
event.text = message.text;
|
||||
var dispatcher:Dispatcher = new Dispatcher();
|
||||
dispatcher.dispatchEvent(event);
|
||||
|
@ -40,6 +40,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
import mx.binding.utils.ChangeWatcher;
|
||||
import mx.collections.ArrayCollection;
|
||||
import mx.controls.Alert;
|
||||
import mx.controls.Button;
|
||||
import mx.events.FlexEvent;
|
||||
import mx.managers.PopUpManager;
|
||||
|
||||
@ -105,8 +106,12 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
if (UserManager.getInstance().getConference().amIModerator()) {
|
||||
transcriptsCollection = new ArrayCollection();
|
||||
for each (var l:String in ResourceUtil.getInstance().localeNames) {
|
||||
transcriptsCollection.addItem({locale: l});
|
||||
|
||||
var names:Array = ResourceUtil.getInstance().localeNames;
|
||||
var codes:Array = ResourceUtil.getInstance().localeCodes;
|
||||
|
||||
for (var i:int=0; i<names.length; i++) {
|
||||
transcriptsCollection.addItem({locale: names[i], localeCode: codes[i]});
|
||||
}
|
||||
} else {
|
||||
transcriptsCollection = t.transcriptCollection;
|
||||
@ -122,7 +127,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
private function optionChange(type:int, val:Object):void {
|
||||
switch (type) {
|
||||
case OptionENUM.LOCALE:
|
||||
onLocaleChange(String(val));
|
||||
onLocaleChange(val);
|
||||
break;
|
||||
case OptionENUM.SIZE:
|
||||
textTab.setFontSize(int(val));
|
||||
@ -139,8 +144,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
}
|
||||
}
|
||||
|
||||
private function onLocaleChange(locale:String):void {
|
||||
currentTranscript = transcriptsObject.findLocale(locale);
|
||||
private function onLocaleChange(item:Object):void {
|
||||
currentTranscript = transcriptsObject.findLocale(item.locale, item.localeCode);
|
||||
|
||||
optionsTab.setCurrentTranscript(currentTranscript);
|
||||
textTab.setCurrentTranscript(currentTranscript);
|
||||
@ -157,6 +162,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
if (!captionTabs.contains(textTab)) {
|
||||
addTextTab();
|
||||
}
|
||||
|
||||
var tab:Button = captionTabs.getTabAt(0);
|
||||
if (tab != null) {
|
||||
tab.setStyle("fillColors", new Array(0xFFAE00, 0xD3800A));
|
||||
}
|
||||
}
|
||||
|
||||
private function onTranscriptOwnerIDChange(o:Object):void {
|
||||
@ -190,6 +200,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
captionTabs.addChildAt(textTab, 0);
|
||||
}
|
||||
|
||||
private function onTabChange():void {
|
||||
var tab:Button = captionTabs.getTabAt(captionTabs.selectedIndex);
|
||||
tab.setStyle("fillColors", new Array(0xFFFFFF, 0xCCCCCC));
|
||||
}
|
||||
|
||||
private function localeChanged(e:Event):void{
|
||||
resourcesChanged();
|
||||
}
|
||||
@ -224,6 +239,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
<mx:Box width="100%" height="100%" horizontalAlign="left">
|
||||
<containers:SuperTabNavigator id="captionTabs"
|
||||
width="100%" height="100%" minTabWidth="20"
|
||||
dragEnabled="false" popUpButtonPolicy="off" />
|
||||
dragEnabled="false" popUpButtonPolicy="off"
|
||||
change="onTabChange()"/>
|
||||
</mx:Box>
|
||||
</CustomMdiWindow>
|
||||
|