Commit 0b70bf1f authored by Dele Olajide's avatar Dele Olajide

ofmeet plugin version 0.1.7

Logs openfire meeting audit events with Openfire security auditor
Logs meeting SIP calls via SIP plugin
Added support for audio conferencing meetings (no video)
Updated Jitsi Videobridge
parent 0d48af65
...@@ -49,6 +49,15 @@ ...@@ -49,6 +49,15 @@
Openfire Meetings Plugin Changelog Openfire Meetings Plugin Changelog
</h1> </h1>
<p><b>0.1.7</b> -- May 13th, 2015</p>
<ul>
<li>Logs openfire meeting audit events with Openfire security auditor</li>
<li>Logs meeting SIP calls via SIP plugin</li>
<li>Added support for audio conferencing meetings (no video)</li>
<li>Updated Jitsi Videobridge</li>
</ul>
<p><b>0.1.6</b> -- May 9th, 2015</p> <p><b>0.1.6</b> -- May 9th, 2015</p>
<ul> <ul>
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
<name>Openfire Meetings</name> <name>Openfire Meetings</name>
<description>Provides high quality, scalable video conferences using Jitsi Meet and Jitsi Videobridge</description> <description>Provides high quality, scalable video conferences using Jitsi Meet and Jitsi Videobridge</description>
<author>Ignite Realtime</author> <author>Ignite Realtime</author>
<version>0.1.6</version> <version>0.1.7</version>
<date>05/09/2015</date> <date>05/13/2015</date>
<minServerVersion>3.9.9</minServerVersion> <minServerVersion>3.9.9</minServerVersion>
<adminconsole> <adminconsole>
......
...@@ -17,6 +17,13 @@ ...@@ -17,6 +17,13 @@
var visible = false; var visible = false;
var joined = false; var joined = false;
function urlParam(name)
{
var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
if (!results) { return undefined; }
return unescape(results[1] || undefined);
};
$(document).bind('ofmeet.connected', function (event, connection) $(document).bind('ofmeet.connected', function (event, connection)
{ {
console.log("ofmeet connected", connection); console.log("ofmeet connected", connection);
...@@ -55,7 +62,7 @@ ...@@ -55,7 +62,7 @@
$(document).bind('ofmeet.ready', function () $(document).bind('ofmeet.ready', function ()
{ {
console.log("ofmeet.ready"); console.log("ofmeet.ready");
ofmeet.connect(); ofmeet.connect(urlParam("novideo"));
}); });
$(document).ready(function () $(document).ready(function ()
......
...@@ -211,8 +211,20 @@ function obtainAudioAndVideoPermissions(callback) { ...@@ -211,8 +211,20 @@ function obtainAudioAndVideoPermissions(callback) {
video: stream.getVideoTracks().length video: stream.getVideoTracks().length
}); });
} }
var media = ['audio', 'video'];
var resolution = config.resolution || '360';
if (urlParam("novideo"))
{
media = ['audio'];
resolution = null;
}
console.log("using media", media);
getUserMediaWithConstraints( getUserMediaWithConstraints(
['audio', 'video'], media,
cb, cb,
function (error) { function (error) {
console.error('failed to obtain audio/video stream - trying audio only', error); console.error('failed to obtain audio/video stream - trying audio only', error);
...@@ -231,7 +243,7 @@ function obtainAudioAndVideoPermissions(callback) { ...@@ -231,7 +243,7 @@ function obtainAudioAndVideoPermissions(callback) {
} }
); );
}, },
config.resolution || '360'); resolution);
} }
function maybeDoJoin() { function maybeDoJoin() {
...@@ -285,6 +297,13 @@ function doJoin() { ...@@ -285,6 +297,13 @@ function doJoin() {
roomName, doJoinAfterFocus); roomName, doJoinAfterFocus);
} }
function urlParam(name)
{
var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
if (!results) { return undefined; }
return unescape(results[1] || undefined);
};
function doJoinAfterFocus() { function doJoinAfterFocus() {
var roomjid; var roomjid;
......
...@@ -24046,6 +24046,11 @@ var ofmeet = (function(of) ...@@ -24046,6 +24046,11 @@ var ofmeet = (function(of)
} }
VideoLayout.updateLargeVideo(localVideoSrc, 0, VideoLayout.updateLargeVideo(localVideoSrc, 0,
myResourceJid); myResourceJid);
if (stream.getVideoTracks().length == 0)
{
localVideoSelector.css("display", "none");
}
}; };
...@@ -31184,7 +31189,7 @@ var ofmeet = (function(of) ...@@ -31184,7 +31189,7 @@ var ofmeet = (function(of)
var sessionTerminated = false; var sessionTerminated = false;
function connectOpenfire(jid, password) function connectOpenfire(jid, password, novideo)
{ {
//console.log("connect", jid, password); //console.log("connect", jid, password);
...@@ -31269,7 +31274,7 @@ var ofmeet = (function(of) ...@@ -31269,7 +31274,7 @@ var ofmeet = (function(of)
} }
$(document).trigger('ofmeet.connected', [connection]); $(document).trigger('ofmeet.connected', [connection]);
}); }, novideo);
} else if (status === Strophe.Status.CONNFAIL) { } else if (status === Strophe.Status.CONNFAIL) {
...@@ -31293,18 +31298,30 @@ var ofmeet = (function(of) ...@@ -31293,18 +31298,30 @@ var ofmeet = (function(of)
* We ask for audio and video combined stream in order to get permissions and * We ask for audio and video combined stream in order to get permissions and
* not to ask twice. * not to ask twice.
*/ */
function obtainAudioAndVideoPermissions(callback) { function obtainAudioAndVideoPermissions(callback, novideo) {
// Get AV // Get AV
var cb = function (stream) { var cb = function (stream) {
//console.log('got', stream, stream.getAudioTracks().length, stream.getVideoTracks().length); console.log('got', stream, stream.getAudioTracks().length, stream.getVideoTracks().length);
callback(stream); callback(stream);
trackUsage('localMedia', { trackUsage('localMedia', {
audio: stream.getAudioTracks().length, audio: stream.getAudioTracks().length,
video: stream.getVideoTracks().length video: stream.getVideoTracks().length
}); });
} }
var media = ['audio', 'video'];
var resolution = config.resolution || '360';
if (novideo)
{
media = ['audio'];
resolution = null;
}
console.log("using media", media);
getUserMediaWithConstraints( getUserMediaWithConstraints(
['audio', 'video'], media,
cb, cb,
function (error) { function (error) {
console.error('failed to obtain audio/video stream - trying audio only', error); console.error('failed to obtain audio/video stream - trying audio only', error);
...@@ -31323,7 +31340,7 @@ var ofmeet = (function(of) ...@@ -31323,7 +31340,7 @@ var ofmeet = (function(of)
} }
); );
}, },
config.resolution || '360'); resolution);
} }
function generateRoomName() { function generateRoomName() {
...@@ -32534,7 +32551,9 @@ var ofmeet = (function(of) ...@@ -32534,7 +32551,9 @@ var ofmeet = (function(of)
if (username && password) if (username && password)
{ {
headers = {"Authorization": "Basic " + btoa(username + ":" + password)} headers = {"Authorization": "Basic " + btoa(username + ":" + password)};
of.username = username;
of.password = password;
} }
$.ajax({type: "GET", url: "/ofmeet/config", dataType: "script", headers: headers}).done(function() $.ajax({type: "GET", url: "/ofmeet/config", dataType: "script", headers: headers}).done(function()
...@@ -32631,7 +32650,7 @@ var ofmeet = (function(of) ...@@ -32631,7 +32650,7 @@ var ofmeet = (function(of)
setAudioMuted(!isAudioMuted()); setAudioMuted(!isAudioMuted());
} }
of.connect = function connect(username, password) of.connect = function connect(novideo)
{ {
RTC = setupRTC(); RTC = setupRTC();
...@@ -32642,7 +32661,7 @@ var ofmeet = (function(of) ...@@ -32642,7 +32661,7 @@ var ofmeet = (function(of)
} }
var jid = config.hosts.domain; var jid = config.hosts.domain;
if (username) jid = username + "@" + config.hosts.domain; if (of.username) jid = of.username + "@" + config.hosts.domain;
if (config.userName) if (config.userName)
{ {
...@@ -32650,7 +32669,7 @@ var ofmeet = (function(of) ...@@ -32650,7 +32669,7 @@ var ofmeet = (function(of)
authenticatedUser = true; authenticatedUser = true;
} }
connectOpenfire(jid, password); connectOpenfire(jid, of.password, novideo);
} }
of.leaveRoom = function leaveRoom() of.leaveRoom = function leaveRoom()
...@@ -88,7 +88,11 @@ window.addEventListener("load", function() ...@@ -88,7 +88,11 @@ window.addEventListener("load", function()
$(document).bind('inum.cleared', function(event, callId) $(document).bind('inum.cleared', function(event, callId)
{ {
console.log("inum.cleared", callId); console.log("inum.cleared", callId);
dialer.setLabel("Call");
dialer.setState("inactive");
dialer.call = null
stopTone();
}); });
$(document).bind('inum.dialled', function (event, confId, to, callId) $(document).bind('inum.dialled', function (event, confId, to, callId)
......
...@@ -143,6 +143,8 @@ public class CallSession ...@@ -143,6 +143,8 @@ public class CallSession
public String callId; public String callId;
public String focusJID; public String focusJID;
public String roomJID; public String roomJID;
public String username;
public long startTimestamp = 0;
private CallControlComponent callControl; private CallControlComponent callControl;
......
...@@ -57,7 +57,7 @@ public class JicofoPlugin ...@@ -57,7 +57,7 @@ public class JicofoPlugin
{ {
Log.info("JicofoPlugin - using focus " + focusUserJid + ":" + hostName); Log.info("JicofoPlugin - using focus " + focusUserJid + ":" + hostName);
System.setProperty("org.jitsi.videobridge.ofmeet.audio.mixer", JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.audio.mixer", "false")); //System.setProperty("org.jitsi.videobridge.ofmeet.audio.mixer", JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.audio.mixer", "false"));
System.setProperty("net.java.sip.communicator.service.gui.ALWAYS_TRUST_MODE_ENABLED", "true"); System.setProperty("net.java.sip.communicator.service.gui.ALWAYS_TRUST_MODE_ENABLED", "true");
System.setProperty(FocusManager.HOSTNAME_PNAME, hostName); System.setProperty(FocusManager.HOSTNAME_PNAME, hostName);
......
...@@ -25,6 +25,8 @@ import org.jivesoftware.openfire.SessionManager; ...@@ -25,6 +25,8 @@ import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.muc.*; import org.jivesoftware.openfire.muc.*;
import org.jivesoftware.openfire.session.*; import org.jivesoftware.openfire.session.*;
import org.jivesoftware.database.DbConnectionManager;
import java.sql.*;
import org.slf4j.*; import org.slf4j.*;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -159,7 +161,7 @@ public class CallControlComponent extends AbstractComponent ...@@ -159,7 +161,7 @@ public class CallControlComponent extends AbstractComponent
sendPacket(iq); sendPacket(iq);
} }
private void makeCall(Conference conference, String confJid, String to, String callId) private void makeCall(Conference conference, String confJid, String to, String callId, String username, long startTimestamp)
{ {
Log.info("CallControlComponent - makeCall " + confJid + " " + to + " " + callId); Log.info("CallControlComponent - makeCall " + confJid + " " + to + " " + callId);
...@@ -267,6 +269,8 @@ public class CallControlComponent extends AbstractComponent ...@@ -267,6 +269,8 @@ public class CallControlComponent extends AbstractComponent
cs.jabberRemote = to; cs.jabberRemote = to;
cs.jabberLocal = from; cs.jabberLocal = from;
cs.username = username;
cs.startTimestamp = startTimestamp;
SipService.sendInvite(cs); SipService.sendInvite(cs);
...@@ -280,11 +284,12 @@ public class CallControlComponent extends AbstractComponent ...@@ -280,11 +284,12 @@ public class CallControlComponent extends AbstractComponent
{ {
Log.info("hangupCall " + callId); Log.info("hangupCall " + callId);
CallSession cs = callSessions.get(callId); CallSession cs = callSessions.remove(callId);
if (cs != null) if (cs != null)
{ {
SipService.sendBye(cs); SipService.sendBye(cs);
updateCallRecord(cs.startTimestamp, (int)(System.currentTimeMillis() - cs.startTimestamp));
} else { } else {
Log.error("CallControlComponent hangup. cannot fine callid " + callId); Log.error("CallControlComponent hangup. cannot fine callid " + callId);
...@@ -379,6 +384,12 @@ public class CallControlComponent extends AbstractComponent ...@@ -379,6 +384,12 @@ public class CallControlComponent extends AbstractComponent
} }
} }
if (session != null)
{
long startTimestamp = System.currentTimeMillis();
session.startTimestamp = startTimestamp;
createCallRecord("admin", from, confJID, startTimestamp, 0, "received");
}
return session; return session;
} }
...@@ -455,7 +466,12 @@ public class CallControlComponent extends AbstractComponent ...@@ -455,7 +466,12 @@ public class CallControlComponent extends AbstractComponent
hangup.addElement("header").addAttribute("name", "caller_id").addAttribute("value", session.jabberRemote); hangup.addElement("header").addAttribute("name", "caller_id").addAttribute("value", session.jabberRemote);
hangup.addElement("header").addAttribute("name", "called_id").addAttribute("value", session.jabberLocal); hangup.addElement("header").addAttribute("name", "called_id").addAttribute("value", session.jabberLocal);
callSessions.remove(callId); CallSession cs = callSessions.remove(callId);
if (cs != null)
{
updateCallRecord(cs.startTimestamp, (int)(System.currentTimeMillis() - cs.startTimestamp));
}
} }
sendPacket(presence); sendPacket(presence);
...@@ -548,7 +564,11 @@ public class CallControlComponent extends AbstractComponent ...@@ -548,7 +564,11 @@ public class CallControlComponent extends AbstractComponent
if (conference != null) if (conference != null)
{ {
makeCall(conference, confJid, to, callId); String username = iq.getFrom().getNode();
long startTimestamp = System.currentTimeMillis();
makeCall(conference, confJid, to, callId, username, startTimestamp);
createCallRecord(username, confJid, to, startTimestamp, 0, "dialed");
} else { } else {
Log.error("CallControlComponent - can't find conference " + confId); Log.error("CallControlComponent - can't find conference " + confId);
...@@ -711,4 +731,70 @@ public class CallControlComponent extends AbstractComponent ...@@ -711,4 +731,70 @@ public class CallControlComponent extends AbstractComponent
Log.error("CallControlComponent sendPacket ", e); Log.error("CallControlComponent sendPacket ", e);
} }
} }
private void createCallRecord(String username, String addressFrom, String addressTo, long datetime, int duration, String calltype)
{
boolean sipPlugin = XMPPServer.getInstance().getPluginManager().getPlugin("sip") != null;
if (sipPlugin)
{
Log.info("createCallRecord " + username + " " + addressFrom + " " + addressTo + " " + datetime);
String sql = "INSERT INTO ofSipPhoneLog (username, addressFrom, addressTo, datetime, duration, calltype) values (?, ?, ?, ?, ?, ?)";
Connection con = null;
PreparedStatement psmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
psmt = con.prepareStatement(sql);
psmt.setString(1, username);
psmt.setString(2, addressFrom);
psmt.setString(3, addressTo);
psmt.setLong(4, datetime);
psmt.setInt(5, duration);
psmt.setString(6, calltype);
psmt.executeUpdate();
} catch (SQLException e) {
Log.error(e.getMessage(), e);
} finally {
DbConnectionManager.closeConnection(rs, psmt, con);
}
}
}
private void updateCallRecord(long datetime, int duration)
{
boolean sipPlugin = XMPPServer.getInstance().getPluginManager().getPlugin("sip") != null;
if (sipPlugin)
{
Log.info("updateCallRecord " + datetime + " " + duration);
String sql = "UPDATE ofSipPhoneLog SET duration = ? WHERE datetime = ?";
Connection con = null;
PreparedStatement psmt = null;
try {
con = DbConnectionManager.getConnection();
psmt = con.prepareStatement(sql);
psmt.setInt(1, duration);
psmt.setLong(2, (datetime / 1000));
psmt.executeUpdate();
} catch (SQLException e) {
Log.error(e.getMessage(), e);
} finally {
DbConnectionManager.closeConnection(psmt, con);
}
}
}
} }
...@@ -18,6 +18,11 @@ import java.util.concurrent.*; ...@@ -18,6 +18,11 @@ import java.util.concurrent.*;
import org.slf4j.*; import org.slf4j.*;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.jivesoftware.openfire.security.SecurityAuditManager;
import org.jivesoftware.util.*;
import org.xmpp.packet.*;
/** /**
* Allows logging of {@link org.jitsi.videobridge.log.Event}s using an * Allows logging of {@link org.jitsi.videobridge.log.Event}s using an
* <tt>Openfire</tt> instance. * <tt>Openfire</tt> instance.
...@@ -55,7 +60,7 @@ public class OpenfireEventService implements LoggingService ...@@ -55,7 +60,7 @@ public class OpenfireEventService implements LoggingService
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public void logEvent(Event e) public void logEvent(final Event e)
{ {
// The following is a sample JSON message in the format used by InfluxDB // The following is a sample JSON message in the format used by InfluxDB
// [ // [
...@@ -101,7 +106,7 @@ public class OpenfireEventService implements LoggingService ...@@ -101,7 +106,7 @@ public class OpenfireEventService implements LoggingService
@Override @Override
public void run() public void run()
{ {
sendPost(jsonString); sendPost(e.getName(), jsonString);
} }
}); });
} }
...@@ -111,11 +116,19 @@ public class OpenfireEventService implements LoggingService ...@@ -111,11 +116,19 @@ public class OpenfireEventService implements LoggingService
* {@link #url}. * {@link #url}.
* @param s the content of the POST request. * @param s the content of the POST request.
*/ */
private void sendPost(final String s) private void sendPost(final String summary, final String detail)
{ {
try try
{ {
Log.info("OpenfireEventService sendPost " + s); String focusUsername = "focus";
String focusUserJid = JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.focus.user.jid");
if (focusUserJid != null)
{
focusUsername = (new JID(focusUserJid)).getNode();
}
Log.info("OpenfireEventService sendPost " + focusUsername + " " + detail);
SecurityAuditManager.getInstance().logEvent(focusUsername, summary, detail);
} }
catch (Exception e) catch (Exception e)
{ {
......
...@@ -573,4 +573,4 @@ public class ComponentImpl ...@@ -573,4 +573,4 @@ public class ComponentImpl
this.bundleContext = null; this.bundleContext = null;
} }
} }
} }
\ No newline at end of file
...@@ -43,6 +43,7 @@ import org.jivesoftware.openfire.user.UserManager; ...@@ -43,6 +43,7 @@ import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.openfire.user.UserNotFoundException; import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.openfire.muc.*; import org.jivesoftware.openfire.muc.*;
import org.jivesoftware.openfire.group.*; import org.jivesoftware.openfire.group.*;
import org.jivesoftware.openfire.security.SecurityAuditManager;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -295,7 +296,7 @@ public class OfMeetPlugin implements Plugin, ClusterEventListener { ...@@ -295,7 +296,7 @@ public class OfMeetPlugin implements Plugin, ClusterEventListener {
public void processMeetingPlanner() public void processMeetingPlanner()
{ {
Log.info("OfMeet Plugin - processMeetingPlanner"); Log.debug("OfMeet Plugin - processMeetingPlanner");
final Collection<Bookmark> bookmarks = BookmarkManager.getBookmarks(); final Collection<Bookmark> bookmarks = BookmarkManager.getBookmarks();
...@@ -392,6 +393,7 @@ public class OfMeetPlugin implements Plugin, ClusterEventListener { ...@@ -392,6 +393,7 @@ public class OfMeetPlugin implements Plugin, ClusterEventListener {
variables.put("domain", XMPPServer.getInstance().getServerInfo().getXMPPDomain()); variables.put("domain", XMPPServer.getInstance().getServerInfo().getXMPPDomain());
sendEmail(name, email, title, replaceTokens(template, variables), null); sendEmail(name, email, title, replaceTokens(template, variables), null);
SecurityAuditManager.getInstance().logEvent(user.getUsername(), "sent email - " + title, description);
} }
} }
catch (Exception e) { catch (Exception e) {
......
...@@ -675,55 +675,58 @@ function getUserMediaWithConstraints(um, success_callback, failure_callback, res ...@@ -675,55 +675,58 @@ function getUserMediaWithConstraints(um, success_callback, failure_callback, res
} }
} }
// Check if we are running on Android device if (constraints.video) {
var isAndroid = navigator.userAgent.indexOf('Android') != -1; // Check if we are running on Android device
var isAndroid = navigator.userAgent.indexOf('Android') != -1;
if (resolution && !constraints.video || isAndroid) {
constraints.video = { mandatory: {}, optional: [] };// same behaviour as true if (resolution && !constraints.video || isAndroid) {
} constraints.video = { mandatory: {}, optional: [] };// same behaviour as true
// see https://code.google.com/p/chromium/issues/detail?id=143631#c9 for list of supported resolutions }
switch (resolution) { // see https://code.google.com/p/chromium/issues/detail?id=143631#c9 for list of supported resolutions
// 16:9 first switch (resolution) {
case '1080': // 16:9 first
case 'fullhd': case '1080':
constraints.video.mandatory.minWidth = 1920; case 'fullhd':
constraints.video.mandatory.minHeight = 1080; constraints.video.mandatory.minWidth = 1920;
break; constraints.video.mandatory.minHeight = 1080;
case '720': break;
case 'hd': case '720':
constraints.video.mandatory.minWidth = 1280; case 'hd':
constraints.video.mandatory.minHeight = 720; constraints.video.mandatory.minWidth = 1280;
break; constraints.video.mandatory.minHeight = 720;
case '360': break;
constraints.video.mandatory.minWidth = 640; case '360':
constraints.video.mandatory.minHeight = 360; constraints.video.mandatory.minWidth = 640;
break; constraints.video.mandatory.minHeight = 360;
case '180': break;
constraints.video.mandatory.minWidth = 320; case '180':
constraints.video.mandatory.minHeight = 180; constraints.video.mandatory.minWidth = 320;
break; constraints.video.mandatory.minHeight = 180;
// 4:3 break;
case '960': // 4:3
constraints.video.mandatory.minWidth = 960; case '960':
constraints.video.mandatory.minHeight = 720; constraints.video.mandatory.minWidth = 960;
break; constraints.video.mandatory.minHeight = 720;
case '640': break;
case 'vga': case '640':
constraints.video.mandatory.minWidth = 640; case 'vga':
constraints.video.mandatory.minHeight = 480; constraints.video.mandatory.minWidth = 640;
break; constraints.video.mandatory.minHeight = 480;
case '320': break;
constraints.video.mandatory.minWidth = 320; case '320':
constraints.video.mandatory.minHeight = 240; constraints.video.mandatory.minWidth = 320;
break; constraints.video.mandatory.minHeight = 240;
default: break;
if (isAndroid) { default:
constraints.video.mandatory.minWidth = 320; if (isAndroid) {
constraints.video.mandatory.minHeight = 240; constraints.video.mandatory.minWidth = 320;
constraints.video.mandatory.maxFrameRate = 15; constraints.video.mandatory.minHeight = 240;
} constraints.video.mandatory.maxFrameRate = 15;
break; }
break;
}
} }
if (constraints.video) if (constraints.video)
{ {
if (constraints.video.mandatory.minWidth) if (constraints.video.mandatory.minWidth)
......
...@@ -108,8 +108,12 @@ var VideoLayout = (function (my) { ...@@ -108,8 +108,12 @@ var VideoLayout = (function (my) {
{ {
myResourceJid = Strophe.getResourceFromJid(connection.emuc.myroomjid); myResourceJid = Strophe.getResourceFromJid(connection.emuc.myroomjid);
} }
VideoLayout.updateLargeVideo(localVideoSrc, 0, VideoLayout.updateLargeVideo(localVideoSrc, 0, myResourceJid);
myResourceJid);
if (stream.getVideoTracks().length == 0)
{
localVideoSelector.css("display", "none");
}
}; };
......
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