Merge remote-tracking branch 'upstream/master' into merge-webrtc-screenshare-2
Conflicts: bigbluebutton-client/resources/config.xml.template
This commit is contained in:
commit
1116cc0d1e
@ -9,6 +9,8 @@ import org.bigbluebutton.core.bus._
|
||||
import org.bigbluebutton.core.api._
|
||||
import org.bigbluebutton.SystemConfiguration
|
||||
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
object BigBlueButtonActor extends SystemConfiguration {
|
||||
def props(system: ActorSystem,
|
||||
eventBus: IncomingEventBus,
|
||||
@ -121,17 +123,26 @@ class BigBlueButtonActor(val system: ActorSystem,
|
||||
eventBus.publish(BigBlueButtonEvent(m.mProps.parentMeetingID,
|
||||
BreakoutRoomEnded(m.mProps.parentMeetingID, m.mProps.meetingID)))
|
||||
}
|
||||
|
||||
// Eject all users using the client.
|
||||
outGW.send(new EndAndKickAll(msg.meetingID, m.mProps.recorded))
|
||||
outGW.send(new DisconnectAllUsers(msg.meetingID))
|
||||
log.info("Destroyed meetingId={}", msg.meetingID)
|
||||
outGW.send(new MeetingDestroyed(msg.meetingID))
|
||||
// Eject all users from the voice conference
|
||||
outGW.send(new EjectAllVoiceUsers(msg.meetingID, m.mProps.recorded, m.mProps.voiceBridge))
|
||||
|
||||
/** Unsubscribe to meeting and voice events. **/
|
||||
eventBus.unsubscribe(m.actorRef, m.mProps.meetingID)
|
||||
eventBus.unsubscribe(m.actorRef, m.mProps.voiceBridge)
|
||||
// Delay sending DisconnectAllUsers because of RTMPT connection being dropped before UserEject message arrives to the client
|
||||
context.system.scheduler.scheduleOnce(Duration.create(2500, TimeUnit.MILLISECONDS)) {
|
||||
// Disconnect all clients
|
||||
outGW.send(new DisconnectAllUsers(msg.meetingID))
|
||||
log.info("Destroyed meetingId={}", msg.meetingID)
|
||||
outGW.send(new MeetingDestroyed(msg.meetingID))
|
||||
|
||||
// Stop the meeting actor.
|
||||
context.stop(m.actorRef)
|
||||
/** Unsubscribe to meeting and voice events. **/
|
||||
eventBus.unsubscribe(m.actorRef, m.mProps.meetingID)
|
||||
eventBus.unsubscribe(m.actorRef, m.mProps.voiceBridge)
|
||||
|
||||
// Stop the meeting actor.
|
||||
context.stop(m.actorRef)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ class BigBlueButtonInGW(
|
||||
msg.payload.durationInMinutes,
|
||||
msg.payload.autoStartRecording,
|
||||
msg.payload.allowStartStopRecording,
|
||||
msg.payload.webcamsOnlyForModerator,
|
||||
msg.payload.moderatorPassword,
|
||||
msg.payload.viewerPassword,
|
||||
msg.payload.createTime,
|
||||
|
@ -114,20 +114,12 @@ class LiveMeeting(val mProps: MeetingProperties,
|
||||
}
|
||||
|
||||
def handleEndMeeting(msg: EndMeeting) {
|
||||
// Broadcast users the meeting will end
|
||||
outGW.send(new MeetingEnding(msg.meetingId))
|
||||
|
||||
meetingModel.meetingHasEnded
|
||||
|
||||
/**
|
||||
* Check if this meeting has breakout rooms. If so, we also need to end them.
|
||||
*/
|
||||
handleEndAllBreakoutRooms(new EndAllBreakoutRooms(msg.meetingId))
|
||||
|
||||
outGW.send(new MeetingEnded(msg.meetingId, mProps.recorded, mProps.voiceBridge))
|
||||
// Delay sending DisconnectAllUsers because of RTMPT connection being dropped before UserEject message arrives to the client
|
||||
import context.dispatcher
|
||||
context.system.scheduler.scheduleOnce(Duration.create(2500, TimeUnit.MILLISECONDS)) {
|
||||
log.info("Sending delayed DisconnectUser. meetingId={}", mProps.meetingID)
|
||||
outGW.send(new DisconnectAllUsers(msg.meetingId))
|
||||
}
|
||||
}
|
||||
|
||||
def handleAllowUserToShareDesktop(msg: AllowUserToShareDesktop): Unit = {
|
||||
|
@ -6,8 +6,8 @@ import java.util.concurrent.TimeUnit
|
||||
case object StopMeetingActor
|
||||
case class MeetingProperties(meetingID: String, externalMeetingID: String, parentMeetingID: String, meetingName: String,
|
||||
recorded: Boolean, voiceBridge: String, deskshareBridge: String, duration: Int,
|
||||
autoStartRecording: Boolean, allowStartStopRecording: Boolean, moderatorPass: String,
|
||||
viewerPass: String, createTime: Long, createDate: String,
|
||||
autoStartRecording: Boolean, allowStartStopRecording: Boolean, webcamsOnlyForModerator: Boolean,
|
||||
moderatorPass: String, viewerPass: String, createTime: Long, createDate: String,
|
||||
red5DeskShareIP: String, red5DeskShareApp: String, isBreakout: Boolean, sequence: Int)
|
||||
|
||||
case class MeetingExtensionProp(maxExtensions: Int = 2, numExtensions: Int = 0, extendByMinutes: Int = 20,
|
||||
|
@ -54,6 +54,7 @@ class MessageSenderActor(val service: MessageSender)
|
||||
case msg: VoiceRecordingStopped => handleVoiceRecordingStopped(msg)
|
||||
case msg: RecordingStatusChanged => handleRecordingStatusChanged(msg)
|
||||
case msg: GetRecordingStatusReply => handleGetRecordingStatusReply(msg)
|
||||
case msg: MeetingEnding => handleMeetingEnding(msg)
|
||||
case msg: MeetingEnded => handleMeetingEnded(msg)
|
||||
case msg: MeetingHasEnded => handleMeetingHasEnded(msg)
|
||||
case msg: MeetingDestroyed => handleMeetingDestroyed(msg)
|
||||
@ -221,7 +222,12 @@ class MessageSenderActor(val service: MessageSender)
|
||||
service.send(MessagingConstants.FROM_MEETING_CHANNEL, json)
|
||||
|
||||
val json2 = UsersMessageToJsonConverter.meetingEnded(msg)
|
||||
service.send(MessagingConstants.FROM_MEETING_CHANNEL, json2)
|
||||
service.send(MessagingConstants.FROM_USERS_CHANNEL, json2)
|
||||
}
|
||||
|
||||
private def handleMeetingEnding(msg: MeetingEnding) {
|
||||
val json = MeetingMessageToJsonConverter.meetingEndingToJson(msg)
|
||||
service.send(MessagingConstants.FROM_MEETING_CHANNEL, json)
|
||||
}
|
||||
|
||||
private def handleStartRecording(msg: StartRecording) {
|
||||
@ -265,7 +271,7 @@ class MessageSenderActor(val service: MessageSender)
|
||||
service.send(MessagingConstants.FROM_MEETING_CHANNEL, json)
|
||||
|
||||
val json2 = UsersMessageToJsonConverter.meetingHasEnded(msg)
|
||||
service.send(MessagingConstants.FROM_MEETING_CHANNEL, json2)
|
||||
service.send(MessagingConstants.FROM_USERS_CHANNEL, json2)
|
||||
}
|
||||
|
||||
private def handleGetAllMeetingsReply(msg: GetAllMeetingsReply) {
|
||||
|
@ -87,6 +87,7 @@ object MessageNames {
|
||||
val VOICE_RECORDING_STOPPED = "voice_recording_stopped_message"
|
||||
val RECORDING_STATUS_CHANGED = "recording_status_changed_message"
|
||||
val GET_RECORDING_STATUS_REPLY = "get_recording_status_reply"
|
||||
val MEETING_ENDING = "meeting_ending_message"
|
||||
val MEETING_ENDED = "meeting_ended_message"
|
||||
val MEETING_HAS_ENDED = "meeting_has_ended_message"
|
||||
val MEETING_STATE = "meeting_state_message"
|
||||
|
@ -17,6 +17,7 @@ case class GetRecordingStatusReply(meetingID: String, recorded: Boolean, userId:
|
||||
case class MeetingCreated(meetingID: String, externalMeetingID: String, parentMeetingID: String, recorded: Boolean, name: String,
|
||||
voiceBridge: String, duration: Int, moderatorPass: String, viewerPass: String, createTime: Long, createDate: String, isBreakout: Boolean) extends IOutMessage
|
||||
case class MeetingMuted(meetingID: String, recorded: Boolean, meetingMuted: Boolean) extends IOutMessage
|
||||
case class MeetingEnding(meetingID: String) extends IOutMessage
|
||||
case class MeetingEnded(meetingID: String, recorded: Boolean, voiceBridge: String) extends IOutMessage
|
||||
case class MeetingState(meetingID: String, recorded: Boolean, userId: String, permissions: Permissions, meetingMuted: Boolean) extends IOutMessage
|
||||
case class MeetingHasEnded(meetingID: String, userId: String) extends IOutMessage
|
||||
|
@ -577,9 +577,8 @@ trait UsersApp {
|
||||
userLeaving foreach (u => outGW.send(new UserLeft(mProps.meetingID, mProps.recorded, u)))
|
||||
}
|
||||
}
|
||||
|
||||
stopRecordingVoiceConference()
|
||||
}
|
||||
stopRecordingVoiceConference()
|
||||
}
|
||||
|
||||
def handleUserMutedInVoiceConfMessage(msg: UserMutedInVoiceConfMessage) {
|
||||
|
@ -52,6 +52,14 @@ object MeetingMessageToJsonConverter {
|
||||
Util.buildJson(header, payload)
|
||||
}
|
||||
|
||||
def meetingEndingToJson(msg: MeetingEnding): String = {
|
||||
val payload = new java.util.HashMap[String, Any]()
|
||||
payload.put(Constants.MEETING_ID, msg.meetingID)
|
||||
|
||||
val header = Util.buildHeader(MessageNames.MEETING_ENDING, None)
|
||||
Util.buildJson(header, payload)
|
||||
}
|
||||
|
||||
def voiceRecordingStartedToJson(msg: VoiceRecordingStarted): String = {
|
||||
val payload = new java.util.HashMap[String, Any]()
|
||||
payload.put(Constants.MEETING_ID, msg.meetingID)
|
||||
|
@ -13,6 +13,7 @@ trait AppsTestFixtures {
|
||||
val durationInMinutes = 10
|
||||
val autoStartRecording = false
|
||||
val allowStartStopRecording = false
|
||||
val webcamsOnlyForModerator = false;
|
||||
val moderatorPassword = "modpass"
|
||||
val viewerPassword = "viewpass"
|
||||
val createTime = System.currentTimeMillis
|
||||
@ -25,7 +26,7 @@ trait AppsTestFixtures {
|
||||
meetingName, record,
|
||||
voiceConfId, deskshareConfId,
|
||||
durationInMinutes,
|
||||
autoStartRecording, allowStartStopRecording,
|
||||
autoStartRecording, allowStartStopRecording, webcamsOnlyForModerator,
|
||||
moderatorPassword, viewerPassword,
|
||||
createTime, createDate, red5DeskShareIP, red5DeskShareApp,
|
||||
isBreakout, sequence)
|
||||
|
@ -234,10 +234,8 @@ public String getJoinURL(String username, String meetingID, String record, Strin
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Create a meeting and return a URL to join it as moderator. This is used for the API demos.
|
||||
// Create a meeting and return a URL to join it as attendee. This is used for the API demos.
|
||||
//
|
||||
// Passed
|
||||
// - username
|
||||
@ -245,19 +243,16 @@ public String getJoinURL(String username, String meetingID, String record, Strin
|
||||
// - record ["true", "false"]
|
||||
// - welcome message (null causes BigBlueButton to use the default welcome message
|
||||
// - metadata (passed through when record="true"
|
||||
// - xml (used for pre-upload of slides)_
|
||||
// - xml (used for pre-upload of slides)
|
||||
// - isModerator [true, false]
|
||||
//
|
||||
// Returned
|
||||
// - valid join URL using the username
|
||||
//
|
||||
// Note this meeting will use username for meetingID
|
||||
//
|
||||
|
||||
// VERSION ADJUSTED TO THE NEEDS OF THE HTML5 CLIENT
|
||||
// -redirect=false //so that we get xml returned instead of being redirected to the meeting
|
||||
// -password=ap //at this stage the html5 client is viewer only (Feb 2015)
|
||||
|
||||
public String getJoinURLHTML5(String username, String meetingID, String record, String welcome, Map<String, String> metadata, String xml) {
|
||||
public String getJoinURLHTML5(String username, String meetingID, String record, String welcome, Map<String, String> metadata, String xml, boolean isModerator) {
|
||||
|
||||
String base_url_create = BigBlueButtonURL + "api/create?";
|
||||
String base_url_join = BigBlueButtonURL + "api/join?";
|
||||
@ -272,6 +267,13 @@ public String getJoinURLHTML5(String username, String meetingID, String record,
|
||||
xml_param = xml;
|
||||
}
|
||||
|
||||
String defaultModeratorPW = "mp";
|
||||
String defaultAttendeePW = "ap";
|
||||
String html5UserPassword = defaultAttendeePW; // default html5 user to attendee
|
||||
if (isModerator) {
|
||||
html5UserPassword = defaultModeratorPW;
|
||||
}
|
||||
|
||||
Random random = new Random();
|
||||
String voiceBridge_param = "&voiceBridge=" + (70000 + random.nextInt(9999));
|
||||
|
||||
@ -290,8 +292,11 @@ public String getJoinURLHTML5(String username, String meetingID, String record,
|
||||
//
|
||||
|
||||
String create_parameters = "name=" + urlEncode(meetingID)
|
||||
+ "&meetingID=" + urlEncode(meetingID) + welcome_param + voiceBridge_param
|
||||
+ "&attendeePW=ap&moderatorPW=mp"
|
||||
+ "&meetingID=" + urlEncode(meetingID)
|
||||
+ welcome_param
|
||||
+ voiceBridge_param
|
||||
+ "&attendeePW=" + defaultAttendeePW
|
||||
+ "&moderatorPW=" + defaultModeratorPW
|
||||
+ "&record=" + record + getMetaData( metadata );
|
||||
|
||||
|
||||
@ -314,8 +319,11 @@ public String getJoinURLHTML5(String username, String meetingID, String record,
|
||||
// Looks good, now return a URL to join that meeting
|
||||
//
|
||||
|
||||
// Note that REDIRECT=FALSE -- we will use the url to extract meetingID, userID, authToken
|
||||
// and will pass them to the joining url for the html5 client (different format)
|
||||
// Also we set PASSWORD=AP FOR ATTENDEE
|
||||
String join_parameters = "meetingID=" + urlEncode(meetingID)
|
||||
+ "&fullName=" + urlEncode(username) + "&redirect=false&password=ap"; //REDIRECT=FALSE (HTML5 CLIENT) PASSWORD=AP FOR ATTENDEE
|
||||
+ "&fullName=" + urlEncode(username) + "&redirect=false&password=" + html5UserPassword;
|
||||
|
||||
return base_url_join + join_parameters + "&checksum="
|
||||
+ checksum("join" + join_parameters + salt);
|
||||
|
@ -1,173 +0,0 @@
|
||||
<!--
|
||||
|
||||
BigBlueButton - http://www.bigbluebutton.org
|
||||
|
||||
Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
|
||||
|
||||
BigBlueButton 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 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, If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Fred Dixon <ffdixon@bigbluebutton.org>
|
||||
|
||||
-->
|
||||
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||
pageEncoding="UTF-8"%>
|
||||
<%
|
||||
request.setCharacterEncoding("UTF-8");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
%>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Record (Matterhorn)</title>
|
||||
<style type="text/css">
|
||||
#formcreate{
|
||||
width:500px;
|
||||
height:500px;
|
||||
}
|
||||
#formcreate ul{
|
||||
list-style:none;
|
||||
}
|
||||
#formcreate li{
|
||||
display:block;
|
||||
width:400px;
|
||||
margin-bottom:5px;
|
||||
}
|
||||
#formcreate label{
|
||||
display:block;
|
||||
float:left;
|
||||
width:150px;
|
||||
text-align:right;
|
||||
}
|
||||
#labdescription{
|
||||
vertical-align:top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<%@ include file="bbb_api.jsp"%>
|
||||
<%@ include file="demo_header.jsp"%>
|
||||
|
||||
<%
|
||||
if (request.getParameterMap().isEmpty()) {
|
||||
//
|
||||
// Assume we want to create a meeting
|
||||
//
|
||||
%>
|
||||
<h2>Record (Matterhorn)</h2>
|
||||
|
||||
<form id="formcreate" name="formcreate" method="get" action="">
|
||||
<fieldset>
|
||||
<legend>Meeting Information</legend>
|
||||
<ul>
|
||||
<li>
|
||||
<label for="confname">Meeting Name:</label>
|
||||
<input id="confname" autofocus required name="confname" type="text" />
|
||||
</li>
|
||||
<li>
|
||||
<label for="username1">Your Name:</label>
|
||||
<input id="username1" required name="username1" type="text" />
|
||||
</li>
|
||||
</ul>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Metadata Details</legend>
|
||||
<ul>
|
||||
<li>
|
||||
<label for="meta_title">Title:</label>
|
||||
<input type="text" id="meta_title" name="meta_title" />
|
||||
</li>
|
||||
<li>
|
||||
<label for="meta_subject">Subject:</label>
|
||||
<input type="text" id="meta_subject" name="meta_subject" />
|
||||
</li>
|
||||
<li>
|
||||
<label id="labdescription" for="meta_description">Description:</label>
|
||||
<textarea id="meta_description" name="meta_description" cols="17" rows="3"></textarea>
|
||||
</li>
|
||||
<li>
|
||||
<label for="meta_creator">Creator:</label>
|
||||
<input type="text" id="meta_creator" name="meta_creator" />
|
||||
</li>
|
||||
<li>
|
||||
<label for="meta_contributor">Contributor:</label>
|
||||
<input type="text" id="meta_contributor" name="meta_contributor" />
|
||||
</li>
|
||||
<li>
|
||||
<label for="meta_language">Language:</label>
|
||||
<input type="text" id="meta_language" name="meta_language" />
|
||||
</li>
|
||||
<li>
|
||||
<label for="meta_identifier">Identifier:</label>
|
||||
<input type="text" id="meta_identifier" name="meta_identifier" />
|
||||
</li>
|
||||
</ul>
|
||||
</fieldset>
|
||||
<input type="submit" value="Create" >
|
||||
<input type="hidden" name="action" value="create" />
|
||||
</form>
|
||||
|
||||
<%
|
||||
} else if (request.getParameter("action").equals("create")) {
|
||||
|
||||
String confname = request.getParameter("confname");
|
||||
String username = request.getParameter("username1");
|
||||
|
||||
//metadata
|
||||
Map<String,String> metadata=new HashMap<String,String>();
|
||||
|
||||
metadata.put("title",request.getParameter("meta_title"));
|
||||
metadata.put("subject",request.getParameter("meta_subject"));
|
||||
metadata.put("description",request.getParameter("meta_description"));
|
||||
metadata.put("creator",request.getParameter("meta_creator"));
|
||||
metadata.put("contributor",request.getParameter("meta_contributor"));
|
||||
metadata.put("language",request.getParameter("meta_language"));
|
||||
metadata.put("identifier",request.getParameter("meta_identifier"));
|
||||
|
||||
//
|
||||
// This is the URL for to join the meeting as moderator
|
||||
//
|
||||
String url = BigBlueButtonURL.replace("bigbluebutton/","demo/");
|
||||
String preUploadPDF = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='presentation'><document url='"+url+"pdfs/matterhorn.pdf'/></module></modules>";
|
||||
String joinURL = getJoinURL(username, confname, "true", null, metadata, preUploadPDF);
|
||||
|
||||
if (joinURL.startsWith("http://") || joinURL.startsWith("https://")) {
|
||||
%>
|
||||
|
||||
<script language="javascript" type="text/javascript">
|
||||
window.location.href="<%=joinURL%>";
|
||||
</script>
|
||||
|
||||
<%
|
||||
} else {
|
||||
%>
|
||||
|
||||
Error: getJoinURL() failed
|
||||
<p/>
|
||||
<%=joinURL %>
|
||||
|
||||
<%
|
||||
}
|
||||
}
|
||||
%>
|
||||
|
||||
<p>
|
||||
See: <a href="http://code.google.com/p/bigbluebutton/wiki/MatterhornIntegration">Matterhorn Integration</a>
|
||||
|
||||
<%@ include file="demo_footer.jsp"%>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -35,9 +35,11 @@ Author: Fred Dixon <ffdixon@bigbluebutton.org>
|
||||
|
||||
<body>
|
||||
|
||||
<p>You must have the BigBlueButton HTML5 client installed to use this API demo.</p>
|
||||
|
||||
<%@ include file="bbb_api.jsp"%>
|
||||
|
||||
<%
|
||||
<%
|
||||
if (request.getParameterMap().isEmpty()) {
|
||||
//
|
||||
// Assume we want to create a meeting
|
||||
@ -47,29 +49,36 @@ if (request.getParameterMap().isEmpty()) {
|
||||
|
||||
<h2>Join Meeting via HTML5 Client</h2>
|
||||
|
||||
<FORM NAME="form1" METHOD="GET">
|
||||
<FORM NAME="form1" METHOD="GET">
|
||||
<table cellpadding="5" cellspacing="5" style="width: 400px; ">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
<td style="text-align: right; ">
|
||||
Full Name:</td>
|
||||
<td style="width: 5px; ">
|
||||
</td>
|
||||
<td style="text-align: left ">
|
||||
<input type="text" autofocus required name="username" /></td>
|
||||
<td> </td>
|
||||
<td style="text-align: right; ">Full Name:</td>
|
||||
<td style="width: 5px; "> </td>
|
||||
<td style="text-align: left "><input type="text" autofocus required name="username" /></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td style="text-align: right; ">Meeting Name:</td>
|
||||
<td style="width: 5px; "> </td>
|
||||
<td style="text-align: left "><input type="text" required name="meetingname" value="Demo Meeting" /></td>
|
||||
<tr>
|
||||
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td style="text-align: right; ">Moderator Role:</td>
|
||||
<td style="width: 5px; "> </td>
|
||||
<td style="text-align: left "><input type=checkbox name=isModerator value="true"></td>
|
||||
<tr>
|
||||
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td><input type="submit" value="Join" /></td>
|
||||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<input type="submit" value="Join" /></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<INPUT TYPE=hidden NAME=action VALUE="create">
|
||||
@ -84,10 +93,10 @@ if (request.getParameterMap().isEmpty()) {
|
||||
//
|
||||
|
||||
String username = request.getParameter("username");
|
||||
String url = BigBlueButtonURL.replace("bigbluebutton/","demo/");
|
||||
// String preUploadPDF = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='presentation'><document url='"+url+"pdfs/sample.pdf'/></module></modules>";
|
||||
String meetingname = request.getParameter("meetingname");
|
||||
boolean isModerator = Boolean.parseBoolean(request.getParameter("isModerator"));
|
||||
|
||||
String joinURL = getJoinURLHTML5(request.getParameter("username"), "Demo Meeting", "false", null, null, null);
|
||||
String joinURL = getJoinURLHTML5(username, meetingname, "false", null, null, null, isModerator);
|
||||
Document doc = null;
|
||||
doc = parseXml(getURL(joinURL));
|
||||
|
||||
|
@ -1,13 +1,12 @@
|
||||
<img src="images/bbb_banner.jpg" /><br>
|
||||
<img src="images/bbb_banner.jpg" /><br>
|
||||
<a href="demo1.jsp">Join</a> |
|
||||
<a href="demo2.jsp">Join Selected</a> |
|
||||
<a href="demo2.jsp">Join Selected</a> |
|
||||
<a href="demo3.jsp">Join Password</a>
|
||||
|
||||
<a href="demo7.jsp">Join & Upload</a> |
|
||||
<a href="demo8.jsp">Join & Upload</a> (URL)
|
||||
|
||||
<a href="demo10.jsp">Record</a> |
|
||||
<a href="demo6.jsp">Record</a> (Matterhorn)
|
||||
<a href="demo10.jsp">Record</a> |
|
||||
|
||||
<a href="create.jsp">Create</a>
|
||||
|
||||
@ -15,12 +14,9 @@
|
||||
|
||||
<a href="demo4.jsp">Activity Monitor</a>
|
||||
|
||||
<a href="demo_mozilla_persona.jsp">Login with Persona</a>
|
||||
|
||||
<a href="demo_openid.jsp">Login with Openid</a>
|
||||
|
||||
<a href="demo11.jsp">Javascript API</a>
|
||||
|
||||
<a href="mobile.jsp">Mobile Demo</a>
|
||||
|
||||
<a href="demoHTML5.jsp">HTML5 Client Demo</a>
|
||||
|
||||
|
@ -1,169 +0,0 @@
|
||||
<!--
|
||||
|
||||
BigBlueButton - http://www.bigbluebutton.org
|
||||
|
||||
Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
|
||||
|
||||
BigBlueButton 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 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, If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Marcos Calderon <mcmarkos86@gmail.com>
|
||||
|
||||
-->
|
||||
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||
pageEncoding="UTF-8"%>
|
||||
<%
|
||||
request.setCharacterEncoding("UTF-8");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
%>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Join Demo Meeting using Mozilla Persona</title>
|
||||
<script src="https://login.persona.org/include.js" type="text/javascript"></script>
|
||||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<%@ include file="bbb_api.jsp"%>
|
||||
<%@ page import="com.google.gson.Gson"%>
|
||||
<%@ page import="com.google.gson.reflect.TypeToken"%>
|
||||
|
||||
<%
|
||||
if (request.getParameterMap().isEmpty()) {
|
||||
//
|
||||
// Assume we want to create a meeting
|
||||
//
|
||||
%>
|
||||
<%@ include file="demo_header.jsp"%>
|
||||
|
||||
<script type="text/javascript">
|
||||
//browserid
|
||||
$(function() {
|
||||
$('#browserid').click(function() {
|
||||
navigator.id.get(gotAssertion);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
function gotAssertion(assertion) {
|
||||
if (assertion) {
|
||||
var assertion_field = document.getElementById("assertion-field");
|
||||
assertion_field.value = assertion;
|
||||
var login_form = document.getElementById("form1");
|
||||
login_form.submit();
|
||||
}
|
||||
}
|
||||
|
||||
function loggedIn(res){
|
||||
alert(res.email);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<h2>Join Demo Meeting using BrowserID (<a href="http://mozilla.org/persona/">Mozilla Persona</a>)</h2>
|
||||
|
||||
|
||||
<FORM id="form1" NAME="form1" METHOD="GET">
|
||||
<table cellpadding="5" cellspacing="5" style="width: 400px; ">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
<td style="text-align: left ">
|
||||
<a href="#" id="browserid" title="Sign-in with BrowserID">
|
||||
<img src="https://browserid.org/i/sign_in_blue.png" alt="Sign in">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<INPUT TYPE=hidden NAME=action VALUE="create">
|
||||
<input type="hidden" name="assertion" id="assertion-field" />
|
||||
</FORM>
|
||||
|
||||
|
||||
<%
|
||||
} else if (request.getParameter("action").equals("create")) {
|
||||
|
||||
//
|
||||
// Got an action=create
|
||||
//
|
||||
|
||||
String url = BigBlueButtonURL.replace("bigbluebutton/","demo/");
|
||||
String joinURL = "";
|
||||
|
||||
try{
|
||||
|
||||
String data = URLEncoder.encode("assertion", "UTF-8") + "=" + URLEncoder.encode(request.getParameter("assertion"), "UTF-8");
|
||||
data += "&" + URLEncoder.encode("audience", "UTF-8") + "=" + URLEncoder.encode(BigBlueButtonURL.replace("/bigbluebutton/",""),"UTF-8");
|
||||
URL urlBrowserID = new URL("https://verifier.login.persona.org/verify");
|
||||
|
||||
|
||||
URLConnection conn = urlBrowserID.openConnection();
|
||||
((HttpURLConnection)conn).setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
conn.setDoOutput(true);
|
||||
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
|
||||
wr.write(data);
|
||||
wr.flush();
|
||||
|
||||
// Get the response
|
||||
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
String jsonResp = "";
|
||||
String line;
|
||||
while ((line = rd.readLine()) != null) {
|
||||
jsonResp += line;
|
||||
}
|
||||
wr.close();
|
||||
rd.close();
|
||||
|
||||
Gson gson = new Gson();
|
||||
HashMap<String,String> map = gson.fromJson(jsonResp, new TypeToken<Map<String, String>>() {}.getType());
|
||||
if(map.get("status").equalsIgnoreCase("okay")){
|
||||
joinURL = getJoinURL(map.get("email"), "Demo Meeting", "false", null, null, null);
|
||||
}
|
||||
}catch(Exception e){
|
||||
|
||||
}
|
||||
|
||||
// String preUploadPDF = "<?xml version='1.0' encoding='UTF-8'?><modules><module name='presentation'><document url='"+url+"pdfs/sample.pdf'/></module></modules>";
|
||||
|
||||
|
||||
if (joinURL.startsWith("http://") || joinURL.startsWith("https://")) {
|
||||
%>
|
||||
|
||||
<script language="javascript" type="text/javascript">
|
||||
window.location.href="<%=joinURL%>";
|
||||
</script>
|
||||
|
||||
<%
|
||||
} else {
|
||||
%>
|
||||
|
||||
Error: getJoinURL() failed
|
||||
<p/>
|
||||
<%=joinURL %>
|
||||
|
||||
<%
|
||||
}
|
||||
}
|
||||
%>
|
||||
|
||||
|
||||
<%@ include file="demo_footer.jsp"%>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,166 +0,0 @@
|
||||
<!--
|
||||
|
||||
BigBlueButton - http://www.bigbluebutton.org
|
||||
|
||||
Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
|
||||
|
||||
BigBlueButton 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 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Author: Jesus Federico <jesus@123it.ca>
|
||||
|
||||
-->
|
||||
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||
pageEncoding="UTF-8"%>
|
||||
<%
|
||||
request.setCharacterEncoding("UTF-8");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
%>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Join Demo Meeting using OpenID</title>
|
||||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
var form = $('#form1');
|
||||
$('#google').click(function() {
|
||||
$("<input>").attr({
|
||||
'type':'hidden',
|
||||
'name':'connect',
|
||||
'value':'google'
|
||||
}).appendTo(form);
|
||||
$('#form1').submit();
|
||||
return false;
|
||||
});
|
||||
$('#yahoo').click(function() {
|
||||
$("<input>").attr({
|
||||
'type':'hidden',
|
||||
'name':'connect',
|
||||
'value':'yahoo'
|
||||
}).appendTo(form);
|
||||
$('#form1').submit();
|
||||
return false;
|
||||
});
|
||||
$('#custom').click(function() {
|
||||
$("<input>").attr({
|
||||
'type':'hidden',
|
||||
'name':'connect',
|
||||
'value':'custom'
|
||||
}).appendTo(form);
|
||||
$('#form1').submit();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<%@ include file="bbb_api.jsp"%>
|
||||
<%@ include file="bbb_jopenid.jsp"%>
|
||||
|
||||
<%
|
||||
String urlPath = request.getRequestURI();
|
||||
String urlHost = new URL(BigBlueButtonURL).getProtocol() + "://" + new URL(BigBlueButtonURL).getAuthority();
|
||||
|
||||
if (request.getParameterMap().isEmpty()) {
|
||||
//
|
||||
// Assume we want to create a meeting
|
||||
//
|
||||
%>
|
||||
<%@ include file="demo_header.jsp"%>
|
||||
|
||||
<h2>Join Demo Meeting using openID</h2>
|
||||
|
||||
<FORM id="form1" NAME="form1" METHOD="GET" ACTION="#">
|
||||
<table cellpadding="5" cellspacing="5" style="width: 400px; ">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td style="text-align: left ">
|
||||
<a href="#" id="yahoo" title="Sign-in with Yahoo OpenID">
|
||||
<img src="images/yahoo.png" alt="Sign in"></br>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<!--
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td style="text-align: left ">
|
||||
<a href="#" id="custom" title="Sign-in with Custom OpenID">
|
||||
<img src="images/openid.png" alt="Sign in"></br>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
</tbody>
|
||||
</table>
|
||||
</FORM>
|
||||
|
||||
<%
|
||||
} else if (request.getParameter("connect")!=null ) {
|
||||
manager.setRealm(urlHost);
|
||||
manager.setReturnTo(urlHost + urlPath);
|
||||
Endpoint endpoint = null;
|
||||
|
||||
if (request.getParameter("connect").equals("google")) {
|
||||
endpoint = manager.lookupEndpoint("Google");
|
||||
|
||||
} else if (request.getParameter("connect").equals("yahoo")) {
|
||||
endpoint = manager.lookupEndpoint("Yahoo");
|
||||
|
||||
} else if (request.getParameter("connect").equals("custom")) {
|
||||
endpoint = manager.lookupEndpoint("Google");
|
||||
//endpoint = manager.lookupEndpoint("Custom");
|
||||
|
||||
}
|
||||
|
||||
Association association = manager.lookupAssociation(endpoint);
|
||||
request.getSession().setAttribute(ATTR_MAC, association.getRawMacKey());
|
||||
request.getSession().setAttribute(ATTR_ALIAS, endpoint.getAlias());
|
||||
String url = manager.getAuthenticationUrl(endpoint, association);
|
||||
response.sendRedirect(url);
|
||||
|
||||
} else if (request.getParameter("openid.ns")!=null && !request.getParameter("openid.ns").equals("")) {
|
||||
|
||||
byte[] mac_key = (byte[]) request.getSession().getAttribute(ATTR_MAC);
|
||||
String alias = (String) request.getSession().getAttribute(ATTR_ALIAS);
|
||||
Authentication authentication = manager.getAuthentication(request, mac_key, alias);
|
||||
String joinURL = getJoinURL(authentication.getFullname(), "Demo Meeting", null, null, null, null );
|
||||
|
||||
if (joinURL.startsWith("http://") || joinURL.startsWith("https://")) {
|
||||
%>
|
||||
|
||||
<script language="javascript" type="text/javascript">
|
||||
window.location.href="<%=joinURL%>";
|
||||
</script>
|
||||
|
||||
<%
|
||||
} else {
|
||||
%>
|
||||
|
||||
Error: getJoinURL() failed
|
||||
<p/>
|
||||
<%=joinURL %>
|
||||
|
||||
<%
|
||||
}
|
||||
}
|
||||
%>
|
||||
|
||||
|
||||
<%@ include file="demo_footer.jsp"%>
|
||||
|
||||
</body>
|
||||
</html>
|
2
bbb-client-check/.gitignore
vendored
2
bbb-client-check/.gitignore
vendored
@ -7,5 +7,3 @@ org.eclipse.ltk.core.refactoring.prefs
|
||||
FlexPrettyPrintCommand.prefs
|
||||
index.template.html
|
||||
conf/config.xml
|
||||
resources/lib/bbb_webrtc_bridge_sip.js
|
||||
resources/lib/sip.js
|
||||
|
@ -103,11 +103,6 @@
|
||||
</target>
|
||||
<target name="Resolve-Dependency"
|
||||
description="Generate HTML wrapper">
|
||||
<copy todir="resources/lib/" >
|
||||
<fileset file="../bigbluebutton-client/resources/prod/lib/bbb_webrtc_bridge_sip.js" />
|
||||
<fileset file="../bigbluebutton-client/resources/prod/lib/sip.js" />
|
||||
</copy>
|
||||
|
||||
<get src="${TEST_IMAGE_URL}" dest="${html.output}/test_image.jpg" skipexisting="true" />
|
||||
<copy file="html-template/index.html"
|
||||
tofile="${html.output}/index.html"/>
|
||||
|
@ -6,10 +6,6 @@
|
||||
<firefoxLatestVersion>FIREFOX_VERSION</firefoxLatestVersion>
|
||||
<downloadFilePath url="test_image.jpg"/>
|
||||
<ports>
|
||||
<port>
|
||||
<name>Port 9123</name>
|
||||
<number>9123</number>
|
||||
</port>
|
||||
</ports>
|
||||
<rtmpapps>
|
||||
<app>
|
||||
@ -17,8 +13,8 @@
|
||||
<uri>rtmp://HOST/bigbluebutton</uri>
|
||||
</app>
|
||||
<app>
|
||||
<name>RTMP deskShare app</name>
|
||||
<uri>rtmp://HOST/deskShare</uri>
|
||||
<name>RTMP screenshare app</name>
|
||||
<uri>rtmp://HOST/screenshare</uri>
|
||||
</app>
|
||||
<app>
|
||||
<name>RTMP video app</name>
|
||||
@ -33,8 +29,8 @@
|
||||
<uri>rtmpt://HOST/bigbluebutton</uri>
|
||||
</app>
|
||||
<app>
|
||||
<name>RTMPT deskShare app</name>
|
||||
<uri>rtmpt://HOST/deskShare</uri>
|
||||
<name>RTMPT screenshare app</name>
|
||||
<uri>rtmpt://HOST/screenshare</uri>
|
||||
</app>
|
||||
<app>
|
||||
<name>RTMPT video app</name>
|
||||
|
44
bbb-client-check/resources/lib/api-bridge.js
Executable file → Normal file
44
bbb-client-check/resources/lib/api-bridge.js
Executable file → Normal file
@ -210,9 +210,11 @@
|
||||
|
||||
webrtc_hangup(function() {
|
||||
console.log("[BBBClientCheck] Handling webRTC hangup callback");
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
if (userAgent) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -224,7 +226,7 @@
|
||||
myRole: "undefined",
|
||||
amIPresenter: "undefined",
|
||||
dialNumber: "undefined",
|
||||
voiceBridge: "undefined",
|
||||
voiceBridge: "",
|
||||
customdata: "undefined"
|
||||
}
|
||||
|
||||
@ -243,7 +245,7 @@
|
||||
|
||||
BBB.webRTCEchoTestStarted = function() {
|
||||
console.log("[BBBClientCheck] Handling webRTCEchoTestStarted");
|
||||
sendWebRTCEchoTestAnswer(true, 'Connected');
|
||||
sendWebRTCEchoTestAnswer(true, 'Success');
|
||||
}
|
||||
|
||||
BBB.webRTCEchoTestConnecting = function() {
|
||||
@ -306,4 +308,36 @@
|
||||
BBB.webRTCMediaFail = function() {
|
||||
console.log("[BBBClientCheck] Handling webRTCMediaFail");
|
||||
}
|
||||
|
||||
BBB.webRTCCallStarted = function(inEchoTest) {
|
||||
console.log("[BBBClientCheck] Handling webRTCCallStarted");
|
||||
BBB.webRTCEchoTestStarted();
|
||||
};
|
||||
|
||||
BBB.webRTCCallConnecting = function(inEchoTest) {
|
||||
console.log("[BBBClientCheck] Handling webRTCCallConnecting");
|
||||
BBB.webRTCEchoTestWebsocketSucceeded();
|
||||
};
|
||||
|
||||
BBB.webRTCCallEnded = function(inEchoTest) {
|
||||
console.log("[BBBClientCheck] Handling webRTCCallEnded");
|
||||
};
|
||||
|
||||
BBB.webRTCCallFailed = function(inEchoTest, errorcode, cause) {
|
||||
console.log("[BBBClientCheck] Handling webRTCCallFailed");
|
||||
BBB.webRTCEchoTestFailed(errorcode);
|
||||
BBB.webRTCEchoTestWebsocketFailed();
|
||||
};
|
||||
|
||||
BBB.webRTCCallWaitingForICE = function(inEchoTest) {
|
||||
console.log("[BBBClientCheck] Handling webRTCCallWaitingForICE");
|
||||
};
|
||||
|
||||
BBB.webRTCCallTransferring = function(inEchoTest) {
|
||||
console.log("[BBBClientCheck] Handling webRTCCallTransferring");
|
||||
};
|
||||
|
||||
BBB.webRTCCallProgressCallback = function(progress) {
|
||||
console.log("[BBBClientCheck] Handling webRTCCallProgressCallback");
|
||||
};
|
||||
}
|
||||
|
545
bbb-client-check/resources/lib/bbb_webrtc_bridge_sip.js
Normal file
545
bbb-client-check/resources/lib/bbb_webrtc_bridge_sip.js
Normal file
@ -0,0 +1,545 @@
|
||||
|
||||
var userID, callerIdName=null, conferenceVoiceBridge, userAgent=null, userMicMedia, userWebcamMedia, currentSession=null, callTimeout, callActive, callICEConnected, iceConnectedTimeout, callFailCounter, callPurposefullyEnded, uaConnected, transferTimeout, iceGatheringTimeout;
|
||||
var inEchoTest = true;
|
||||
var html5StunTurn = {};
|
||||
|
||||
function webRTCCallback(message) {
|
||||
switch (message.status) {
|
||||
case 'failed':
|
||||
if (message.errorcode !== 1004) {
|
||||
message.cause = null;
|
||||
}
|
||||
BBB.webRTCCallFailed(inEchoTest, message.errorcode, message.cause);
|
||||
break;
|
||||
case 'ended':
|
||||
BBB.webRTCCallEnded(inEchoTest);
|
||||
break;
|
||||
case 'started':
|
||||
BBB.webRTCCallStarted(inEchoTest);
|
||||
break;
|
||||
case 'connecting':
|
||||
BBB.webRTCCallConnecting(inEchoTest);
|
||||
break;
|
||||
case 'waitingforice':
|
||||
BBB.webRTCCallWaitingForICE(inEchoTest);
|
||||
break;
|
||||
case 'transferring':
|
||||
BBB.webRTCCallTransferring(inEchoTest);
|
||||
break;
|
||||
case 'mediarequest':
|
||||
BBB.webRTCMediaRequest();
|
||||
break;
|
||||
case 'mediasuccess':
|
||||
BBB.webRTCMediaSuccess();
|
||||
break;
|
||||
case 'mediafail':
|
||||
BBB.webRTCMediaFail();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function callIntoConference(voiceBridge, callback, isListenOnly, stunTurn = null) {
|
||||
// root of the call initiation process from the html5 client
|
||||
// Flash will not pass in the listen only field. For html5 it is optional. Assume NOT listen only if no state passed
|
||||
if (isListenOnly == null) {
|
||||
isListenOnly = false;
|
||||
}
|
||||
|
||||
// if additional stun configuration is passed, store the information
|
||||
if (stunTurn != null) {
|
||||
html5StunTurn['stunServers'] = stunTurn.stun;
|
||||
html5StunTurn['turnServers'] = stunTurn.turn;
|
||||
}
|
||||
|
||||
// reset callerIdName
|
||||
callerIdName = null;
|
||||
if (!callerIdName) {
|
||||
BBB.getMyUserInfo(function(userInfo) {
|
||||
console.log("User info callback [myUserID=" + userInfo.myUserID
|
||||
+ ",myUsername=" + userInfo.myUsername + ",myAvatarURL=" + userInfo.myAvatarURL
|
||||
+ ",myRole=" + userInfo.myRole + ",amIPresenter=" + userInfo.amIPresenter
|
||||
+ ",dialNumber=" + userInfo.dialNumber + ",voiceBridge=" + userInfo.voiceBridge
|
||||
+ ",isListenOnly=" + isListenOnly + "].");
|
||||
userID = userInfo.myUserID;
|
||||
callerIdName = userInfo.myUserID + "-bbbID-" + userInfo.myUsername;
|
||||
if (isListenOnly) {
|
||||
//prepend the callerIdName so it is recognized as a global audio user
|
||||
callerIdName = "GLOBAL_AUDIO_" + callerIdName;
|
||||
}
|
||||
conferenceVoiceBridge = userInfo.voiceBridge
|
||||
if (voiceBridge === "9196") {
|
||||
voiceBridge = voiceBridge + conferenceVoiceBridge;
|
||||
} else {
|
||||
voiceBridge = conferenceVoiceBridge;
|
||||
}
|
||||
console.log(callerIdName);
|
||||
webrtc_call(callerIdName, voiceBridge, callback, isListenOnly);
|
||||
});
|
||||
} else {
|
||||
if (voiceBridge === "9196") {
|
||||
voiceBridge = voiceBridge + conferenceVoiceBridge;
|
||||
} else {
|
||||
voiceBridge = conferenceVoiceBridge;
|
||||
}
|
||||
webrtc_call(callerIdName, voiceBridge, callback, isListenOnly);
|
||||
}
|
||||
}
|
||||
|
||||
function joinWebRTCVoiceConference() {
|
||||
console.log("Joining to the voice conference directly");
|
||||
inEchoTest = false;
|
||||
// set proper callbacks to previously created user agent
|
||||
if(userAgent) {
|
||||
setUserAgentListeners(webRTCCallback);
|
||||
}
|
||||
callIntoConference(conferenceVoiceBridge, webRTCCallback);
|
||||
}
|
||||
|
||||
function leaveWebRTCVoiceConference() {
|
||||
console.log("Leaving the voice conference");
|
||||
|
||||
webrtc_hangup();
|
||||
}
|
||||
|
||||
function startWebRTCAudioTest(){
|
||||
console.log("Joining the audio test first");
|
||||
inEchoTest = true;
|
||||
callIntoConference("9196", webRTCCallback);
|
||||
}
|
||||
|
||||
function stopWebRTCAudioTest(){
|
||||
console.log("Stopping webrtc audio test");
|
||||
|
||||
webrtc_hangup();
|
||||
}
|
||||
|
||||
function stopWebRTCAudioTestJoinConference(){
|
||||
console.log("Transferring from audio test to conference");
|
||||
|
||||
webRTCCallback({'status': 'transferring'});
|
||||
|
||||
transferTimeout = setTimeout( function() {
|
||||
console.log("Call transfer failed. No response after 3 seconds");
|
||||
webRTCCallback({'status': 'failed', 'errorcode': 1008});
|
||||
currentSession = null;
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
BBB.listen("UserJoinedVoiceEvent", userJoinedVoiceHandler);
|
||||
|
||||
currentSession.dtmf(1);
|
||||
inEchoTest = false;
|
||||
}
|
||||
|
||||
function userJoinedVoiceHandler(event) {
|
||||
console.log("UserJoinedVoiceHandler - " + event);
|
||||
if (inEchoTest === false && userID === event.userID) {
|
||||
BBB.unlisten("UserJoinedVoiceEvent", userJoinedVoiceHandler);
|
||||
clearTimeout(transferTimeout);
|
||||
webRTCCallback({'status': 'started'});
|
||||
}
|
||||
}
|
||||
|
||||
function createUA(username, server, callback, makeCallFunc) {
|
||||
if (userAgent) {
|
||||
console.log("User agent already created");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Fetching STUN/TURN server info for user agent");
|
||||
|
||||
console.log(html5StunTurn);
|
||||
if (html5StunTurn != null) {
|
||||
createUAWithStuns(username, server, callback, html5StunTurn, makeCallFunc);
|
||||
return;
|
||||
}
|
||||
|
||||
BBB.getSessionToken(function(sessionToken) {
|
||||
$.ajax({
|
||||
dataType: 'json',
|
||||
url: '/bigbluebutton/api/stuns',
|
||||
data: {sessionToken:sessionToken}
|
||||
}).done(function(data) {
|
||||
var stunsConfig = {};
|
||||
stunsConfig['stunServers'] = ( data['stunServers'] ? data['stunServers'].map(function(data) {
|
||||
return data['url'];
|
||||
}) : [] );
|
||||
stunsConfig['turnServers'] = ( data['turnServers'] ? data['turnServers'].map(function(data) {
|
||||
return {
|
||||
'urls': data['url'],
|
||||
'username': data['username'],
|
||||
'password': data['password']
|
||||
};
|
||||
}) : [] );
|
||||
createUAWithStuns(username, server, callback, stunsConfig, makeCallFunc);
|
||||
}).fail(function(data, textStatus, errorThrown) {
|
||||
BBBLog.error("Could not fetch stun/turn servers", {error: textStatus, user: callerIdName, voiceBridge: conferenceVoiceBridge});
|
||||
callback({'status':'failed', 'errorcode': 1009});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function createUAWithStuns(username, server, callback, stunsConfig, makeCallFunc) {
|
||||
console.log("Creating new user agent");
|
||||
|
||||
/* VERY IMPORTANT
|
||||
* - You must escape the username because spaces will cause the connection to fail
|
||||
* - We are connecting to the websocket through an nginx redirect instead of directly to 5066
|
||||
*/
|
||||
var configuration = {
|
||||
uri: 'sip:' + encodeURIComponent(username) + '@' + server,
|
||||
wsServers: 'ws://' + server + '/ws',
|
||||
displayName: username,
|
||||
register: false,
|
||||
traceSip: true,
|
||||
autostart: false,
|
||||
userAgentString: "BigBlueButton",
|
||||
stunServers: stunsConfig['stunServers'],
|
||||
turnServers: stunsConfig['turnServers']
|
||||
};
|
||||
|
||||
uaConnected = false;
|
||||
|
||||
userAgent = new SIP.UA(configuration);
|
||||
setUserAgentListeners(callback, makeCallFunc);
|
||||
userAgent.start();
|
||||
};
|
||||
|
||||
function setUserAgentListeners(callback, makeCallFunc) {
|
||||
console.log("resetting UA callbacks");
|
||||
userAgent.removeAllListeners('connected');
|
||||
userAgent.on('connected', function() {
|
||||
uaConnected = true;
|
||||
makeCallFunc();
|
||||
});
|
||||
userAgent.removeAllListeners('disconnected');
|
||||
userAgent.on('disconnected', function() {
|
||||
if (userAgent) {
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
|
||||
if (uaConnected) {
|
||||
callback({'status':'failed', 'errorcode': 1001}); // WebSocket disconnected
|
||||
} else {
|
||||
callback({'status':'failed', 'errorcode': 1002}); // Could not make a WebSocket connection
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function getUserMicMedia(getUserMicMediaSuccess, getUserMicMediaFailure) {
|
||||
if (userMicMedia == undefined) {
|
||||
if (SIP.WebRTC.isSupported()) {
|
||||
SIP.WebRTC.getUserMedia({audio:true, video:false}, getUserMicMediaSuccess, getUserMicMediaFailure);
|
||||
} else {
|
||||
console.log("getUserMicMedia: webrtc not supported");
|
||||
getUserMicMediaFailure("WebRTC is not supported");
|
||||
}
|
||||
} else {
|
||||
console.log("getUserMicMedia: mic already set");
|
||||
getUserMicMediaSuccess(userMicMedia);
|
||||
}
|
||||
};
|
||||
|
||||
function webrtc_call(username, voiceBridge, callback, isListenOnly) {
|
||||
if (!isWebRTCAvailable()) {
|
||||
callback({'status': 'failed', 'errorcode': 1003}); // Browser version not supported
|
||||
return;
|
||||
}
|
||||
if (isListenOnly == null) { // assume NOT listen only unless otherwise stated
|
||||
isListenOnly = false;
|
||||
}
|
||||
|
||||
var server = window.document.location.hostname;
|
||||
console.log("user " + username + " calling to " + voiceBridge);
|
||||
|
||||
var makeCallFunc = function() {
|
||||
// only make the call when both microphone and useragent have been created
|
||||
// for listen only, stating listen only is a viable substitute for acquiring user media control
|
||||
if ((isListenOnly||userMicMedia) && userAgent)
|
||||
make_call(username, voiceBridge, server, callback, false, isListenOnly);
|
||||
};
|
||||
|
||||
// Reset userAgent so we can successfully switch between listenOnly and listen+speak modes
|
||||
userAgent = null;
|
||||
if (!userAgent) {
|
||||
createUA(username, server, callback, makeCallFunc);
|
||||
}
|
||||
// if the user requests to proceed as listen only (does not require media) or media is already acquired,
|
||||
// proceed with making the call
|
||||
if (isListenOnly || userMicMedia !== undefined) {
|
||||
makeCallFunc();
|
||||
} else {
|
||||
callback({'status':'mediarequest'});
|
||||
getUserMicMedia(function(stream) {
|
||||
console.log("getUserMicMedia: success");
|
||||
userMicMedia = stream;
|
||||
callback({'status':'mediasuccess'});
|
||||
makeCallFunc();
|
||||
}, function(e) {
|
||||
console.error("getUserMicMedia: failure - " + e);
|
||||
callback({'status':'mediafail', 'cause': e});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function make_call(username, voiceBridge, server, callback, recall, isListenOnly) {
|
||||
if (isListenOnly == null) {
|
||||
isListenOnly = false;
|
||||
}
|
||||
|
||||
if (userAgent == null) {
|
||||
console.log("userAgent is still null. Delaying call");
|
||||
var callDelayTimeout = setTimeout( function() {
|
||||
make_call(username, voiceBridge, server, callback, recall, isListenOnly);
|
||||
}, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!userAgent.isConnected()) {
|
||||
console.log("Trying to make call, but UserAgent hasn't connected yet. Delaying call");
|
||||
userAgent.once('connected', function() {
|
||||
console.log("UserAgent has now connected, retrying the call");
|
||||
make_call(username, voiceBridge, server, callback, recall, isListenOnly);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentSession) {
|
||||
console.log('Active call detected ignoring second make_call');
|
||||
return;
|
||||
}
|
||||
|
||||
// Make an audio/video call:
|
||||
console.log("Setting options.. ");
|
||||
|
||||
var options = {};
|
||||
if (isListenOnly) {
|
||||
// create necessary options for a listen only stream
|
||||
var stream = null;
|
||||
// handle the web browser
|
||||
// create a stream object through the browser separated from user media
|
||||
if (typeof webkitMediaStream !== 'undefined') {
|
||||
// Google Chrome
|
||||
stream = new webkitMediaStream;
|
||||
} else {
|
||||
// Firefox
|
||||
audioContext = new window.AudioContext;
|
||||
stream = audioContext.createMediaStreamDestination().stream;
|
||||
}
|
||||
|
||||
options = {
|
||||
media: {
|
||||
stream: stream, // use the stream created above
|
||||
constraints: {
|
||||
audio: true,
|
||||
video: false
|
||||
},
|
||||
render: {
|
||||
remote: document.getElementById('remote-media')
|
||||
}
|
||||
},
|
||||
// a list of our RTC Connection constraints
|
||||
RTCConstraints: {
|
||||
// our constraints are mandatory. We must received audio and must not receive audio
|
||||
mandatory: {
|
||||
OfferToReceiveAudio: true,
|
||||
OfferToReceiveVideo: false
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
options = {
|
||||
media: {
|
||||
stream: userMicMedia,
|
||||
constraints: {
|
||||
audio: true,
|
||||
video: false
|
||||
},
|
||||
render: {
|
||||
remote: document.getElementById('remote-media')
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
callTimeout = setTimeout(function() {
|
||||
console.log('Ten seconds without updates sending timeout code');
|
||||
callback({'status':'failed', 'errorcode': 1006}); // Failure on call
|
||||
currentSession = null;
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
callActive = false;
|
||||
callICEConnected = false;
|
||||
callPurposefullyEnded = false;
|
||||
callFailCounter = 0;
|
||||
console.log("Calling to " + voiceBridge + "....");
|
||||
currentSession = userAgent.invite('sip:' + voiceBridge + '@' + server, options);
|
||||
|
||||
// Only send the callback if it's the first try
|
||||
if (recall === false) {
|
||||
console.log('call connecting');
|
||||
callback({'status':'connecting'});
|
||||
} else {
|
||||
console.log('call connecting again');
|
||||
}
|
||||
|
||||
/*
|
||||
iceGatheringTimeout = setTimeout(function() {
|
||||
console.log('Thirty seconds without ICE gathering finishing');
|
||||
callback({'status':'failed', 'errorcode': 1011}); // ICE Gathering Failed
|
||||
currentSession = null;
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
}, 30000);
|
||||
*/
|
||||
|
||||
currentSession.mediaHandler.on('iceGatheringComplete', function() {
|
||||
clearTimeout(iceGatheringTimeout);
|
||||
});
|
||||
|
||||
// The connecting event fires before the listener can be added
|
||||
currentSession.on('connecting', function(){
|
||||
clearTimeout(callTimeout);
|
||||
});
|
||||
currentSession.on('progress', function(response){
|
||||
console.log('call progress: ' + response);
|
||||
clearTimeout(callTimeout);
|
||||
});
|
||||
currentSession.on('failed', function(response, cause){
|
||||
console.log('call failed with cause: '+ cause);
|
||||
|
||||
if (currentSession) {
|
||||
if (callActive === false) {
|
||||
callback({'status':'failed', 'errorcode': 1004, 'cause': cause}); // Failure on call
|
||||
currentSession = null;
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
} else {
|
||||
callActive = false;
|
||||
//currentSession.bye();
|
||||
currentSession = null;
|
||||
if (userAgent != null) {
|
||||
userAgent.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
clearTimeout(callTimeout);
|
||||
});
|
||||
currentSession.on('bye', function(request){
|
||||
callActive = false;
|
||||
|
||||
if (currentSession) {
|
||||
console.log('call ended ' + currentSession.endTime);
|
||||
|
||||
if (callPurposefullyEnded === true) {
|
||||
callback({'status':'ended'});
|
||||
} else {
|
||||
callback({'status':'failed', 'errorcode': 1005}); // Call ended unexpectedly
|
||||
}
|
||||
clearTimeout(callTimeout);
|
||||
currentSession = null;
|
||||
} else {
|
||||
console.log('bye event already received');
|
||||
}
|
||||
});
|
||||
currentSession.on('accepted', function(data){
|
||||
callActive = true;
|
||||
console.log('BigBlueButton call accepted');
|
||||
|
||||
if (callICEConnected === true) {
|
||||
callback({'status':'started'});
|
||||
} else {
|
||||
callback({'status':'waitingforice'});
|
||||
console.log('Waiting for ICE negotiation');
|
||||
iceConnectedTimeout = setTimeout(function() {
|
||||
console.log('60 seconds without ICE finishing');
|
||||
callback({'status':'failed', 'errorcode': 1010}); // ICE negotiation timeout
|
||||
currentSession = null;
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
}, 60000);
|
||||
}
|
||||
clearTimeout(callTimeout);
|
||||
});
|
||||
currentSession.mediaHandler.on('iceConnectionFailed', function() {
|
||||
console.log('received ice negotiation failed');
|
||||
callback({'status':'failed', 'errorcode': 1007}); // Failure on call
|
||||
currentSession = null;
|
||||
clearTimeout(iceConnectedTimeout);
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
|
||||
clearTimeout(callTimeout);
|
||||
});
|
||||
|
||||
// Some browsers use status of 'connected', others use 'completed', and a couple use both
|
||||
|
||||
currentSession.mediaHandler.on('iceConnectionConnected', function() {
|
||||
console.log('Received ICE status changed to connected');
|
||||
if (callICEConnected === false) {
|
||||
callICEConnected = true;
|
||||
clearTimeout(iceConnectedTimeout);
|
||||
if (callActive === true) {
|
||||
callback({'status':'started'});
|
||||
}
|
||||
clearTimeout(callTimeout);
|
||||
}
|
||||
});
|
||||
|
||||
currentSession.mediaHandler.on('iceConnectionCompleted', function() {
|
||||
console.log('Received ICE status changed to completed');
|
||||
if (callICEConnected === false) {
|
||||
callICEConnected = true;
|
||||
clearTimeout(iceConnectedTimeout);
|
||||
if (callActive === true) {
|
||||
callback({'status':'started'});
|
||||
}
|
||||
clearTimeout(callTimeout);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function webrtc_hangup(callback) {
|
||||
callPurposefullyEnded = true;
|
||||
|
||||
console.log("Hanging up current session");
|
||||
if (callback) {
|
||||
currentSession.on('bye', callback);
|
||||
}
|
||||
currentSession.bye();
|
||||
}
|
||||
|
||||
function isWebRTCAvailable() {
|
||||
return SIP.WebRTC.isSupported();
|
||||
}
|
||||
|
||||
function getCallStatus() {
|
||||
return currentSession;
|
||||
}
|
||||
|
11734
bbb-client-check/resources/lib/sip.js
Normal file
11734
bbb-client-check/resources/lib/sip.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -32,6 +32,7 @@ public class Constants {
|
||||
public static final String RECORDING = "recording";
|
||||
public static final String AUTO_START_RECORDING = "auto_start_recording";
|
||||
public static final String ALLOW_START_STOP_RECORDING = "allow_start_stop_recording";
|
||||
public static final String WEBCAMS_ONLY_FOR_MODERATOR = "webcams_only_for_moderator";
|
||||
public static final String LAYOUT_ID = "layout_id";
|
||||
public static final String LISTENONLY = "listenOnly";
|
||||
public static final String LISTEN_ONLY = "listen_only";
|
||||
|
@ -12,6 +12,7 @@ public class CreateMeetingMessage implements IBigBlueButtonMessage {
|
||||
public final Long duration;
|
||||
public final Boolean autoStartRecording;
|
||||
public final Boolean allowStartStopRecording;
|
||||
public final Boolean webcamsOnlyForModerator;
|
||||
public final String moderatorPass;
|
||||
public final String viewerPass;
|
||||
public final Long createTime;
|
||||
@ -19,8 +20,9 @@ public class CreateMeetingMessage implements IBigBlueButtonMessage {
|
||||
|
||||
public CreateMeetingMessage(String id, String externalId, String name, Boolean record, String voiceBridge,
|
||||
Long duration, Boolean autoStartRecording,
|
||||
Boolean allowStartStopRecording, String moderatorPass,
|
||||
String viewerPass, Long createTime, String createDate) {
|
||||
Boolean allowStartStopRecording,Boolean webcamsOnlyForModerator,
|
||||
String moderatorPass, String viewerPass,
|
||||
Long createTime, String createDate) {
|
||||
this.id = id;
|
||||
this.externalId = externalId;
|
||||
this.name = name;
|
||||
@ -29,6 +31,7 @@ public class CreateMeetingMessage implements IBigBlueButtonMessage {
|
||||
this.duration = duration;
|
||||
this.autoStartRecording = autoStartRecording;
|
||||
this.allowStartStopRecording = allowStartStopRecording;
|
||||
this.webcamsOnlyForModerator = webcamsOnlyForModerator;
|
||||
this.moderatorPass = moderatorPass;
|
||||
this.viewerPass = viewerPass;
|
||||
this.createTime = createTime;
|
||||
|
@ -0,0 +1,48 @@
|
||||
package org.bigbluebutton.common.messages;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
public class MeetingEndingMessage implements ISubscribedMessage {
|
||||
public static final String MEETING_ENDING = "meeting_ending_message";
|
||||
public final String VERSION = "0.0.1";
|
||||
|
||||
public final String meetingId;
|
||||
|
||||
public MeetingEndingMessage(String meetingID) {
|
||||
this.meetingId = meetingID;
|
||||
}
|
||||
|
||||
public String toJson() {
|
||||
HashMap<String, Object> payload = new HashMap<String, Object>();
|
||||
payload.put(Constants.MEETING_ID, meetingId);
|
||||
|
||||
java.util.HashMap<String, Object> header = MessageBuilder.buildHeader(MEETING_ENDING, VERSION, null);
|
||||
|
||||
return MessageBuilder.buildJson(header, payload);
|
||||
}
|
||||
public static MeetingEndingMessage fromJson(String message) {
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject obj = (JsonObject) parser.parse(message);
|
||||
|
||||
if (obj.has("header") && obj.has("payload")) {
|
||||
JsonObject header = (JsonObject) obj.get("header");
|
||||
JsonObject payload = (JsonObject) obj.get("payload");
|
||||
|
||||
if (header.has("name")) {
|
||||
String messageName = header.get("name").getAsString();
|
||||
if (MEETING_ENDING.equals(messageName)) {
|
||||
if (payload.has(Constants.MEETING_ID)) {
|
||||
String meetingId = payload.get(Constants.MEETING_ID).getAsString();
|
||||
|
||||
return new MeetingEndingMessage(meetingId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -60,6 +60,7 @@ public class MessageFromJsonConverter {
|
||||
Long duration = payload.get(Constants.DURATION).getAsLong();
|
||||
Boolean autoStartRecording = payload.get(Constants.AUTO_START_RECORDING).getAsBoolean();
|
||||
Boolean allowStartStopRecording = payload.get(Constants.ALLOW_START_STOP_RECORDING).getAsBoolean();
|
||||
Boolean webcamsOnlyForModerator = payload.get(Constants.WEBCAMS_ONLY_FOR_MODERATOR).getAsBoolean();
|
||||
String moderatorPassword = payload.get(Constants.MODERATOR_PASS).getAsString();
|
||||
String viewerPassword = payload.get(Constants.VIEWER_PASS).getAsString();
|
||||
Long createTime = payload.get(Constants.CREATE_TIME).getAsLong();
|
||||
@ -67,7 +68,8 @@ public class MessageFromJsonConverter {
|
||||
|
||||
return new CreateMeetingMessage(id, externalId, name, record, voiceBridge,
|
||||
duration, autoStartRecording, allowStartStopRecording,
|
||||
moderatorPassword, viewerPassword, createTime, createDate);
|
||||
webcamsOnlyForModerator, moderatorPassword, viewerPassword,
|
||||
createTime, createDate);
|
||||
}
|
||||
|
||||
private static IBigBlueButtonMessage processDestroyMeeting(JsonObject payload) {
|
||||
|
@ -23,6 +23,7 @@ public class CreateMeetingRequest implements IBigBlueButtonMessage {
|
||||
public final Integer durationInMinutes;
|
||||
public final Boolean autoStartRecording;
|
||||
public final Boolean allowStartStopRecording;
|
||||
public final Boolean webcamsOnlyForModerator;
|
||||
public final String moderatorPassword;
|
||||
public final String viewerPassword;
|
||||
public final Long createTime;
|
||||
@ -34,8 +35,9 @@ public class CreateMeetingRequest implements IBigBlueButtonMessage {
|
||||
String parentId, String name, Boolean record,
|
||||
String voiceConfId, Integer duration,
|
||||
Boolean autoStartRecording, Boolean allowStartStopRecording,
|
||||
String moderatorPass, String viewerPass, Long createTime,
|
||||
String createDate, Boolean isBreakout, Integer sequence) {
|
||||
Boolean webcamsOnlyForModerator, String moderatorPass,
|
||||
String viewerPass, Long createTime, String createDate,
|
||||
Boolean isBreakout, Integer sequence) {
|
||||
this.id = id;
|
||||
this.externalId = externalId;
|
||||
this.parentId = parentId;
|
||||
@ -45,6 +47,7 @@ public class CreateMeetingRequest implements IBigBlueButtonMessage {
|
||||
this.durationInMinutes = duration;
|
||||
this.autoStartRecording = autoStartRecording;
|
||||
this.allowStartStopRecording = allowStartStopRecording;
|
||||
this.webcamsOnlyForModerator = webcamsOnlyForModerator;
|
||||
this.moderatorPassword = moderatorPass;
|
||||
this.viewerPassword = viewerPass;
|
||||
this.createTime = createTime;
|
||||
|
@ -8,46 +8,48 @@ import org.junit.Test;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class CreateMeetingRequestTest {
|
||||
@Test
|
||||
public void testCreateMeetingRequest() {
|
||||
String meetingId = "abc123";
|
||||
String externalId = "extabc123";
|
||||
String parentId = "";
|
||||
Boolean record = false;
|
||||
Integer durationInMinutes = 20;
|
||||
String name = "Breakout room 1";
|
||||
String voiceConfId = "851153";
|
||||
Boolean autoStartRecording = false;
|
||||
Boolean allowStartStopRecording = false;
|
||||
Boolean isBreakout = true;
|
||||
Integer sequence = 4;
|
||||
String viewerPassword = "vp";
|
||||
String moderatorPassword = "mp";
|
||||
long createTime = System.currentTimeMillis();
|
||||
String createDate = new Date(createTime).toString();
|
||||
|
||||
@Test
|
||||
public void testCreateMeetingRequest() {
|
||||
String meetingId = "abc123";
|
||||
String externalId = "extabc123";
|
||||
String parentId = "";
|
||||
Boolean record = false;
|
||||
Integer durationInMinutes = 20;
|
||||
String name = "Breakout room 1";
|
||||
String voiceConfId = "851153";
|
||||
Boolean autoStartRecording = false;
|
||||
Boolean allowStartStopRecording = false;
|
||||
Boolean webcamsOnlyForModerator = false;
|
||||
Boolean isBreakout = true;
|
||||
Integer sequence = 4;
|
||||
String viewerPassword = "vp";
|
||||
String moderatorPassword = "mp";
|
||||
long createTime = System.currentTimeMillis();
|
||||
String createDate = new Date(createTime).toString();
|
||||
|
||||
CreateMeetingRequestPayload payload = new CreateMeetingRequestPayload(
|
||||
meetingId, externalId, parentId, name, record, voiceConfId,
|
||||
durationInMinutes, autoStartRecording, allowStartStopRecording,
|
||||
moderatorPassword, viewerPassword, createTime, createDate,
|
||||
isBreakout, sequence);
|
||||
CreateMeetingRequest msg = new CreateMeetingRequest(payload);
|
||||
Gson gson = new Gson();
|
||||
String json = gson.toJson(msg);
|
||||
System.out.println(json);
|
||||
|
||||
CreateMeetingRequest rxMsg = gson.fromJson(json, CreateMeetingRequest.class);
|
||||
|
||||
Assert.assertEquals(rxMsg.header.name, CreateMeetingRequest.NAME);
|
||||
Assert.assertEquals(rxMsg.payload.id, meetingId);
|
||||
Assert.assertEquals(rxMsg.payload.externalId, externalId);
|
||||
Assert.assertEquals(rxMsg.payload.parentId, parentId);
|
||||
Assert.assertEquals(rxMsg.payload.name, name);
|
||||
Assert.assertEquals(rxMsg.payload.voiceConfId, voiceConfId);
|
||||
Assert.assertEquals(rxMsg.payload.viewerPassword, viewerPassword);
|
||||
Assert.assertEquals(rxMsg.payload.moderatorPassword, moderatorPassword);
|
||||
Assert.assertEquals(rxMsg.payload.durationInMinutes, durationInMinutes);
|
||||
Assert.assertEquals(rxMsg.payload.isBreakout, isBreakout);
|
||||
Assert.assertEquals(rxMsg.payload.sequence, sequence);
|
||||
}
|
||||
webcamsOnlyForModerator, moderatorPassword, viewerPassword,
|
||||
createTime, createDate, isBreakout, sequence);
|
||||
CreateMeetingRequest msg = new CreateMeetingRequest(payload);
|
||||
Gson gson = new Gson();
|
||||
String json = gson.toJson(msg);
|
||||
System.out.println(json);
|
||||
|
||||
CreateMeetingRequest rxMsg = gson.fromJson(json,
|
||||
CreateMeetingRequest.class);
|
||||
|
||||
Assert.assertEquals(rxMsg.header.name, CreateMeetingRequest.NAME);
|
||||
Assert.assertEquals(rxMsg.payload.id, meetingId);
|
||||
Assert.assertEquals(rxMsg.payload.externalId, externalId);
|
||||
Assert.assertEquals(rxMsg.payload.parentId, parentId);
|
||||
Assert.assertEquals(rxMsg.payload.name, name);
|
||||
Assert.assertEquals(rxMsg.payload.voiceConfId, voiceConfId);
|
||||
Assert.assertEquals(rxMsg.payload.viewerPassword, viewerPassword);
|
||||
Assert.assertEquals(rxMsg.payload.moderatorPassword, moderatorPassword);
|
||||
Assert.assertEquals(rxMsg.payload.durationInMinutes, durationInMinutes);
|
||||
Assert.assertEquals(rxMsg.payload.isBreakout, isBreakout);
|
||||
Assert.assertEquals(rxMsg.payload.sequence, sequence);
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ cd lib
|
||||
sudo cp -r ~/dev/bigbluebutton/bbb-screenshare/app/jws/lib/* .
|
||||
cd ..
|
||||
sudo cp ~/dev/bigbluebutton/bbb-screenshare/app/jws/screenshare.jnlp .
|
||||
sudo cp ~/dev/bigbluebutton/bbb-screenshare/app/jws/screenshare.jnlp.h264 .
|
||||
|
||||
sudo chmod -R 777 /usr/share/red5/webapps/screenshare
|
||||
sudo chown -R red5:red5 /usr/share/red5/webapps/screenshare
|
||||
|
BIN
bbb-screenshare/app/jws/lib/ffmpeg-linux-x86-svc2.jar
Normal file
BIN
bbb-screenshare/app/jws/lib/ffmpeg-linux-x86-svc2.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
bbb-screenshare/app/jws/lib/ffmpeg-linux-x86_64-svc2.jar
Normal file
BIN
bbb-screenshare/app/jws/lib/ffmpeg-linux-x86_64-svc2.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
bbb-screenshare/app/jws/lib/ffmpeg-macosx-x86_64-svc2.jar
Normal file
BIN
bbb-screenshare/app/jws/lib/ffmpeg-macosx-x86_64-svc2.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
bbb-screenshare/app/jws/lib/ffmpeg-svc2.jar
Normal file
BIN
bbb-screenshare/app/jws/lib/ffmpeg-svc2.jar
Normal file
Binary file not shown.
BIN
bbb-screenshare/app/jws/lib/ffmpeg-win-x86-svc2.jar
Normal file
BIN
bbb-screenshare/app/jws/lib/ffmpeg-win-x86-svc2.jar
Normal file
Binary file not shown.
BIN
bbb-screenshare/app/jws/lib/ffmpeg-win-x86_64-svc2.jar
Normal file
BIN
bbb-screenshare/app/jws/lib/ffmpeg-win-x86_64-svc2.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -16,23 +16,23 @@
|
||||
</resources>
|
||||
|
||||
<resources os="Windows" arch="amd64">
|
||||
<nativelib href="ffmpeg-windows-x86_64.jar"/>
|
||||
<nativelib href="ffmpeg-win-x86_64-svc2.jar"/>
|
||||
</resources>
|
||||
|
||||
<resources os="Windows" arch="x86">
|
||||
<nativelib href="$$jnlpUrl/lib/ffmpeg-windows-x86.jar"/>
|
||||
<nativelib href="ffmpeg-win-x86-svc2.jar"/>
|
||||
</resources>
|
||||
|
||||
<resources os="Linux" arch="x86_64 amd64">
|
||||
<nativelib href="ffmpeg-linux-x86_64.jar"/>
|
||||
<nativelib href="ffmpeg-linux-x86_64-svc2.jar"/>
|
||||
</resources>
|
||||
|
||||
<resources os="Linux" arch="x86 i386 i486 i586 i686">
|
||||
<nativelib href="ffmpeg-linux-x86.jar"/>
|
||||
<nativelib href="ffmpeg-linux-x86-svc2.jar"/>
|
||||
</resources>
|
||||
|
||||
<resources os="Mac OS X">
|
||||
<nativelib href="ffmpeg-macosx-x86_64.jar"/>
|
||||
<nativelib href="ffmpeg-macosx-x86_64-svc2.jar"/>
|
||||
</resources>
|
||||
|
||||
<application-desc
|
||||
@ -45,6 +45,7 @@
|
||||
<argument>$$fullScreen</argument>
|
||||
<argument>$$codecOptions</argument>
|
||||
<argument>$$session</argument>
|
||||
<argument>$$useH264</argument>
|
||||
<argument>$$errorMessage</argument>
|
||||
</application-desc>
|
||||
<security><all-permissions/></security>
|
||||
|
@ -16,23 +16,23 @@
|
||||
</resources>
|
||||
|
||||
<resources os="Windows" arch="amd64">
|
||||
<nativelib href="ffmpeg-windows-x86_64.jar"/>
|
||||
<nativelib href="ffmpeg-win-x86_64-h264.jar"/>
|
||||
</resources>
|
||||
|
||||
<resources os="Windows" arch="x86">
|
||||
<nativelib href="$$jnlpUrl/lib/ffmpeg-windows-x86.jar"/>
|
||||
<nativelib href="ffmpeg-win-x86-h264.jar"/>
|
||||
</resources>
|
||||
|
||||
<resources os="Linux" arch="x86_64 amd64">
|
||||
<nativelib href="ffmpeg-linux-x86_64.jar"/>
|
||||
<nativelib href="ffmpeg-linux-x86_64-h264.jar"/>
|
||||
</resources>
|
||||
|
||||
<resources os="Linux" arch="x86 i386 i486 i586 i686">
|
||||
<nativelib href="ffmpeg-linux-x86.jar"/>
|
||||
<nativelib href="ffmpeg-linux-x86-h264.jar"/>
|
||||
</resources>
|
||||
|
||||
<resources os="Mac OS X">
|
||||
<nativelib href="ffmpeg-macosx-x86_64.jar"/>
|
||||
<nativelib href="ffmpeg-macosx-x86_64-h264.jar"/>
|
||||
</resources>
|
||||
|
||||
<application-desc
|
||||
@ -45,6 +45,7 @@
|
||||
<argument>$$fullScreen</argument>
|
||||
<argument>$$codecOptions</argument>
|
||||
<argument>$$session</argument>
|
||||
<argument>$$useH264</argument>
|
||||
<argument>$$errorMessage</argument>
|
||||
</application-desc>
|
||||
<security><all-permissions/></security>
|
@ -41,6 +41,8 @@ import java.io.*;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
import javax.xml.parsers.*;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.operations.Bool;
|
||||
import org.xml.sax.*;
|
||||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
@ -314,12 +316,23 @@ public class JnlpFileHandler {
|
||||
if (sInfo == null) {
|
||||
errorMessage = "ERROR_GETTING_INFO_USING_TOKEN";
|
||||
} else {
|
||||
publishUrl = sInfo.publishUrl;
|
||||
|
||||
System.out.println("********* URL=" + sInfo.publishUrl);
|
||||
if (sInfo.tunnel) {
|
||||
publishUrl = sInfo.publishUrl.replaceFirst("rtmp","rtmpt");
|
||||
} else {
|
||||
publishUrl = sInfo.publishUrl;
|
||||
}
|
||||
|
||||
streamId = sInfo.streamId;
|
||||
session = sInfo.session;
|
||||
}
|
||||
|
||||
|
||||
|
||||
System.out.println("********* URL=" + publishUrl);
|
||||
|
||||
String jnlpUrl = configurator.getJnlpUrl();
|
||||
Boolean useH264 = configurator.isUseH264();
|
||||
|
||||
String codecOptions = configurator.getCodecOptions();
|
||||
log.debug("Codec Options = [" + codecOptions + "]");
|
||||
@ -337,6 +350,7 @@ public class JnlpFileHandler {
|
||||
jnlpTemplate = substitute(jnlpTemplate, "$$session", session);
|
||||
jnlpTemplate = substitute(jnlpTemplate, "$$streamId", streamId);
|
||||
jnlpTemplate = substitute(jnlpTemplate, "$$codecOptions", codecOptions);
|
||||
jnlpTemplate = substitute(jnlpTemplate, "$$useH264", useH264.toString());
|
||||
jnlpTemplate = substitute(jnlpTemplate, "$$errorMessage", errorMessage);
|
||||
// fix for 5039951: Add $$hostname macro
|
||||
jnlpTemplate = substitute(jnlpTemplate, "$$hostname", request.getServerName());
|
||||
|
@ -11,7 +11,7 @@ public interface IScreenShareApplication {
|
||||
Boolean recordStream(String meetingId, String streamId);
|
||||
|
||||
void isScreenSharing(String meetingId, String userId);
|
||||
void requestShareToken(String meetingId, String userId, Boolean record);
|
||||
void requestShareToken(String meetingId, String userId, Boolean record, Boolean tunnel);
|
||||
void startShareRequest(String meetingId, String userId, String session);
|
||||
void pauseShareRequest(String meetingId, String userId, String streamId);
|
||||
void restartShareRequest(String meetingId, String userId);
|
||||
|
@ -5,10 +5,12 @@ public class ScreenShareInfo {
|
||||
public final String session;
|
||||
public final String streamId;
|
||||
public final String publishUrl;
|
||||
public final Boolean tunnel;
|
||||
|
||||
public ScreenShareInfo(String session, String publishUrl, String streamId) {
|
||||
public ScreenShareInfo(String session, String publishUrl, String streamId, Boolean tunnel) {
|
||||
this.session = session;
|
||||
this.streamId = streamId;
|
||||
this.publishUrl = publishUrl;
|
||||
this.tunnel = tunnel;
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ public class Red5AppHandler {
|
||||
app.isScreenSharing(meetingId, userId);
|
||||
}
|
||||
|
||||
public void requestShareToken(String meetingId, String userId, Boolean record) {
|
||||
app.requestShareToken(meetingId, userId, record);
|
||||
public void requestShareToken(String meetingId, String userId, Boolean record, Boolean tunnel) {
|
||||
app.requestShareToken(meetingId, userId, record, tunnel);
|
||||
}
|
||||
|
||||
public void startShareRequest(String meetingId, String userId, String session) {
|
||||
|
@ -133,12 +133,13 @@ public class Red5AppService {
|
||||
Boolean record = (Boolean) msg.get("record");
|
||||
String meetingId = Red5.getConnectionLocal().getScope().getName();
|
||||
String userId = (String) Red5.getConnectionLocal().getAttribute("USERID");
|
||||
Boolean tunnel = (Boolean) msg.get("tunnel");
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Received startShareRequest for meetingId=" + meetingId + " from user=" + userId);
|
||||
}
|
||||
|
||||
handler.requestShareToken(meetingId, userId, record);
|
||||
handler.requestShareToken(meetingId, userId, record, tunnel);
|
||||
}
|
||||
|
||||
public void stopShareRequest(Map<String, Object> msg) {
|
||||
|
@ -10,6 +10,7 @@ public class JnlpConfigurator {
|
||||
private IScreenShareApplication screenShareApplication;
|
||||
private String streamBaseUrl;
|
||||
private String codecOptions;
|
||||
private boolean useH264 = false;
|
||||
|
||||
|
||||
public String getJnlpUrl() {
|
||||
@ -35,6 +36,14 @@ public class JnlpConfigurator {
|
||||
public String getCodecOptions() {
|
||||
return codecOptions;
|
||||
}
|
||||
|
||||
public void setUseH264(boolean h264) {
|
||||
useH264 = h264;
|
||||
}
|
||||
|
||||
public boolean isUseH264() {
|
||||
return useH264;
|
||||
}
|
||||
|
||||
public ScreenShareInfo getScreenShareInfo(String meetingId, String token) {
|
||||
ScreenShareInfoResponse resp = screenShareApplication.getScreenShareInfo(meetingId, token);
|
||||
|
@ -98,7 +98,7 @@ class ScreenShareApplication(val bus: IEventsMessageBus, val jnlpFile: String,
|
||||
val reply = Await.result(future, timeout.duration).asInstanceOf[ScreenShareInfoRequestReply]
|
||||
|
||||
val publishUrl = streamBaseUrl + "/" + meetingId
|
||||
val info = new ScreenShareInfo(reply.session, publishUrl, reply.streamId)
|
||||
val info = new ScreenShareInfo(reply.session, publishUrl, reply.streamId, reply.tunnel)
|
||||
new ScreenShareInfoResponse(info, null)
|
||||
} catch {
|
||||
case e: TimeoutException =>
|
||||
@ -157,12 +157,12 @@ class ScreenShareApplication(val bus: IEventsMessageBus, val jnlpFile: String,
|
||||
|
||||
}
|
||||
|
||||
def requestShareToken(meetingId: String, userId: String, record: java.lang.Boolean) {
|
||||
def requestShareToken(meetingId: String, userId: String, record: java.lang.Boolean, tunnel: java.lang.Boolean) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Received request share token on meeting=" + meetingId + "for user=" + userId + "]")
|
||||
}
|
||||
|
||||
screenShareManager ! RequestShareTokenMessage(meetingId, userId, jnlpFile, record)
|
||||
screenShareManager ! RequestShareTokenMessage(meetingId, userId, jnlpFile, record, tunnel)
|
||||
}
|
||||
|
||||
def startShareRequest(meetingId: String, userId: String, session: String) {
|
||||
|
@ -6,12 +6,12 @@ import org.bigbluebutton.app.screenshare.events.IEventsMessageBus
|
||||
|
||||
object ActiveSession {
|
||||
def apply(parent: Screenshare, bus: IEventsMessageBus, meetingId: String, streamId: String,
|
||||
token: String, recorded: Boolean, userId: String)(implicit context: ActorContext) =
|
||||
new ActiveSession(parent, bus, meetingId, streamId, token, recorded, userId)(context)
|
||||
token: String, recorded: Boolean, userId: String, tunnel: Boolean)(implicit context: ActorContext) =
|
||||
new ActiveSession(parent, bus, meetingId, streamId, token, recorded, userId, tunnel)(context)
|
||||
}
|
||||
|
||||
class ActiveSession(parent: Screenshare, bus: IEventsMessageBus, val meetingId: String,
|
||||
val streamId: String, val token: String, val recorded: Boolean,
|
||||
val userId: String)(implicit val context: ActorContext) {
|
||||
val userId: String, val tunnel: Boolean)(implicit val context: ActorContext) {
|
||||
// val actorRef = context.actorOf(Session.props(parent, bus, meetingId, streamId, token, recorded, userId))
|
||||
}
|
||||
|
@ -143,6 +143,9 @@ class Screenshare(val sessionManager: ScreenshareManager,
|
||||
private val PRESENTER_AUTO_RECONNECTED_REASON = "PRESENTER_AUTO_RECONNECTED_REASON"
|
||||
private val JWS_START_FAILED_REASON = "JWS_START_FAILED_REASON"
|
||||
|
||||
// RTMP or RTMPT
|
||||
private var tunnel: Boolean = false;
|
||||
|
||||
val sessionAudit = context.actorOf(ScreenShareAuditInternal.props(meetingId))
|
||||
|
||||
def receive = {
|
||||
@ -283,7 +286,7 @@ class Screenshare(val sessionManager: ScreenshareManager,
|
||||
sss <- screenShareSession
|
||||
} yield {
|
||||
if (as.token == msg.token) {
|
||||
sender ! new ScreenShareInfoRequestReply(msg.meetingId, as.streamId, sss)
|
||||
sender ! new ScreenShareInfoRequestReply(msg.meetingId, as.streamId, sss, as.tunnel)
|
||||
}
|
||||
|
||||
}
|
||||
@ -446,7 +449,7 @@ class Screenshare(val sessionManager: ScreenshareManager,
|
||||
val token = streamId
|
||||
|
||||
val userId = trimUserId(msg.userId).getOrElse(msg.userId)
|
||||
val session = ActiveSession(this, bus, meetingId, streamId, token, record, userId)
|
||||
val session = ActiveSession(this, bus, meetingId, streamId, token, record, userId, tunnel)
|
||||
activeSession = Some(session)
|
||||
sessionStartedTimestamp = TimeUtil.currentMonoTimeInSeconds()
|
||||
status = START
|
||||
@ -474,7 +477,8 @@ class Screenshare(val sessionManager: ScreenshareManager,
|
||||
|
||||
val userId = trimUserId(msg.userId).getOrElse(msg.userId)
|
||||
|
||||
val session = ActiveSession(this, bus, meetingId, streamId, token, msg.record, userId)
|
||||
tunnel = msg.tunnel
|
||||
val session = ActiveSession(this, bus, meetingId, streamId, token, msg.record, userId, tunnel)
|
||||
activeSession = Some(session)
|
||||
|
||||
currentPresenterId = Some(msg.userId)
|
||||
|
@ -1,6 +1,6 @@
|
||||
package org.bigbluebutton.app.screenshare.server.sessions.messages
|
||||
|
||||
case class RequestShareTokenMessage(meetingId: String, userId: String, jnlp: String, record: Boolean)
|
||||
case class RequestShareTokenMessage(meetingId: String, userId: String, jnlp: String, record: Boolean, tunnel: Boolean)
|
||||
|
||||
case class StartShareRequestMessage(meetingId: String, userId: String, session: String)
|
||||
|
||||
@ -37,7 +37,7 @@ case class IsScreenSharingReply(sharing: Boolean, streamId: String,
|
||||
|
||||
case class ScreenShareInfoRequest(meetingId: String, token: String)
|
||||
|
||||
case class ScreenShareInfoRequestReply(meetingId: String, streamId: String, session: String)
|
||||
case class ScreenShareInfoRequestReply(meetingId: String, streamId: String, session: String, tunnel: Boolean)
|
||||
|
||||
case class UserDisconnected(meetingId: String, userId: String)
|
||||
|
||||
|
@ -83,6 +83,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
<property name="jnlpUrl" value="${jnlpUrl}"/>
|
||||
<property name="streamBaseUrl" value="${streamBaseUrl}"/>
|
||||
<property name="codecOptions" value="${codecOptions}"/>
|
||||
<property name="useH264" value="${useH264}"/>
|
||||
<property name="application" ref="screenShareApplication"/>
|
||||
</bean>
|
||||
|
||||
|
@ -18,6 +18,7 @@ redis.port=6379
|
||||
streamBaseUrl=rtmp://192.168.23.53/screenshare
|
||||
jnlpUrl=http://192.168.23.53/screenshare
|
||||
jnlpFile=http://192.168.23.53/screenshare/screenshare.jnlp
|
||||
useH264=false
|
||||
|
||||
# NOTES:
|
||||
# 1. GOP (group of pictures) is calculated as frameRate * keyFrameInterval
|
||||
|
@ -1,15 +1,181 @@
|
||||
|
||||
This directory contains the difference JavaCV jar files that we need for our web start application.
|
||||
** NOTE: **
|
||||
Taken from https://github.com/bytedeco/javacpp-presets/wiki/Build-Environments
|
||||
|
||||
To build each native library and sign each ffmpeg native libraries:
|
||||
|
||||
1. cd to the platform directory you want to build (cd ffmpeg-win-x86)
|
||||
2. type ```gradle jar``` to build the jar file
|
||||
3. type ```ant sign-jar``` to sign the jar file with your certificate
|
||||
4. copy the signed-jar to ```bbb-screenshare/app/jws/lib``` to be included when
|
||||
deploying to red5
|
||||
|
||||
We have included unsigned jars for ```ffmpeg.jar```, ```javacpp.jar```, and ```javacv.jar``` in the
|
||||
unsigned-jars directory. You can sign the jar files there with your certificate.
|
||||
Introduction
|
||||
------------
|
||||
This page contains a description of the environments that are used to build the JavaCPP Presets for [Android (ARM and x86)](#android-arm-and-x86), [Linux (x86 and x86_64)](#linux-x86-and-x86_64), [Linux (ARM)](#linux-arm), [Mac OS X (x86_64)](#mac-os-x-x86_64), and [Windows (x86 and x86_64)](#windows-x86-and-x86_64). We also explain our choices given the requirements and provide some recommendations. Furthermore, JavaCPP is by no means limited to these platforms, so if you happen to know how to set up an environment for other platforms, by all means, please do add that information to this page to share with others. Thank you!
|
||||
|
||||
|
||||
Prerequisites for all platforms
|
||||
-------------------------------
|
||||
The build process for the modules of `javacpp-presets` usually depends on the same version of the `javacpp` module. To insure that you have the latest matching version of both, please execute the following before starting the build in the `javacpp-presets` directory:
|
||||
```bash
|
||||
$ git clone https://github.com/bytedeco/javacpp.git --branch <tag>
|
||||
$ git clone https://github.com/bytedeco/javacpp-presets.git --branch <tag>
|
||||
$ cd javacpp
|
||||
$ mvn clean install
|
||||
```
|
||||
For the latest tag please check
|
||||
https://github.com/bytedeco/javacpp-presets/tags
|
||||
|
||||
Android (ARM and x86)
|
||||
---------------------
|
||||
To produce native libraries for Android, we basically only need to install the JDK and the NDK, which is available for Linux, Mac OS X, and Windows. However, the build scripts of some libraries only run correctly under Linux, so we recommend using a recent distribution of Linux (such as Fedora or Ubuntu) as build environment for Android.
|
||||
|
||||
### Preparations
|
||||
1. Download the latest version of the [NDK](https://developer.android.com/ndk/downloads/), which is r10e at the time of this writing and contains important fixes for OpenMP, among other things
|
||||
2. Install the NDK under `~/Android/android-ndk`, where the build scripts will look for it by default
|
||||
3. Finally, make sure to have installed at least OpenJDK and Maven as per the instructions of your distribution
|
||||
|
||||
After which the following commands can be used to start the build inside the `javacpp-presets` directory:
|
||||
```bash
|
||||
$ ANDROID_NDK=/path/to/android-ndk/ bash cppbuild.sh -platform android-xxx install
|
||||
$ mvn clean install -Djavacpp.platform=android-xxx -Djavacpp.platform.root=/path/to/android-ndk/ -Djavacpp.platform.compiler=/path/to/target-g++
|
||||
```
|
||||
where `android-xxx` is either `android-arm` or `android-x86`, and where `target-g++` is either `arm-linux-androideabi-g++` or `i686-linux-android-g++`.
|
||||
|
||||
|
||||
Linux (x86 and x86_64)
|
||||
----------------------
|
||||
To produce native libraries that can run on the largest possible number of Linux installations out there, it is recommended to build under CentOS 7. This is because it relies on an old enough version of glibc, which nevertheless works for all the libraries found in the JavaCPP Presets, and since newer versions of glibc are backward compatible, all recent distributions of Linux should support the binaries generated. We do not actually need to install CentOS 7 though. Pretty much any recent distribution of Linux comes with a package for [Docker](https://www.docker.com/). It is also possible to map existing directories, for example `/usr/local/lib/bazel` and `/usr/local/cuda` as shown in the steps below, to reuse an existing [Bazel](http://bazel.io/docs/install.html) or [CUDA](https://developer.nvidia.com/cuda-downloads) installation as well as any other set of files for the purpose of the build.
|
||||
|
||||
### Preparations
|
||||
1. Install Docker under, for example, Fedora and Ubuntu, respectively:
|
||||
|
||||
```bash
|
||||
$ sudo yum install docker
|
||||
$ sudo apt-get install docker.io
|
||||
```
|
||||
|
||||
2. When using SELinux, it might also be necessary to disable temporarily the firewall, for example:
|
||||
|
||||
```
|
||||
$ sudo systemctl stop firewalld
|
||||
$ sudo systemctl start docker
|
||||
```
|
||||
|
||||
3. Start the container for CentOS 7 (the command might be `docker.io` instead of `docker`):
|
||||
|
||||
```bash
|
||||
$ sudo docker run --privileged -it -v /usr/local/lib/bazel:/usr/local/lib/bazel -v /usr/local/cuda:/usr/local/cuda centos:7 /bin/bash
|
||||
```
|
||||
|
||||
4. Finally, inside the container, we need to install a bunch of things:
|
||||
|
||||
```bash
|
||||
$ ln -s /usr/local/lib/bazel/bin/bazel /usr/local/bin/bazel
|
||||
$ yum install epel-release
|
||||
$ yum install clang gcc-c++ gcc-gfortran java-devel maven python numpy swig git file which wget unzip tar bzip2 gzip xz patch make cmake3 perl nasm yasm alsa-lib-devel freeglut-devel gtk2-devel libusb-devel libusb1-devel zlib-devel
|
||||
$ yum install `rpm -qa | sed s/.x86_64$/.i686/`
|
||||
```
|
||||
|
||||
After which the following commands can be used to start the build inside the `javacpp-presets` directory:
|
||||
```bash
|
||||
$ bash cppbuild.sh -platform linux-xxx install
|
||||
$ mvn clean install -Djavacpp.platform=linux-xxx
|
||||
```
|
||||
where `linux-xxx` is either `linux-x86` or `linux-x86_64`.
|
||||
|
||||
|
||||
Linux (ARM)
|
||||
-----------
|
||||
There are a growing number of arm platforms running Linux, though testing of this build has mainly focussed on the Pi family of products. Compiling natively on these platforms can be quite time consuming, and as well to automate the build process, the build setup here relies on cross-compiling for the target arm platform. This has been tested using Ubuntu x64 15.10, but it should be reasonably similar approach for other host OS's.
|
||||
|
||||
You'll need to have setup a build environment with the usual packages (pkgconfig, build-essentials, yasm, nasm, maven3, etc). The major addition you'll need is a set of cross compilers: arm-linux-gnueabihf-gcc, arm-linux-gnueabihf-g++ and arm-linux-gnueabihf-cpp. It's best to get these via your OS's package manager, as there are other dependencies for these.
|
||||
|
||||
Originally a 5.x compiler was used, but this seems to caused problems in creating a dependency on newer glibc functionality which might not be present on your target arm device. The 4.8 or 4.9 version of the compiler seems to work fine, but, in targetting support for the Pi1 and well as Pi2-Pi3 (i.e. arm6 as well as arm7) it seems some compiler flag combinations might not be support by the standard gnueabihf compiler toolchain.
|
||||
|
||||
There are pi specific compilers available, so these have been used in the current setup.
|
||||
|
||||
1. Get the Pi tools: git clone https://github.com/raspberrypi/tools.git
|
||||
2. From this folder, move out a specific compiler version to a more generic location: sudo cp -r ./tools/arm-bcm2708/arm-bcm2708-linux-gnueabi /opt
|
||||
3. Setup alternatives of the generic compiler names in /usr/bin to point to this new compiler
|
||||
|
||||
```bash
|
||||
$ update-alternatives --install /usr/bin/arm-linux-gnueabihf-gcc arm-linux-gnueabihf-gcc /opt/arm-bcm2708hardfp-linux-gnueabi/bin/arm-bcm2708hardfp-linux-gnueabi-gcc 46
|
||||
$ update-alternatives --install /usr/bin/arm-linux-gnueabihf-g++ arm-linux-gnueabihf-g++ /opt/arm-bcm2708hardfp-linux-gnueabi/bin/arm-bcm2708hardfp-linux-gnueabi-g++ 46
|
||||
$ update-alternatives --install /usr/bin/arm-linux-gnueabihf-cpp arm-linux-gnueabihf-cpp /opt/arm-bcm2708hardfp-linux-gnueabi/bin/arm-bcm2708hardfp-linux-gnueabi-cpp 46
|
||||
```
|
||||
|
||||
(This way if you want to explore using other newer compilers, just add them to alternatives and the same build setup should work fine)
|
||||
|
||||
This should now have you setup ready to build for arm. It could be an idea to test at this stage with building a simple hello world executable (save your hello world test code as hello.cpp):
|
||||
|
||||
$ arm-linux-gnueabihf-g++ -O3 -g3 -Wall -fPIC -march=armv6 -mfpu=vfp -mfloat-abi=hard hello.cpp -c -o hello.o
|
||||
$ arm-linux-gnueabihf-g++ -o hello hello.o
|
||||
$ file hello
|
||||
|
||||
And you should see in the returned info that hello is built for ARM
|
||||
|
||||
With the build environment setup, now its on to building JavaCV. Not all components have been setup with the linux-armhf build configurations, so rather than building the entire project only a subset are built here, but enough to have core functionality (OpenCV, FFmpeg) working with some additional parts (artoolkitplus, flycapture, flandmark, libfreenect, libdc1394) built but not tested. For flycapture, you need to download the arm SDK (currently flycapture.2.9.3.13_armhf) and make these .so libs available, either in your path, or setting up a /usr/include/flycapture directory and moving them there.
|
||||
|
||||
Now all the dependencies are setup, the build can be started (assuming you've done a git clone of javacv, javacpp and javacpp-presets all to the same folder)
|
||||
|
||||
$ cd javacpp
|
||||
$ mvn install
|
||||
$ cd ..
|
||||
$ cd javacpp-presets
|
||||
$ ./cppbuild.sh -platform linux-armhf install
|
||||
$ mvn install -Djavacpp.platform=linux-armhf -Djavacpp.platform.compiler=arm-linux-gnueabihf-g++
|
||||
$ cd platform
|
||||
$ mvn install -Djavacpp.platform=linux-armhf
|
||||
|
||||
Hopefully that all runs OK, and then in ./javacpp-presets/platform/target/ you should find there are platform specific (opencv-linux-armhf.jar, ffmpeg-linux-armhf.jar, etc) files built.
|
||||
|
||||
If you want to try alternative flags, you need to modify in javacpp, ./src/main/resources/org/bytedeco/javacpp/properties/linux-armhf.properties and then in javacpp-presets any project cppbuild.sh file where you want to update too (e.g. ./opencv/cppbuild.sh linux-armhf section). For newer Pis on arm7 it does look like there are potential performance gains in armv7 and neon flags, and using a newer compiler rather than the bcm2708 build used here may further improve things (some earlier builds specific for armv7 did look faster). Also if you are using onboard picam devices, make sure you load the module with "modprobe bcm2835-v4l2 max_video_width=2592 max_video_height=1944" - this way if you test just using OpenCV or FFMPEG grabber you should get at least 30fps as a start point. The more computation you then do on each frame, the more this will drop.
|
||||
|
||||
|
||||
Mac OS X (x86_64)
|
||||
-----------------
|
||||
OS X Mavericks (10.9) is the first version of Mac OS X to support C++11 fully and properly, so to preserve your sanity, we do not recommend trying to build or use the JavaCPP Presets on any older versions of Mac OS X.
|
||||
|
||||
### Preparations
|
||||
1. Install [Xcode](https://developer.apple.com/xcode/) and [Homebrew](http://brew.sh/)
|
||||
2. Ensure the command line tools for Xcode are installed
|
||||
|
||||
```bash
|
||||
$ xcode-select --install
|
||||
```
|
||||
3. Run the following commands to install the JDK, among other things Apple left out of Xcode:
|
||||
|
||||
```bash
|
||||
$ brew install caskroom/cask/brew-cask
|
||||
$ brew cask install cuda java
|
||||
$ brew install gcc5 swig bazel cmake libusb maven nasm yasm xz pkg-config
|
||||
```
|
||||
|
||||
After which the following commands can be used to start the build inside the `javacpp-presets` directory:
|
||||
```bash
|
||||
$ bash cppbuild.sh install
|
||||
$ mvn clean install
|
||||
```
|
||||
|
||||
|
||||
Windows (x86 and x86_64)
|
||||
------------------------
|
||||
Visual Studio Community 2013 is the first free version to have been decently bundled with support for C++11, OpenMP, the Windows SDK, and everything else from Microsoft, so we recommend installing that version of Visual Studio, which consequently requires Windows 7. Still, to run the bash scripts and compile some things that the Microsoft C/C++ Compiler does not support, we need to install manually a few other things.
|
||||
|
||||
### Preparations
|
||||
1. Install the [Java SE Development Kit](http://www.oracle.com/technetwork/java/javase/downloads/), [Maven](https://maven.apache.org/download.cgi), [MSYS2](https://msys2.github.io/), [Visual Studio Community 2013](https://www.visualstudio.com/en-us/news/vs2013-community-vs.aspx), and [CUDA](https://developer.nvidia.com/cuda-downloads)
|
||||
2. Under an "MSYS2 Shell", run:
|
||||
|
||||
```bash
|
||||
$ pacman -S base-devel tar patch make git unzip zip nasm yasm pkg-config mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc mingw-w64-i686-gcc mingw-w64-x86_64-gcc-fortran mingw-w64-i686-gcc-fortran mingw-w64-x86_64-libwinpthread-git mingw-w64-i686-libwinpthread-git
|
||||
```
|
||||
|
||||
3. From the "Visual Studio Tools" found inside the Start menu, open:
|
||||
- "VS2013 x86 Native Tools Command Prompt" and run `c:\msys64\mingw32_shell.bat` inside
|
||||
- "VS2013 x64 Native Tools Command Prompt" and run `c:\msys64\mingw64_shell.bat` inside
|
||||
- Making sure the `set MSYS2_PATH_TYPE=inherit` line is *not* commented out in either of those batch files.
|
||||
|
||||
4. Run the "Prerequisites for all platforms" tasks inside the shell
|
||||
|
||||
Afterwards the following commands can be used to start the build inside the `javacpp-presets` directory:
|
||||
```bash
|
||||
$ bash cppbuild.sh -platform windows-xxx install
|
||||
$ mvn clean install -Djavacpp.platform=windows-xxx
|
||||
```
|
||||
where `windows-xxx` is either `windows-x86` or `windows-x86_64`. Run the builds for `windows-x86` inside the "MINGW32" window, and the ones for `windows-x86_64` in the "MINGW64" one.
|
||||
|
||||
|
||||
|
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-linux-x86.jar
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-linux-x86-h264.jar
|
||||
mkdir workdir
|
||||
cp $FFMPEG workdir/ffmpeg-linux-x86.jar
|
||||
rm -rf src
|
||||
@ -9,9 +9,9 @@ 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
|
||||
cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../../unsigned-jars/ffmpeg-linux-x86-h264-unsigned.jar
|
||||
ant sign-jar
|
||||
cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../../../app/jws/lib/ffmpeg-linux-x86.jar
|
||||
cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../../../../app/jws/lib/ffmpeg-linux-x86-h264.jar
|
||||
rm -rf workdir
|
||||
rm -rf src
|
||||
|
10
bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/svc2/build.gradle
Executable file
10
bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/svc2/build.gradle
Executable file
@ -0,0 +1,10 @@
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
sourceCompatibility=1.6
|
||||
targetCompatibility=1.6
|
||||
|
||||
version = '0.0.1'
|
||||
archivesBaseName = 'ffmpeg-linux-x86'
|
||||
|
||||
|
38
bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/svc2/build.xml
Executable file
38
bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/svc2/build.xml
Executable file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" ?>
|
||||
<project name="ffmpeg-linux-x86-signing" basedir=".">
|
||||
|
||||
<!-- Sign jar with Certificate using pkcs12 file -->
|
||||
<target name="check-certificate">
|
||||
<input message="Enter cetificate filename:" addproperty="cert.name" />
|
||||
<input message="Enter cetificate password:" addproperty="cert.password" />
|
||||
<exec executable="/usr/bin/keytool" outputproperty="cert.info">
|
||||
<arg line="-list" />
|
||||
<arg line="-storetype pkcs12" />
|
||||
<arg line="-keystore ${cert.name}" />
|
||||
<arg line="-storepass ${cert.password}" />
|
||||
<arg line="-v" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="get-alias-name" depends="check-certificate">
|
||||
<script language="javascript">
|
||||
<![CDATA[
|
||||
// getting the value
|
||||
info = project.getProperty("cert.info");
|
||||
alias = (info.match(/Alias name:(.*)/)[0]).replace("Alias name: ","");
|
||||
project.setProperty("cert.alias",alias);
|
||||
]]>
|
||||
</script>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="sign-jar" depends="get-alias-name">
|
||||
<signjar jar="build/libs/ffmpeg-linux-x86-0.0.1.jar"
|
||||
storetype="pkcs12"
|
||||
keystore="${cert.name}"
|
||||
storepass="${cert.password}"
|
||||
alias="${cert.alias}" />
|
||||
</target>
|
||||
|
||||
|
||||
</project>
|
Binary file not shown.
18
bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/svc2/sign-jar.sh
Executable file
18
bbb-screenshare/jws/native-libs/ffmpeg-linux-x86/svc2/sign-jar.sh
Executable file
@ -0,0 +1,18 @@
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-linux-x86-svc2.jar
|
||||
mkdir workdir
|
||||
cp $FFMPEG workdir/ffmpeg-linux-x86.jar
|
||||
rm -rf src
|
||||
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-svc2-unsigned.jar
|
||||
ant sign-jar
|
||||
cp build/libs/ffmpeg-linux-x86-0.0.1.jar ../../../../app/jws/lib/ffmpeg-linux-x86-svc2.jar
|
||||
rm -rf workdir
|
||||
rm -rf src
|
||||
|
||||
|
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-linux-x86_64.jar
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-linux-x86_64-h264.jar
|
||||
mkdir workdir
|
||||
cp $FFMPEG workdir/ffmpeg-linux-x86_64.jar
|
||||
rm -rf src
|
||||
@ -9,9 +9,9 @@ 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
|
||||
cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-linux-x86_64-h264-unsigned.jar
|
||||
ant sign-jar
|
||||
cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../../../app/jws/lib/ffmpeg-linux-x86_64.jar
|
||||
cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-linux-x86_64-h264.jar
|
||||
rm -rf workdir
|
||||
rm -rf src
|
||||
|
10
bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/svc2/build.gradle
Executable file
10
bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/svc2/build.gradle
Executable file
@ -0,0 +1,10 @@
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
sourceCompatibility=1.6
|
||||
targetCompatibility=1.6
|
||||
|
||||
version = '0.0.1'
|
||||
archivesBaseName = 'ffmpeg-linux-x86_64'
|
||||
|
||||
|
38
bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/svc2/build.xml
Executable file
38
bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/svc2/build.xml
Executable file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" ?>
|
||||
<project name="ffmpeg-linux-x86_64-signing" basedir=".">
|
||||
|
||||
<!-- Sign jar with Certificate using pkcs12 file -->
|
||||
<target name="check-certificate">
|
||||
<input message="Enter cetificate filename:" addproperty="cert.name" />
|
||||
<input message="Enter cetificate password:" addproperty="cert.password" />
|
||||
<exec executable="/usr/bin/keytool" outputproperty="cert.info">
|
||||
<arg line="-list" />
|
||||
<arg line="-storetype pkcs12" />
|
||||
<arg line="-keystore ${cert.name}" />
|
||||
<arg line="-storepass ${cert.password}" />
|
||||
<arg line="-v" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="get-alias-name" depends="check-certificate">
|
||||
<script language="javascript">
|
||||
<![CDATA[
|
||||
// getting the value
|
||||
info = project.getProperty("cert.info");
|
||||
alias = (info.match(/Alias name:(.*)/)[0]).replace("Alias name: ","");
|
||||
project.setProperty("cert.alias",alias);
|
||||
]]>
|
||||
</script>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="sign-jar" depends="get-alias-name">
|
||||
<signjar jar="build/libs/ffmpeg-linux-x86_64-0.0.1.jar"
|
||||
storetype="pkcs12"
|
||||
keystore="${cert.name}"
|
||||
storepass="${cert.password}"
|
||||
alias="${cert.alias}" />
|
||||
</target>
|
||||
|
||||
|
||||
</project>
|
Binary file not shown.
17
bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/svc2/sign-jar.sh
Executable file
17
bbb-screenshare/jws/native-libs/ffmpeg-linux-x86_64/svc2/sign-jar.sh
Executable file
@ -0,0 +1,17 @@
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-linux-x86_64-svc2.jar
|
||||
mkdir workdir
|
||||
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-svc2-unsigned.jar
|
||||
ant sign-jar
|
||||
cp build/libs/ffmpeg-linux-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-linux-x86_64-svc2.jar
|
||||
rm -rf workdir
|
||||
rm -rf src
|
||||
|
Binary file not shown.
16
bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/h264/sign-jar.sh
Executable file
16
bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/h264/sign-jar.sh
Executable file
@ -0,0 +1,16 @@
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-macosx-x86_64-h264.jar
|
||||
mkdir workdir
|
||||
cp $FFMPEG workdir/ffmpeg-macosx-x86_64.jar
|
||||
rm -rf src
|
||||
mkdir -p src/main/resources
|
||||
cd workdir
|
||||
jar xvf ffmpeg-macosx-x86_64.jar
|
||||
cp org/bytedeco/javacpp/macosx-x86_64/* ../src/main/resources
|
||||
cd ..
|
||||
rm -rf workdir
|
||||
gradle jar
|
||||
cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-macosx-x86_64-h264-unsigned.jar
|
||||
ant sign-jar
|
||||
cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-macosx-x86_64-h264.jar
|
||||
rm -rf src
|
||||
|
10
bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/svc2/build.gradle
Executable file
10
bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/svc2/build.gradle
Executable file
@ -0,0 +1,10 @@
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
sourceCompatibility=1.6
|
||||
targetCompatibility=1.6
|
||||
|
||||
version = '0.0.1'
|
||||
archivesBaseName = 'ffmpeg-macosx-x86_64'
|
||||
|
||||
|
38
bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/svc2/build.xml
Executable file
38
bbb-screenshare/jws/native-libs/ffmpeg-macosx-x86_64/svc2/build.xml
Executable file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" ?>
|
||||
<project name="ffmpeg-macosx-x86_64-signing" basedir=".">
|
||||
|
||||
<!-- Sign jar with Certificate using pkcs12 file -->
|
||||
<target name="check-certificate">
|
||||
<input message="Enter cetificate filename:" addproperty="cert.name" />
|
||||
<input message="Enter cetificate password:" addproperty="cert.password" />
|
||||
<exec executable="/usr/bin/keytool" outputproperty="cert.info">
|
||||
<arg line="-list" />
|
||||
<arg line="-storetype pkcs12" />
|
||||
<arg line="-keystore ${cert.name}" />
|
||||
<arg line="-storepass ${cert.password}" />
|
||||
<arg line="-v" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="get-alias-name" depends="check-certificate">
|
||||
<script language="javascript">
|
||||
<![CDATA[
|
||||
// getting the value
|
||||
info = project.getProperty("cert.info");
|
||||
alias = (info.match(/Alias name:(.*)/)[0]).replace("Alias name: ","");
|
||||
project.setProperty("cert.alias",alias);
|
||||
]]>
|
||||
</script>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="sign-jar" depends="get-alias-name">
|
||||
<signjar jar="build/libs/ffmpeg-macosx-x86_64-0.0.1.jar"
|
||||
storetype="pkcs12"
|
||||
keystore="${cert.name}"
|
||||
storepass="${cert.password}"
|
||||
alias="${cert.alias}" />
|
||||
</target>
|
||||
|
||||
|
||||
</project>
|
Binary file not shown.
@ -9,8 +9,8 @@ cp org/bytedeco/javacpp/macosx-x86_64/* ../src/main/resources
|
||||
cd ..
|
||||
rm -rf workdir
|
||||
gradle jar
|
||||
cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../unsigned-jars/ffmpeg-macosx-x86_64-unsigned.jar
|
||||
cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-macosx-x86_64-svc2-unsigned.jar
|
||||
ant sign-jar
|
||||
cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../../../app/jws/lib/ffmpeg-macosx-x86_64.jar
|
||||
cp build/libs/ffmpeg-macosx-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-macosx-x86_64-svc2.jar
|
||||
rm -rf src
|
||||
|
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-windows-x86.jar
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-windows-x86-h264.jar
|
||||
mkdir workdir
|
||||
cp $FFMPEG workdir/ffmpeg-windows-x86.jar
|
||||
rm -rf src
|
||||
@ -10,8 +10,8 @@ cp org/bytedeco/javacpp/windows-x86/*.dll ../src/main/resources
|
||||
cd ..
|
||||
rm -rf workdir
|
||||
gradle jar
|
||||
cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../unsigned-jars/ffmpeg-windows-x86-unsigned.jar
|
||||
cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../../unsigned-jars/ffmpeg-win-x86-h264-unsigned.jar
|
||||
ant sign-jar
|
||||
cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../../../app/jws/lib/ffmpeg-windows-x86.jar
|
||||
cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../../../../app/jws/lib/ffmpeg-win-x86-h264.jar
|
||||
rm -rf src
|
||||
|
10
bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/svc2/build.gradle
Executable file
10
bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/svc2/build.gradle
Executable file
@ -0,0 +1,10 @@
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
sourceCompatibility=1.6
|
||||
targetCompatibility=1.6
|
||||
|
||||
version = '0.0.1'
|
||||
archivesBaseName = 'ffmpeg-windows-x86'
|
||||
|
||||
|
38
bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/svc2/build.xml
Executable file
38
bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/svc2/build.xml
Executable file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" ?>
|
||||
<project name="ffmpeg-win-x86-signing" basedir=".">
|
||||
|
||||
<!-- Sign jar with Certificate using pkcs12 file -->
|
||||
<target name="check-certificate">
|
||||
<input message="Enter cetificate filename:" addproperty="cert.name" />
|
||||
<input message="Enter cetificate password:" addproperty="cert.password" />
|
||||
<exec executable="/usr/bin/keytool" outputproperty="cert.info">
|
||||
<arg line="-list" />
|
||||
<arg line="-storetype pkcs12" />
|
||||
<arg line="-keystore ${cert.name}" />
|
||||
<arg line="-storepass ${cert.password}" />
|
||||
<arg line="-v" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="get-alias-name" depends="check-certificate">
|
||||
<script language="javascript">
|
||||
<![CDATA[
|
||||
// getting the value
|
||||
info = project.getProperty("cert.info");
|
||||
alias = (info.match(/Alias name:(.*)/)[0]).replace("Alias name: ","");
|
||||
project.setProperty("cert.alias",alias);
|
||||
]]>
|
||||
</script>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="sign-jar" depends="get-alias-name">
|
||||
<signjar jar="build/libs/ffmpeg-windows-x86-0.0.1.jar"
|
||||
storetype="pkcs12"
|
||||
keystore="${cert.name}"
|
||||
storepass="${cert.password}"
|
||||
alias="${cert.alias}" />
|
||||
</target>
|
||||
|
||||
|
||||
</project>
|
Binary file not shown.
17
bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/svc2/sign-jar.sh
Executable file
17
bbb-screenshare/jws/native-libs/ffmpeg-windows-x86/svc2/sign-jar.sh
Executable file
@ -0,0 +1,17 @@
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-windows-x86-svc2.jar
|
||||
mkdir workdir
|
||||
cp $FFMPEG workdir/ffmpeg-windows-x86.jar
|
||||
rm -rf src
|
||||
mkdir -p src/main/resources
|
||||
mkdir -p src/main/java
|
||||
cd workdir
|
||||
jar xvf ffmpeg-windows-x86.jar
|
||||
cp org/bytedeco/javacpp/windows-x86/*.dll ../src/main/resources
|
||||
cd ..
|
||||
rm -rf workdir
|
||||
gradle jar
|
||||
cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../../unsigned-jars/ffmpeg-win-x86-svc2-unsigned.jar
|
||||
ant sign-jar
|
||||
cp build/libs/ffmpeg-windows-x86-0.0.1.jar ../../../../app/jws/lib/ffmpeg-win-x86-svc2.jar
|
||||
rm -rf src
|
||||
|
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-windows-x86_64.jar
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-windows-x86_64-h264.jar
|
||||
mkdir workdir
|
||||
cp $FFMPEG workdir/ffmpeg-windows-x86_64.jar
|
||||
rm -rf src
|
||||
@ -10,8 +10,8 @@ cp org/bytedeco/javacpp/windows-x86_64/*.dll ../src/main/resources
|
||||
cd ..
|
||||
rm -rf workdir
|
||||
gradle jar
|
||||
cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../unsigned-jars/ffmpeg-windows-x86_64-unsigned.jar
|
||||
cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-win-x86_64-h264-unsigned.jar
|
||||
ant sign-jar
|
||||
cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../../../app/jws/lib/ffmpeg-windows-x86_64.jar
|
||||
cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-win-x86_64-h264.jar
|
||||
rm -rf src
|
||||
|
10
bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/svc2/build.gradle
Executable file
10
bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/svc2/build.gradle
Executable file
@ -0,0 +1,10 @@
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
sourceCompatibility=1.6
|
||||
targetCompatibility=1.6
|
||||
|
||||
version = '0.0.1'
|
||||
archivesBaseName = 'ffmpeg-windows-x86_64'
|
||||
|
||||
|
38
bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/svc2/build.xml
Executable file
38
bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/svc2/build.xml
Executable file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" ?>
|
||||
<project name="ffmpeg-win-x86-signing" basedir=".">
|
||||
|
||||
<!-- Sign jar with Certificate using pkcs12 file -->
|
||||
<target name="check-certificate">
|
||||
<input message="Enter cetificate filename:" addproperty="cert.name" />
|
||||
<input message="Enter cetificate password:" addproperty="cert.password" />
|
||||
<exec executable="/usr/bin/keytool" outputproperty="cert.info">
|
||||
<arg line="-list" />
|
||||
<arg line="-storetype pkcs12" />
|
||||
<arg line="-keystore ${cert.name}" />
|
||||
<arg line="-storepass ${cert.password}" />
|
||||
<arg line="-v" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="get-alias-name" depends="check-certificate">
|
||||
<script language="javascript">
|
||||
<![CDATA[
|
||||
// getting the value
|
||||
info = project.getProperty("cert.info");
|
||||
alias = (info.match(/Alias name:(.*)/)[0]).replace("Alias name: ","");
|
||||
project.setProperty("cert.alias",alias);
|
||||
]]>
|
||||
</script>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="sign-jar" depends="get-alias-name">
|
||||
<signjar jar="build/libs/ffmpeg-windows-x86_64-0.0.1.jar"
|
||||
storetype="pkcs12"
|
||||
keystore="${cert.name}"
|
||||
storepass="${cert.password}"
|
||||
alias="${cert.alias}" />
|
||||
</target>
|
||||
|
||||
|
||||
</project>
|
Binary file not shown.
17
bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/svc2/sign-jar.sh
Executable file
17
bbb-screenshare/jws/native-libs/ffmpeg-windows-x86_64/svc2/sign-jar.sh
Executable file
@ -0,0 +1,17 @@
|
||||
FFMPEG=ffmpeg-3.0.2-1.2-windows-x86_64-svc2.jar
|
||||
mkdir workdir
|
||||
cp $FFMPEG workdir/ffmpeg-windows-x86_64.jar
|
||||
rm -rf src
|
||||
mkdir -p src/main/resources
|
||||
mkdir -p src/main/java
|
||||
cd workdir
|
||||
jar xvf ffmpeg-windows-x86_64.jar
|
||||
cp org/bytedeco/javacpp/windows-x86_64/*.dll ../src/main/resources
|
||||
cd ..
|
||||
rm -rf workdir
|
||||
gradle jar
|
||||
cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../../unsigned-jars/ffmpeg-win-x86_64-svc2-unsigned.jar
|
||||
ant sign-jar
|
||||
cp build/libs/ffmpeg-windows-x86_64-0.0.1.jar ../../../../app/jws/lib/ffmpeg-win-x86_64-svc2.jar
|
||||
rm -rf src
|
||||
|
BIN
bbb-screenshare/jws/native-libs/unsigned-jars/ffmpeg-3.0.2-1.2-svc2.jar
Executable file
BIN
bbb-screenshare/jws/native-libs/unsigned-jars/ffmpeg-3.0.2-1.2-svc2.jar
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user