Commit dd5f8282 authored by Dele Olajide's avatar Dele Olajide Committed by dele

Jitsi Videobridge plugin code refresh

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@13841 b35dd754-fafc-0310-a699-88a17e54d16e
parent ff3733c7
......@@ -47,7 +47,7 @@ Jitsi Video Bridge Plugin Changelog
<p><b>1.1</b> -- Dec 4th, 2013</p>
<ul>
<li>OF-716 Added to Openfire plugins with webrtc demo video application</li>
<li>OF-716 Added to Openfire plugins with jitmeet web video conference application</li>
</ul>
<p><b>1.0</b> -- Apr 12, 2013</p>
......
......@@ -63,7 +63,7 @@ Jitsi Videobridge does not mix the video channels into a composite video stream,
but only relays the received video channels to all call participants.
Therefore, while it does need to run on a server with good network bandwidth,
CPU horsepower is not that critical for performance.
A demo video conference application using WebRTC is included.
The JitMeet video conference application using WebRTC is included.
</p>
......@@ -79,7 +79,7 @@ Under Server settings -> Jitsi Videobridge tab you can configure it.
<h2>How to use</h2>
To run the demo video conference application, point your browser at https://your_server:7443/videobridge
To run the demo video conference application, point your browser at https://your_server:7443/jitmeet
</body>
</html>
......@@ -168,6 +168,7 @@ $(document).bind('callterminated.jingle', function (event, sid, reason) {
$(document).bind('joined.muc', function (event, jid, info) {
console.log('onJoinComplete', info);
updateRoomUrl(window.location.href);
showToolbar();
if (Object.keys(connection.emuc.members).length < 1) {
focus = new ColibriFocus(connection, config.hosts.bridge);
return;
......@@ -177,6 +178,7 @@ $(document).bind('joined.muc', function (event, jid, info) {
$(document).bind('entered.muc', function (event, jid, info) {
console.log('entered', jid, info);
console.log(focus);
if (focus !== null) {
// FIXME: this should prepare the video
if (focus.confid === null) {
......@@ -428,6 +430,10 @@ function openChat() {
$('#usermsg').focus();
}
function showToolbar() {
$('#toolbar').css({visibility:"visible"});
}
function updateRoomUrl(newRoomUrl) {
roomUrl = newRoomUrl;
}
Sorry, this currently only works with chrome because it uses "Plan B".
<html>
<head>
<title></title>
<link rel="stylesheet" type="text/css" media="screen" href="css/chromeonly.css" />
</head>
<body>
<!-- wrap starts here -->
<div id="wrap">
<a href="http://google.com/chrome"><div id="left"></div></a>
<div id="middle"></div>
<div id="text">
<p>This service only works with Chrome.</p>
<p><a href="http://google.com/chrome">Download Chrome</a></p>
</div>
<!-- wrap ends here -->
</div>
</body>
</html>
body {
width:100%;
height:100%;
background-color: white;
color: #424242;
font-family:'YanoneKaffeesatzLight',Verdana,Tahoma,Arial;
margin:0;
padding:0;
}
#wrap{
display: block;
position: absolute;
width:766px;
height: 262px;
overflow:hidden;
text-align: center;
margin: auto;
top: 0; left: 0; bottom: 0; right: 0;
}
#left{
display:inline-block;
background-image:url(../images/chromelogo.png);
background-repeat:no-repeat;
width:246px;
height:262px;
float: left;
}
#middle{
display:inline-block;
background-image:url(../images/chromepointer.png);
background-repeat:no-repeat;
width:53px;
height:262px;
float: left;
}
#text{
display:inline-block;
font-size: 20pt;
width: 400px;
vertical-align:middle;
padding-top: 30px;
}
a {
color: #087dba;
text-decoration:none;
}
......@@ -92,11 +92,11 @@ html, body{
visibility:hidden;
}
div.localuser {
.localuser {
color: #087dba;
}
div.remoteuser {
.remoteuser {
color: #424242;
}
......@@ -128,7 +128,7 @@ div.remoteuser {
font-size: 14;
}
div#spacer {
#spacer {
height:5px;
}
......@@ -140,17 +140,15 @@ div#spacer {
display:none;
}
div#header{
#header{
display:block;
position:relative;
width:100%;
height:39px;
z-index: 1;
text-align:center;
background-color:#087dba;
}
div#left {
#left {
display:block;
position: absolute;
left: 0px;
......@@ -163,7 +161,7 @@ div#left {
padding: 0;
}
div#leftlogo {
#leftlogo {
position:absolute;
top: 5px;
left: 15px;
......@@ -174,13 +172,14 @@ div#leftlogo {
z-index:1;
}
div#link {
#toolbar {
display:block;
position:relative;
height:39px;
width:auto;
overflow: hidden;
z-index:0;
visibility: hidden;
}
.button {
......@@ -189,10 +188,9 @@ div#link {
color: #FFFFFF;
top: 0;
padding: 10px 0px;
height: 19px;
width: 39px;
cursor: pointer;
font-size: 19px;
font-size: 11pt;
text-align: center;
text-shadow: 0px 1px 0px rgba(255,255,255,.3), 0px -1px 0px rgba(0,0,0,.7);
}
......@@ -227,7 +225,7 @@ a.button:hover {
background: -webkit-gradient(linear, 0 0, 0 100%, from(#087dba), to(#087dba), color-stop(50%, white));
}
div#right {
#right {
display:block;
position:absolute;
right: 0px;
......@@ -239,7 +237,8 @@ div#right {
width:100px;
height:39px;
}
div#rightlogo {
#rightlogo {
position:absolute;
top: 6px;
right: 15px;
......
.jqistates {
font-size: 14px;
}
.jqistates h2 {
padding-bottom: 10px;
border-bottom: 1px solid #eee;
......@@ -5,18 +9,18 @@
line-height: 25px;
text-align: center;
color: #424242;
}
}
.jqistates input {
width: 100%;
margin: 20px 0;
}
}
.jqibuttons button {
margin-right: 5px;
float:right;
}
}
button.jqidefaultbutton #inviteLinkRef {
button.jqidefaultbutton #inviteLinkRef {
color: #2c8ad2;
}
\ No newline at end of file
}
\ No newline at end of file
<html>
<head>
<title>WebRTC, meet the Jitsi Videobridge</title>
<script src="jquery.min.js"></script>
<title>JitMeet</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="libs/strophejingle.bundle.js"></script><!-- strophe.jingle bundle -->
<script src="libs/colibri.js"></script><!-- colibri focus implementation -->
<script src="muc.js"></script><!-- simple MUC library -->
<script src="app.js"></script><!-- application logic -->
<link href="font-awesome-4.0.3/css/font-awesome.css" rel="stylesheet">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="css/main.css" />
<link rel="stylesheet" href="css/jquery-impromptu.css">
<link rel="stylesheet" href="css/modaldialog.css">
......@@ -18,7 +18,7 @@
<div id="header">
<a href="http://jitsi.org" target="_blank"><div id="leftlogo"></div></a>
<a href="http://www.estos.com/" target="_blank"><div id="rightlogo"></div></a>
<div id="link">
<div id="toolbar">
<a class="button" onclick='buttonClick("#mute", "fa fa-microphone fa-lg fa fa-microphone-slash fa-lg");toggleAudio();'><i id="mute" title="Mute / unmute" class="fa fa-microphone fa-lg"></i></a>
<div class="header_button_separator"></div>
<a class="button" onclick='buttonClick("#video", "fa fa-video-camera fa-lg fa fa-video-camera no-fa-video-camera fa-lg");toggleVideo();'><i id="video" title="Start / stop camera" class="fa fa-video-camera fa-lg"></i></a>
......
package com.rayo.core.verb;
import org.xmpp.packet.*;
import org.dom4j.*;
public class AddSourceEvent extends AbstractVerbEvent {
private JID muc;
private String nickname;
private JID participant;
private Element conference;
public AddSourceEvent() {}
public AddSourceEvent(Verb verb) {
super(verb);
}
public Element getConference() {
return conference;
}
public void setConference(Element conference) {
this.conference = conference;
}
public JID getParticipant() {
return participant;
}
public void setParticipant(JID participant) {
this.participant = participant;
}
public JID getMuc() {
return muc;
}
public void setMuc(JID muc) {
this.muc = muc;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
package com.rayo.core.verb;
import org.dom4j.Element;
public class ColibriCommand extends AbstractVerbCommand {
private String videobridge;
private Element conference;
public void setVideobridge(String videobridge) {
public ColibriCommand(String videobridge, Element conference)
{
this.videobridge = videobridge;
this.conference = conference;
}
public String getVideobridge() {
public String getVideobridge()
{
return this.videobridge;
}
public Element getConference()
{
return this.conference;
}
}
package com.rayo.core.verb;
import org.xmpp.packet.*;
import org.dom4j.*;
public class ColibriOfferEvent extends AbstractVerbEvent {
private JID muc;
private String nickname;
private JID participant;
private Element conference;
public ColibriOfferEvent() {}
public ColibriOfferEvent(Verb verb) {
super(verb);
}
public Element getConference() {
return conference;
}
public void setConference(Element conference) {
this.conference = conference;
}
public JID getParticipant() {
return participant;
}
public void setParticipant(JID participant) {
this.participant = participant;
}
public JID getMuc() {
return muc;
}
public void setMuc(JID muc) {
this.muc = muc;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
package com.rayo.core.verb;
import org.xmpp.packet.*;
public class RemoveSourceEvent extends AbstractVerbEvent {
private JID muc;
private String nickname;
private JID participant;
private boolean active;
public RemoveSourceEvent() {}
public RemoveSourceEvent(Verb verb) {
super(verb);
}
public JID getParticipant() {
return participant;
}
public void setParticipant(JID participant) {
this.participant = participant;
}
public JID getMuc() {
return muc;
}
public void setMuc(JID muc) {
this.muc = muc;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public void setActive(boolean active) {
this.active = active;
}
public boolean isActive() {
return active;
}
}
......@@ -46,8 +46,9 @@ public class ColibriProvider extends BaseProvider {
private Object buildColibriCommand(Element element) throws URISyntaxException
{
String videobridge = element.attributeValue("videobridge");
ColibriCommand command = new ColibriCommand();
command.setVideobridge(videobridge);
Element conference = element.element("conference").createCopy();
ColibriCommand command = new ColibriCommand(videobridge, conference);
return command;
}
......@@ -62,6 +63,9 @@ public class ColibriProvider extends BaseProvider {
if (object instanceof ColibriCommand) {
createColibriCommand((ColibriCommand) object, document);
} else if (object instanceof ColibriOfferEvent) {
createColibriOfferEvent((ColibriOfferEvent) object, document);
} else if (object instanceof AddSourceEvent) {
createAddSourceEvent((AddSourceEvent) object, document);
......@@ -82,14 +86,34 @@ public class ColibriProvider extends BaseProvider {
root.addAttribute("videobridge", command.getVideobridge());
}
private void createColibriOfferEvent(ColibriOfferEvent event, Document document)
{
Element root = document.addElement(new QName("offer", NAMESPACE));
root.addAttribute("muc", event.getMuc().toString());
root.addAttribute("videobridge", event.getMuc().getNode());
root.addAttribute("nickname", event.getNickname());
root.addAttribute("participant", event.getParticipant().toString());
root.add(event.getConference().createCopy());
}
private void createAddSourceEvent(AddSourceEvent event, Document document)
{
document.addElement(new QName("addsource", NAMESPACE));
Element root = document.addElement(new QName("addsource", NAMESPACE));
root.addAttribute("muc", event.getMuc().toString());
root.addAttribute("videobridge", event.getMuc().getNode());
root.addAttribute("nickname", event.getNickname());
root.addAttribute("participant", event.getParticipant().toString());
root.add(event.getConference().createCopy());
}
private void createRemoveSourceEvent(RemoveSourceEvent event, Document document)
{
document.addElement(new QName("removesource", NAMESPACE));
Element root = document.addElement(new QName("removesource", NAMESPACE));
root.addAttribute("muc", event.getMuc().toString());
root.addAttribute("videobridge", event.getMuc().getNode());
root.addAttribute("nickname", event.getNickname());
root.addAttribute("participant", event.getParticipant().toString());
root.addAttribute("active", event.isActive() ? "true" : "false");
}
private void createMutedEvent(MutedEvent muted, Document document)
......
......@@ -18,6 +18,7 @@ import org.jitsi.service.neomedia.*;
import org.jitsi.util.*;
import org.jitsi.videobridge.*;
import org.jivesoftware.openfire.container.*;
import org.jivesoftware.openfire.muc.*;
import org.jivesoftware.util.*;
import org.jivesoftware.openfire.http.HttpBindManager;
import org.jivesoftware.openfire.XMPPServer;
......@@ -158,7 +159,7 @@ public class PluginImpl implements Plugin, PropertyEventListener
component = null;
}
destroyIQHandlers();
//destroyIQHandlers();
}
/**
......@@ -188,7 +189,7 @@ public class PluginImpl implements Plugin, PropertyEventListener
WebAppContext context = new WebAppContext(contexts, pluginDirectory.getPath(), "/" + appName);
context.setWelcomeFiles(new String[]{"index.html"});
createIQHandlers();
//createIQHandlers();
}
catch(Exception e) {
......@@ -496,14 +497,18 @@ public class PluginImpl implements Plugin, PropertyEventListener
*
*/
private class ColibriIQHandler extends IQHandler
private class ColibriIQHandler extends IQHandler implements MUCEventListener
{
private ConcurrentHashMap<String, LocalClientSession> sessions;
private ConcurrentHashMap<String, FocusAgent> sessions;
private MultiUserChatManager mucManager;
public ColibriIQHandler()
{
super("Rayo: XEP 0327 - Colibri");
sessions = new ConcurrentHashMap<String, LocalClientSession>();
sessions = new ConcurrentHashMap<String, FocusAgent>();
MUCEventDispatcher.addListener(this);
mucManager = XMPPServer.getInstance().getMultiUserChatManager();
}
/**
......@@ -523,6 +528,10 @@ public class PluginImpl implements Plugin, PropertyEventListener
if (object instanceof ColibriCommand) {
ColibriCommand command = (ColibriCommand) object;
reply = handleColibriCommand(command, iq);
} else {
reply = IQ.createResultIQ(iq);
reply.setError(PacketError.Condition.not_allowed);
}
return reply;
......@@ -549,10 +558,28 @@ public class PluginImpl implements Plugin, PropertyEventListener
IQ reply = IQ.createResultIQ(iq);
String vBridge = command.getVideobridge();
Element conference = command.getConference();
if (vBridge != null)
{
createColibriFocus(vBridge);
String focusAgentName = "colibri.focus.agent." + vBridge;
JID user = iq.getFrom();
if (sessions.containsKey(focusAgentName))
{
FocusAgent focusAgent = sessions.get(focusAgentName);
if (focusAgent.isUser(user))
{
focusAgent.handleColibriCommand(reply, user, conference);
} else {
reply.setError(PacketError.Condition.item_not_found);
}
} else {
reply.setError(PacketError.Condition.not_allowed);
}
}
return reply;
......@@ -561,26 +588,102 @@ public class PluginImpl implements Plugin, PropertyEventListener
*
*
*/
private void createColibriFocus(String vBridge)
public void roomCreated(JID roomJID)
{
}
/**
*
*
*/
public void roomDestroyed(JID roomJID)
{
Log.info("ColibriIQHandler createColibriFocus " + vBridge);
LocalClientSession session;
if (sessions.containsKey(vBridge))
}
/**
*
*
*/
public void occupantJoined(JID roomJID, JID user, String nickname)
{
MUCRoom mucRoom = mucManager.getMultiUserChatService(roomJID).getChatRoom(roomJID.getNode());
Log.info("ColibriIQHandler occupantJoined " + roomJID + " " + user + " " + nickname);
String focusAgentName = "colibri.focus.agent." + roomJID.getNode();
FocusAgent focusAgent;
Participant participant = new Participant(nickname, user);
if (sessions.containsKey(focusAgentName))
{
session = sessions.get(vBridge);
focusAgent = sessions.get(focusAgentName);
} else {
WSConnection wsConnection = new WSConnection(vBridge, vBridge);
session = SessionManager.getInstance().createClientSession(wsConnection, new BasicStreamID(vBridge + "-" + System.currentTimeMillis() ) );
wsConnection.setRouter( new SessionPacketRouter(session));
AuthToken authToken = new AuthToken(vBridge, true);
session.setAuthToken(authToken, vBridge);
sessions.put(vBridge, session);
focusAgent = new FocusAgent(focusAgentName, roomJID);
LocalClientSession session = SessionManager.getInstance().createClientSession(focusAgent, new BasicStreamID(focusAgentName + "-" + System.currentTimeMillis() ) );
focusAgent.setRouter( new SessionPacketRouter(session));
AuthToken authToken = new AuthToken(focusAgentName, true);
session.setAuthToken(authToken, focusAgentName);
sessions.put(focusAgentName, focusAgent);
Presence presence = new Presence();
wsConnection.getRouter().route(presence);
focusAgent.getRouter().route(presence);
}
focusAgent.createColibriChannel(participant);
}
/**
*
*
*/
public void occupantLeft(JID roomJID, JID user)
{
MUCRoom mucRoom = mucManager.getMultiUserChatService(roomJID).getChatRoom(roomJID.getNode());
Log.info("ColibriIQHandler occupantLeft " + roomJID + " " + user);
String focusAgentName = "colibri.focus.agent." + roomJID.getNode();
if (sessions.containsKey(focusAgentName))
{
FocusAgent focusAgent = sessions.get(focusAgentName);
focusAgent.removeColibriChannel(user);
}
}
/**
*
*
*/
public void nicknameChanged(JID roomJID, JID user, String oldNickname, String newNickname)
{
}
/**
*
*
*/
public void messageReceived(JID roomJID, JID user, String nickname, Message message)
{
}
/**
*
*
*/
public void roomSubjectChanged(JID roomJID, JID user, String newSubject)
{
}
/**
*
*
*/
public void privateMessageRecieved(JID a, JID b, Message message)
{
}
}
......@@ -626,22 +729,240 @@ public class PluginImpl implements Plugin, PropertyEventListener
}
}
public class WSConnection extends VirtualConnection
/**
*
*
*/
public class Participant
{
/**
*
*
*/
public String audioChannelId;
/**
*
*
*/
public String videoChannelId;
/**
*
*
*/
private String nickname;
/**
*
*
*/
private JID user;
/**
*
*
*/
public Participant(String nickname, JID user) {
this.nickname = nickname;
this.user = user;
}
/**
*
*
*/
public String getNickname() {
return nickname;
}
/**
*
*
*/
public String toString() {
return user + " " + nickname;
}
/**
*
*
*/
public JID getUser() {
return user;
}
}
public class FocusAgent extends VirtualConnection
{
private SessionPacketRouter router;
private String remoteAddr;
private String hostName;
private String focusName;
private JID roomJid;
private String focusId = null;
private int count = 0;
private LocalClientSession session;
private Participant firstParticipant;
private String domainName = XMPPServer.getInstance().getServerInfo().getXMPPDomain();
public ConcurrentHashMap<String, Participant> users = new ConcurrentHashMap<String, Participant>();
public ConcurrentHashMap<String, Participant> ids = new ConcurrentHashMap<String, Participant>();
public ConcurrentHashMap<String, Participant> channels = new ConcurrentHashMap<String, Participant>();
/**
*
*
*/
public WSConnection( String remoteAddr, String hostName ) {
this.remoteAddr = remoteAddr;
this.hostName = hostName;
public FocusAgent(String focusName, JID roomJid) {
this.focusName = focusName;
this.roomJid = roomJid;
}
/**
*
*
*/
public void notifyUser(Participant participant, Element conference)
{
routeColibriEvent(participant, conference, true);
}
/**
*
*
*/
public void answerUser(Participant participant, Element conference)
{
String nickname = participant.getNickname();
IQ iq = new IQ(IQ.Type.set);
iq.setFrom(XMPPServer.getInstance().createJID(focusName, focusName));
iq.setTo("jitsi-videobridge." + domainName);
String id = nickname + "-" + System.currentTimeMillis();
ids.put(id, participant);
iq.setID(id);
iq.setChildElement(conference.createCopy());
router.route(iq);
routeColibriEvent(participant, conference, true);
}
/**
*
*
*/
public void addUser(Participant participant, Element conference)
{
users.put(participant.getUser().toString(), participant);
Presence presence = new Presence();
presence.setFrom(XMPPServer.getInstance().createJID(focusName, focusName));
presence.setTo(participant.getUser());
ColibriOfferEvent event = new ColibriOfferEvent();
event.setMuc(roomJid);
event.setNickname(participant.getNickname());
event.setParticipant(participant.getUser());
event.setConference(conference);
presence.getElement().add(colibriProvider.toXML(event));
router.route(presence);
for ( Iterator i = conference.elementIterator("content"); i.hasNext(); )
{
Element content = (Element) i.next();
Element channel = content.element("channel");
if ("audio".equals(content.attributeValue("name")))
{
participant.audioChannelId = channel.attributeValue("id");
channels.put(participant.audioChannelId, participant);
} else {
participant.videoChannelId = channel.attributeValue("id");
channels.put(participant.videoChannelId, participant);
}
}
}
/**
*
*
*/
public void updateUser(Participant participant, Element conference)
{
}
/**
*
*
*/
public boolean isUser(JID user)
{
return users.containsKey(user.toString());
}
/**
*
*
*/
public void createColibriChannel(Participant participant)
{
Log.info("createColibriChannel " + participant + " " + count);
count++;
if (count == 1)
{
firstParticipant = participant; // can't start until we have at least 2 people
return;
}
String nickname = participant.getNickname();
IQ iq = new IQ(IQ.Type.get);
iq.setFrom(XMPPServer.getInstance().createJID(focusName, focusName));
iq.setTo("jitsi-videobridge." + domainName);
String id = nickname + "-" + System.currentTimeMillis();
ids.put(id, participant);
iq.setID(id);
Element conferenceIq = iq.setChildElement("conference", "http://jitsi.org/protocol/colibri");
if (focusId != null)
{
conferenceIq.addAttribute("id", focusId);
}
Element audioContent = conferenceIq.addElement("content").addAttribute("name", "audio");
audioContent.addElement("channel").addAttribute("initiator", "true").addAttribute("expire", "15");
Element videoContent = conferenceIq.addElement("content").addAttribute("name", "video");
videoContent.addElement("channel").addAttribute("initiator", "true").addAttribute("expire", "15");
router.route(iq);
}
/**
*
*
*/
public void removeColibriChannel(JID user)
{
String username = user.toString();
count--;
if (count <= 1)
{
focusId = null; // invalidate current focus session
count = 0;
}
if (users.containsKey(username))
{
Participant participant = users.remove(username);
routeColibriEvent(participant, null, false);
}
Log.info("removeColibriChannel " + count);
}
/**
*
*
*/
public void handleColibriCommand(IQ reply, JID user, Element conference)
{
reply.setError(PacketError.Condition.not_allowed); // not implemented
}
/**
*
*
......@@ -664,7 +985,7 @@ public class PluginImpl implements Plugin, PropertyEventListener
*/
public void closeVirtualConnection()
{
Log.debug("WSConnection - close ");
Log.debug("FocusAgent - close ");
}
/**
......@@ -672,18 +993,18 @@ public class PluginImpl implements Plugin, PropertyEventListener
*
*/
public byte[] getAddress() {
return remoteAddr.getBytes();
return focusName.getBytes();
}
/**
*
*
*/
public String getHostAddress() {
return remoteAddr;
return focusName;
}
public String getHostName() {
return ( hostName != null ) ? hostName : "0.0.0.0";
return "0.0.0.0";
}
/**
*
......@@ -698,7 +1019,81 @@ public class PluginImpl implements Plugin, PropertyEventListener
*/
public void deliver(Packet packet) throws UnauthorizedException
{
deliverRawText(packet.toXML());
Log.info("FocusAgent deliver\n" + packet);
IQ iq = (IQ) packet;
if (iq.getType() == IQ.Type.result)
{
Element conference = iq.getChildElement().createCopy();
focusId = conference.attributeValue("id");
String id = packet.getID();
if (ids.containsKey(id))
{
Participant participant = ids.remove(id);
if (users.containsKey(participant.getUser().toString()))
updateUser(participant, conference);
else
addUser(participant, conference);
Log.info("FocusAgent response for user " + participant + " " + focusId + "\n" + conference);
} else Log.error("FocusAgent deliver cannot find iq owner " + id + "\n" + packet);
if (firstParticipant != null) // send pending channel request for first participant
{
createColibriChannel(firstParticipant);
firstParticipant = null;
}
} else if (iq.getType() == IQ.Type.error) {
focusId = null; // error
count = 0;
Log.error("Videobrideg error \n" + packet);
for (Participant reciepient : users.values())
{
Log.info("routeColibriEvent - E " + reciepient);
sendRayoEvent(reciepient, null, false, reciepient);
}
} else if (iq.getType() == IQ.Type.set || iq.getType() == IQ.Type.get) {
JID user = iq.getFrom();
Element root = iq.getChildElement();
Element conference = null;
if (user.toString().equals("jitsi-videobridge." + domainName)) // SSRC notification from videobridge
{
/*
conference = root.createCopy();
String channelId = conference.element("content").element("channel").attributeValue("id");
if (channels.containsKey(channelId))
notifyUser(channels.get(channelId), conference);
else Log.error("FocusAgent deliver cannot find channel owner " + channelId + "\n" + packet);
*/
} else {
conference = root.element("conference").createCopy(); // rayo from participant
IQ reply = IQ.createResultIQ(iq);
if (users.containsKey(user.toString()))
answerUser(users.get(user.toString()), conference);
else
reply.setError(PacketError.Condition.not_allowed);
router.route(reply);
}
} else {
Log.warn("Unexpected Videobrideg message \n" + packet);
}
}
/**
*
......@@ -706,7 +1101,56 @@ public class PluginImpl implements Plugin, PropertyEventListener
*/
public void deliverRawText(String text)
{
Log.debug("FocusAgent deliverRawText\n" + text);
}
/**
*
*
*/
private void routeColibriEvent(Participant participant, Element conference, boolean isAdd)
{
Log.info("routeColibriEvent - P " + participant);
for (Participant reciepient : users.values())
{
if (participant.getUser().toString().equals(reciepient.getUser().toString()) == false)
{
Log.info("routeColibriEvent - R " + reciepient);
sendRayoEvent(reciepient, conference, isAdd, participant);
}
}
}
/**
*
*
*/
private void sendRayoEvent(Participant reciepient, Element conference, boolean isAdd, Participant participant)
{
Presence presence = new Presence();
presence.setFrom(XMPPServer.getInstance().createJID(focusName, focusName));
presence.setTo(reciepient.getUser());
if (isAdd)
{
AddSourceEvent event = new AddSourceEvent();
event.setMuc(roomJid);
event.setNickname(participant.getNickname());
event.setParticipant(participant.getUser());
event.setConference(conference);
presence.getElement().add(colibriProvider.toXML(event));
} else {
RemoveSourceEvent event = new RemoveSourceEvent();
event.setMuc(roomJid);
event.setNickname(participant.getNickname());
event.setParticipant(participant.getUser());
event.setActive(focusId != null);
presence.getElement().add(colibriProvider.toXML(event));
}
router.route(presence);
}
/**
*
......
......@@ -7,6 +7,7 @@ Strophe.addConnectionPlugin('emuc', {
roomjid: null,
myroomjid: null,
members: {},
joined: false,
isOwner: false,
init: function (conn) {
this.connection = conn;
......@@ -23,7 +24,7 @@ Strophe.addConnectionPlugin('emuc', {
}
var join = $pres({to: this.myroomjid }).c('x', {xmlns: 'http://jabber.org/protocol/muc'});
if (password !== null) {
if (password !== undefined) {
join.c('password').t(password);
}
this.connection.send(join);
......@@ -47,10 +48,14 @@ Strophe.addConnectionPlugin('emuc', {
member.show = $(pres).find('>show').text();
member.status = $(pres).find('>status').text();
var tmp = $(pres).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>item');
member.affilication = tmp.attr('affiliation');
member.affiliation = tmp.attr('affiliation');
member.role = tmp.attr('role');
if (from == this.myroomjid) {
$(document).trigger('joined.muc', [from, member]);
if (member.affiliation == 'owner') this.isOwner = true;
if (!this.joined) {
this.joined = true;
$(document).trigger('joined.muc', [from, member]);
}
} else if (this.members[from] === undefined) {
// new participant
this.members[from] = member;
......
Sorry, webrtc is required for this and your browser does not seem to support it.
<html>
<head>
<title></title>
<link rel="stylesheet" type="text/css" media="screen" href="css/chromeonly.css" />
</head>
<body>
<!-- wrap starts here -->
<div id="wrap">
<a href="http://google.com/chrome"><div id="left"></div></a>
<div id="middle"></div>
<div id="text">
<p>This service only works with Chrome.</p>
<p><a href="http://google.com/chrome">Download Chrome</a></p>
</div>
<!-- wrap ends here -->
</div>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment