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

Jitsi Videobridge - Added support for audio only participants (no webcam)

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@14010 b35dd754-fafc-0310-a699-88a17e54d16e
parent f51428cf
...@@ -27,6 +27,11 @@ var currentVideoHeight = null; ...@@ -27,6 +27,11 @@ var currentVideoHeight = null;
* @type {function()} * @type {function()}
*/ */
var getVideoSize; var getVideoSize;
/**
* Method used to get large video position.
* @type {function()}
*/
var getVideoPosition;
/* window.onbeforeunload = closePageWarning; */ /* window.onbeforeunload = closePageWarning; */
...@@ -219,6 +224,7 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) { ...@@ -219,6 +224,7 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
if (data.stream.id === 'mixedmslabel') return; if (data.stream.id === 'mixedmslabel') return;
var videoTracks = data.stream.getVideoTracks(); var videoTracks = data.stream.getVideoTracks();
console.log("waiting..", videoTracks, selector[0]); console.log("waiting..", videoTracks, selector[0]);
if (videoTracks.length === 0 || selector[0].currentTime > 0) { if (videoTracks.length === 0 || selector[0].currentTime > 0) {
RTC.attachMediaStream(selector, data.stream); // FIXME: why do i have to do this for FF? RTC.attachMediaStream(selector, data.stream); // FIXME: why do i have to do this for FF?
...@@ -720,8 +726,10 @@ function updateLargeVideo(newSrc, vol) { ...@@ -720,8 +726,10 @@ function updateLargeVideo(newSrc, vol) {
document.getElementById('largeVideo').style.webkitTransform = "none"; document.getElementById('largeVideo').style.webkitTransform = "none";
} }
// Change the way we'll be measuring large video // Change the way we'll be measuring and positioning large video
getVideoSize = isVideoSrcDesktop(newSrc) ? getVideoSizeFit : getVideoSizeCover; var isDesktop = isVideoSrcDesktop(newSrc);
getVideoSize = isDesktop ? getDesktopVideoSize : getCameraVideoSize;
getVideoPosition = isDesktop ? getDesktopVideoPosition : getCameraVideoPosition;
if (isVisible) if (isVisible)
$(this).fadeIn(300); $(this).fadeIn(300);
...@@ -849,10 +857,10 @@ var positionLarge = function(videoWidth, videoHeight) { ...@@ -849,10 +857,10 @@ var positionLarge = function(videoWidth, videoHeight) {
* @return an array with 2 elements, the horizontal indent and the vertical * @return an array with 2 elements, the horizontal indent and the vertical
* indent * indent
*/ */
var getVideoPosition = function ( videoWidth, function getCameraVideoPosition( videoWidth,
videoHeight, videoHeight,
videoSpaceWidth, videoSpaceWidth,
videoSpaceHeight) { videoSpaceHeight) {
// Parent height isn't completely calculated when we position the video in // Parent height isn't completely calculated when we position the video in
// full screen mode and this is why we use the screen height in this case. // full screen mode and this is why we use the screen height in this case.
// Need to think it further at some point and implement it properly. // Need to think it further at some point and implement it properly.
...@@ -866,7 +874,26 @@ var getVideoPosition = function ( videoWidth, ...@@ -866,7 +874,26 @@ var getVideoPosition = function ( videoWidth,
var verticalIndent = (videoSpaceHeight - videoHeight)/2; var verticalIndent = (videoSpaceHeight - videoHeight)/2;
return [horizontalIndent, verticalIndent]; return [horizontalIndent, verticalIndent];
}; }
/**
* Returns an array of the video horizontal and vertical indents.
* Centers horizontally and top aligns vertically.
*
* @return an array with 2 elements, the horizontal indent and the vertical
* indent
*/
function getDesktopVideoPosition( videoWidth,
videoHeight,
videoSpaceWidth,
videoSpaceHeight) {
var horizontalIndent = (videoSpaceWidth - videoWidth)/2;
var verticalIndent = 0;// Top aligned
return [horizontalIndent, verticalIndent];
}
/** /**
* Returns an array of the video dimensions, so that it covers the screen. * Returns an array of the video dimensions, so that it covers the screen.
...@@ -874,7 +901,7 @@ var getVideoPosition = function ( videoWidth, ...@@ -874,7 +901,7 @@ var getVideoPosition = function ( videoWidth,
* *
* @return an array with 2 elements, the video width and the video height * @return an array with 2 elements, the video width and the video height
*/ */
function getVideoSizeCover(videoWidth, function getCameraVideoSize(videoWidth,
videoHeight, videoHeight,
videoSpaceWidth, videoSpaceWidth,
videoSpaceHeight) { videoSpaceHeight) {
...@@ -907,10 +934,11 @@ function getVideoSizeCover(videoWidth, ...@@ -907,10 +934,11 @@ function getVideoSizeCover(videoWidth,
* *
* @return an array with 2 elements, the video width and the video height * @return an array with 2 elements, the video width and the video height
*/ */
function getVideoSizeFit(videoWidth, function getDesktopVideoSize( videoWidth,
videoHeight, videoHeight,
videoSpaceWidth, videoSpaceWidth,
videoSpaceHeight) { videoSpaceHeight )
{
if (!videoWidth) if (!videoWidth)
videoWidth = currentVideoWidth; videoWidth = currentVideoWidth;
if (!videoHeight) if (!videoHeight)
...@@ -921,12 +949,16 @@ function getVideoSizeFit(videoWidth, ...@@ -921,12 +949,16 @@ function getVideoSizeFit(videoWidth,
var availableWidth = Math.max(videoWidth, videoSpaceWidth); var availableWidth = Math.max(videoWidth, videoSpaceWidth);
var availableHeight = Math.max(videoHeight, videoSpaceHeight); var availableHeight = Math.max(videoHeight, videoSpaceHeight);
if (availableWidth / aspectRatio >= videoSpaceHeight) { videoSpaceHeight -= $('#remoteVideos').outerHeight();
if (availableWidth / aspectRatio >= videoSpaceHeight)
{
availableHeight = videoSpaceHeight; availableHeight = videoSpaceHeight;
availableWidth = availableHeight*aspectRatio; availableWidth = availableHeight*aspectRatio;
} }
if (availableHeight*aspectRatio >= videoSpaceWidth) { if (availableHeight*aspectRatio >= videoSpaceWidth)
{
availableWidth = videoSpaceWidth; availableWidth = videoSpaceWidth;
availableHeight = availableWidth / aspectRatio; availableHeight = availableWidth / aspectRatio;
} }
...@@ -971,8 +1003,8 @@ var resizeLargeVideoContainer = function () { ...@@ -971,8 +1003,8 @@ var resizeLargeVideoContainer = function () {
resizeThumbnails(); resizeThumbnails();
}; };
function resizeThumbnails() { var calculateThumbnailSize = function() {
// Calculate the available height, which is the inner window height minus // Calculate the available height, which is the inner window height minus
// 39px for the header minus 2px for the delimiter lines on the top and // 39px for the header minus 2px for the delimiter lines on the top and
// bottom of the large video, minus the 36px space inside the remoteVideos // bottom of the large video, minus the 36px space inside the remoteVideos
// container used for highlighting shadow. // container used for highlighting shadow.
...@@ -990,10 +1022,18 @@ function resizeThumbnails() { ...@@ -990,10 +1022,18 @@ function resizeThumbnails() {
availableWidth = Math.floor(availableHeight * aspectRatio); availableWidth = Math.floor(availableHeight * aspectRatio);
} }
return [availableWidth, availableHeight];
};
function resizeThumbnails() {
var thumbnailSize = calculateThumbnailSize();
var width = thumbnailSize[0];
var height = thumbnailSize[1];
// size videos so that while keeping AR and max height, we have a nice fit // size videos so that while keeping AR and max height, we have a nice fit
$('#remoteVideos').height(availableHeight); $('#remoteVideos').height(height);
$('#remoteVideos>span').width(availableWidth); $('#remoteVideos>span').width(width);
$('#remoteVideos>span').height(availableHeight); $('#remoteVideos>span').height(height);
} }
$(document).ready(function () { $(document).ready(function () {
...@@ -1004,9 +1044,15 @@ $(document).ready(function () { ...@@ -1004,9 +1044,15 @@ $(document).ready(function () {
// Set default desktop sharing method // Set default desktop sharing method
setDesktopSharing(config.desktopSharing); setDesktopSharing(config.desktopSharing);
// Initialize Chrome extension inline installs
if(config.chromeExtensionId)
{
initInlineInstalls();
}
// By default we cover the whole screen with video // By default we use camera
getVideoSize = getVideoSizeCover; getVideoSize = getCameraVideoSize;
getVideoPosition = getCameraVideoPosition;
resizeLargeVideoContainer(); resizeLargeVideoContainer();
$(window).resize(function () { $(window).resize(function () {
...@@ -1448,8 +1494,6 @@ function toggleFullScreen() { ...@@ -1448,8 +1494,6 @@ function toggleFullScreen() {
* Shows the display name for the given video. * Shows the display name for the given video.
*/ */
function showDisplayName(videoSpanId, displayName) { function showDisplayName(videoSpanId, displayName) {
var escDisplayName = Util.escapeHtml(displayName);
var nameSpan = $('#' + videoSpanId + '>span.displayname'); var nameSpan = $('#' + videoSpanId + '>span.displayname');
// If we already have a display name for this video. // If we already have a display name for this video.
...@@ -1457,10 +1501,10 @@ function showDisplayName(videoSpanId, displayName) { ...@@ -1457,10 +1501,10 @@ function showDisplayName(videoSpanId, displayName) {
var nameSpanElement = nameSpan.get(0); var nameSpanElement = nameSpan.get(0);
if (nameSpanElement.id === 'localDisplayName' if (nameSpanElement.id === 'localDisplayName'
&& $('#localDisplayName').html() !== escDisplayName) && $('#localDisplayName').text() !== displayName)
$('#localDisplayName').html(escDisplayName); $('#localDisplayName').text(displayName);
else else
$('#' + videoSpanId + '_name').html(escDisplayName); $('#' + videoSpanId + '_name').text(displayName);
} }
else { else {
var editButton = null; var editButton = null;
...@@ -1468,10 +1512,10 @@ function showDisplayName(videoSpanId, displayName) { ...@@ -1468,10 +1512,10 @@ function showDisplayName(videoSpanId, displayName) {
if (videoSpanId === 'localVideoContainer') { if (videoSpanId === 'localVideoContainer') {
editButton = createEditDisplayNameButton(); editButton = createEditDisplayNameButton();
} }
if (escDisplayName.length) { if (displayName.length) {
nameSpan = document.createElement('span'); nameSpan = document.createElement('span');
nameSpan.className = 'displayname'; nameSpan.className = 'displayname';
nameSpan.innerHTML = escDisplayName; nameSpan.innerText = displayName;
$('#' + videoSpanId)[0].appendChild(nameSpan); $('#' + videoSpanId)[0].appendChild(nameSpan);
} }
...@@ -1486,9 +1530,9 @@ function showDisplayName(videoSpanId, displayName) { ...@@ -1486,9 +1530,9 @@ function showDisplayName(videoSpanId, displayName) {
editableText.className = 'displayname'; editableText.className = 'displayname';
editableText.id = 'editDisplayName'; editableText.id = 'editDisplayName';
if (escDisplayName.length) if (displayName.length)
editableText.value editableText.value
= escDisplayName.substring(0, escDisplayName.indexOf(' (me)')); = displayName.substring(0, displayName.indexOf(' (me)'));
editableText.setAttribute('style', 'display:none;'); editableText.setAttribute('style', 'display:none;');
editableText.setAttribute('placeholder', 'ex. Jane Pink'); editableText.setAttribute('placeholder', 'ex. Jane Pink');
...@@ -1503,7 +1547,7 @@ function showDisplayName(videoSpanId, displayName) { ...@@ -1503,7 +1547,7 @@ function showDisplayName(videoSpanId, displayName) {
var inputDisplayNameHandler = function(name) { var inputDisplayNameHandler = function(name) {
if (nickname !== name) { if (nickname !== name) {
nickname = Util.escapeHtml(name); nickname = name;
window.localStorage.displayname = nickname; window.localStorage.displayname = nickname;
connection.emuc.addDisplayNameToPresence(nickname); connection.emuc.addDisplayNameToPresence(nickname);
connection.emuc.sendPresence(); connection.emuc.sendPresence();
...@@ -1512,7 +1556,7 @@ function showDisplayName(videoSpanId, displayName) { ...@@ -1512,7 +1556,7 @@ function showDisplayName(videoSpanId, displayName) {
} }
if (!$('#localDisplayName').is(":visible")) { if (!$('#localDisplayName').is(":visible")) {
$('#localDisplayName').html(nickname + " (me)"); $('#localDisplayName').text(nickname + " (me)");
$('#localDisplayName').show(); $('#localDisplayName').show();
$('#editDisplayName').hide(); $('#editDisplayName').hide();
} }
......
config.desktopSharing = 'webrtc'; // Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable. config.desktopSharing = 'ext'; // Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable.
config.chromeExtensionId = 'diibjkoicjeejcmhdnailmkgecihlobk'; // Id of desktop streamer Chrome extension config.chromeExtensionId = 'diibjkoicjeejcmhdnailmkgecihlobk'; // Id of desktop streamer Chrome extension
config.minChromeExtVersion = '0.0.8'; // Required version of Chrome extension config.minChromeExtVersion = '0.1'; // Required version of Chrome extension
config.getroomnode = function (path) config.getroomnode = function (path)
{ {
...@@ -19,4 +19,4 @@ config.getroomnode = function (path) ...@@ -19,4 +19,4 @@ config.getroomnode = function (path)
window.history.pushState('VideoChat', 'Room: ' + roomnode, path + "?r=" + roomnode); window.history.pushState('VideoChat', 'Room: ' + roomnode, path + "?r=" + roomnode);
} }
return roomnode; return roomnode;
} };
...@@ -55,13 +55,13 @@ ...@@ -55,13 +55,13 @@
#localVideoWrapper { #localVideoWrapper {
display:inline-block; display:inline-block;
-webkit-mask-box-image: url(http://emcho.com/db/videomask.svg); -webkit-mask-box-image: url(../images/videomask.svg);
border-radius:0px !important; border-radius:0px !important;
border: 0px !important; border: 0px !important;
} }
#remoteVideos .videocontainer>video { #remoteVideos .videocontainer>video {
border-radius:6px; border-radius:4px;
} }
.flipVideoX { .flipVideoX {
...@@ -150,14 +150,22 @@ ...@@ -150,14 +150,22 @@
white-space: nowrap; white-space: nowrap;
z-index: 2; z-index: 2;
box-sizing: border-box; box-sizing: border-box;
border-bottom-left-radius:6px; border-bottom-left-radius:4px;
border-bottom-right-radius:6px; border-bottom-right-radius:4px;
} }
#localVideoContainer>span.displayname:hover { #localVideoContainer>span.displayname:hover {
cursor: text; cursor: text;
} }
.videocontainer>span.displayname {
pointer-events: none;
}
#localDisplayName {
pointer-events: auto !important;
}
.videocontainer>a.displayname { .videocontainer>a.displayname {
display: inline-block; display: inline-block;
position: absolute; position: absolute;
...@@ -223,4 +231,4 @@ ...@@ -223,4 +231,4 @@
background-size: contain; background-size: contain;
background-repeat: no-repeat; background-repeat: no-repeat;
z-index: 2; z-index: 2;
} }
\ No newline at end of file
...@@ -74,6 +74,25 @@ function showDesktopSharingButton() { ...@@ -74,6 +74,25 @@ function showDesktopSharingButton() {
} }
} }
/**
* Initializes <link rel=chrome-webstore-item /> with extension id set in config.js to support inline installs.
* Host site must be selected as main website of published extension.
*/
function initInlineInstalls()
{
$("link[rel=chrome-webstore-item]").attr("href", getWebStoreInstallUrl());
}
/**
* Constructs inline install URL for Chrome desktop streaming extension.
* The 'chromeExtensionId' must be defined in config.js.
* @returns {string}
*/
function getWebStoreInstallUrl()
{
return "https://chrome.google.com/webstore/detail/" + config.chromeExtensionId;
}
/* /*
* Toggles screen sharing. * Toggles screen sharing.
*/ */
...@@ -168,7 +187,7 @@ function obtainScreenFromExtension(streamCallback, failCallback) { ...@@ -168,7 +187,7 @@ function obtainScreenFromExtension(streamCallback, failCallback) {
doGetStreamFromExtension(streamCallback, failCallback); doGetStreamFromExtension(streamCallback, failCallback);
} else { } else {
chrome.webstore.install( chrome.webstore.install(
"https://chrome.google.com/webstore/detail/" + config.chromeExtensionId, getWebStoreInstallUrl(),
function(arg) { function(arg) {
console.log("Extension installed successfully", arg); console.log("Extension installed successfully", arg);
// We need to reload the page in order to get the access to chrome.runtime // We need to reload the page in order to get the access to chrome.runtime
...@@ -188,7 +207,6 @@ function checkExtInstalled(isInstalledCallback) { ...@@ -188,7 +207,6 @@ function checkExtInstalled(isInstalledCallback) {
if(!chrome.runtime) { if(!chrome.runtime) {
// No API, so no extension for sure // No API, so no extension for sure
isInstalledCallback(false); isInstalledCallback(false);
return false;
} }
chrome.runtime.sendMessage( chrome.runtime.sendMessage(
config.chromeExtensionId, config.chromeExtensionId,
...@@ -202,7 +220,7 @@ function checkExtInstalled(isInstalledCallback) { ...@@ -202,7 +220,7 @@ function checkExtInstalled(isInstalledCallback) {
// Check installed extension version // Check installed extension version
var extVersion = response.version; var extVersion = response.version;
console.log('Extension version is: '+extVersion); console.log('Extension version is: '+extVersion);
var updateRequired = extVersion < config.minChromeExtVersion; var updateRequired = isUpdateRequired(config.minChromeExtVersion, extVersion);
if(updateRequired) { if(updateRequired) {
alert( alert(
'Jitsi Desktop Streamer requires update. ' + 'Jitsi Desktop Streamer requires update. ' +
...@@ -214,6 +232,50 @@ function checkExtInstalled(isInstalledCallback) { ...@@ -214,6 +232,50 @@ function checkExtInstalled(isInstalledCallback) {
); );
} }
/**
* Checks whether extension update is required.
* @param minVersion minimal required version
* @param extVersion current extension version
* @returns {boolean}
*/
function isUpdateRequired(minVersion, extVersion)
{
try
{
var s1 = minVersion.split('.');
var s2 = extVersion.split('.');
var len = Math.max(s1.length, s2.length);
for(var i = 0; i < len; i++)
{
var n1=0,n2=0;
if(i < s1.length)
n1 = parseInt(s1[i]);
if(i < s2.length)
n2 = parseInt(s2[i]);
if(isNaN(n1) || isNaN(n2))
{
return true;
}
else if(n1 !== n2)
{
return n1 > n2;
}
}
// will happen if boths version has identical numbers in
// their components (even if one of them is longer, has more components)
return false;
}
catch(e)
{
console.error("Failed to parse extension version", e);
return true;
}
}
function doGetStreamFromExtension(streamCallback, failCallback) { function doGetStreamFromExtension(streamCallback, failCallback) {
// Sends 'getStream' msg to the extension. Extension id must be defined in the config. // Sends 'getStream' msg to the extension. Extension id must be defined in the config.
chrome.runtime.sendMessage( chrome.runtime.sendMessage(
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="480"
height="270"
id="svg2"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="videomask.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="-16.428571"
inkscape:cy="520"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="998"
inkscape:window-height="711"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-782.36218)">
<rect
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.92795467;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
id="rect2985"
width="479.07202"
height="269.07205"
x="0.46397734"
y="782.82617"
ry="20" />
</g>
</svg>
<html> <html itemscope itemtype="http://schema.org/Product" prefix="og: http://ogp.me/ns#">
<head> <head>
<title>WebRTC, meet the Jitsi Videobridge</title> <title>Jitsi Videobridge meets WebRTC</title>
<script src="/jitsi/config"></script> <meta property="og:title" content="Jitsi Meet"/>
<meta property="og:image" content="/images/jitsilogo.png"/>
<meta property="og:description" content="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
<meta description="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
<meta itemprop="name" content="Jitsi Meet"/>
<meta itemprop="description" content="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
<meta itemprop="image" content="/images/jitsilogo.png"/>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="libs/strophe/strophe.jingle.adapter.js?v=1"></script><!-- strophe.jingle bundles --> <script src="libs/strophe/strophe.jingle.adapter.js?v=1"></script><!-- strophe.jingle bundles -->
<script src="libs/strophe/strophe.jingle.bundle.js?v=8"></script> <script src="libs/strophe/strophe.jingle.bundle.js?v=8"></script>
<script src="libs/strophe/strophe.jingle.js?v=1"></script> <script src="libs/strophe/strophe.jingle.js?v=1"></script>
<script src="libs/strophe/strophe.jingle.sdp.js?v=1"></script> <script src="libs/strophe/strophe.jingle.sdp.js?v=2"></script>
<script src="libs/strophe/strophe.jingle.sdp.util.js?v=1"></script> <script src="libs/strophe/strophe.jingle.sdp.util.js?v=1"></script>
<script src="libs/strophe/strophe.jingle.sessionbase.js?v=1"></script> <script src="libs/strophe/strophe.jingle.sessionbase.js?v=1"></script>
<script src="libs/strophe/strophe.jingle.session.js?v=1"></script> <script src="libs/strophe/strophe.jingle.session.js?v=1"></script>
...@@ -17,7 +23,7 @@ ...@@ -17,7 +23,7 @@
<script src="muc.js?v=9"></script><!-- simple MUC library --> <script src="muc.js?v=9"></script><!-- simple MUC library -->
<script src="estos_log.js?v=2"></script><!-- simple stanza logger --> <script src="estos_log.js?v=2"></script><!-- simple stanza logger -->
<script src="desktopsharing.js?v=1"></script><!-- desktop sharing --> <script src="desktopsharing.js?v=1"></script><!-- desktop sharing -->
<script src="app.js?v=24"></script><!-- application logic --> <script src="app.js?v=25"></script><!-- application logic -->
<script src="chat.js?v=4"></script><!-- chat logic --> <script src="chat.js?v=4"></script><!-- chat logic -->
<script src="util.js?v=3"></script><!-- utility functions --> <script src="util.js?v=3"></script><!-- utility functions -->
<script src="etherpad.js?v=7"></script><!-- etherpad plugin --> <script src="etherpad.js?v=7"></script><!-- etherpad plugin -->
...@@ -27,12 +33,12 @@ ...@@ -27,12 +33,12 @@
<link href="//netdna.bootstrapcdn.com/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" href="css/font.css"/> <link rel="stylesheet" href="css/font.css"/>
<link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=20"/> <link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=20"/>
<link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=1" id="videolayout_default"/> <link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=3" id="videolayout_default"/>
<link rel="stylesheet" href="css/jquery-impromptu.css?v=4"> <link rel="stylesheet" href="css/jquery-impromptu.css?v=4">
<link rel="stylesheet" href="css/modaldialog.css?v=3"> <link rel="stylesheet" href="css/modaldialog.css?v=3">
<!-- <!--
Link used for inline installation of chrome desktop streaming extension, Link used for inline installation of chrome desktop streaming extension,
must contain the same extension id as defined in config.js --> is updated automatically from the code with the value defined in config.js -->
<link rel="chrome-webstore-item" href="https://chrome.google.com/webstore/detail/diibjkoicjeejcmhdnailmkgecihlobk"> <link rel="chrome-webstore-item" href="https://chrome.google.com/webstore/detail/diibjkoicjeejcmhdnailmkgecihlobk">
<script src="libs/jquery-impromptu.js"></script> <script src="libs/jquery-impromptu.js"></script>
<script src="libs/jquery.autosize.js"></script> <script src="libs/jquery.autosize.js"></script>
......
...@@ -308,8 +308,7 @@ SDP.prototype.TransportToJingle = function (mediaindex, elem) { ...@@ -308,8 +308,7 @@ SDP.prototype.TransportToJingle = function (mediaindex, elem) {
var fingerprints = SDPUtil.find_lines(this.media[mediaindex], 'a=fingerprint:', this.session); var fingerprints = SDPUtil.find_lines(this.media[mediaindex], 'a=fingerprint:', this.session);
fingerprints.forEach(function(line) { fingerprints.forEach(function(line) {
tmp = SDPUtil.parse_fingerprint(line); tmp = SDPUtil.parse_fingerprint(line);
tmp.xmlns = 'urn:xmpp:tmp:jingle:apps:dtls:0'; tmp.xmlns = 'urn:xmpp:jingle:apps:dtls:0';
// tmp.xmlns = 'urn:xmpp:jingle:apps:dtls:0'; -- FIXME: update receivers first
elem.c('fingerprint').t(tmp.fingerprint); elem.c('fingerprint').t(tmp.fingerprint);
delete tmp.fingerprint; delete tmp.fingerprint;
line = SDPUtil.find_line(self.media[mediaindex], 'a=setup:', self.session); line = SDPUtil.find_line(self.media[mediaindex], 'a=setup:', self.session);
...@@ -553,4 +552,4 @@ SDP.prototype.jingle2media = function (content) { ...@@ -553,4 +552,4 @@ SDP.prototype.jingle2media = function (content) {
} }
} }
return media; return media;
}; };
\ No newline at end of file
...@@ -54,7 +54,7 @@ html, body{ ...@@ -54,7 +54,7 @@ html, body{
display: inline-block; display: inline-block;
background-image:url(../images/avatar1.png); background-image:url(../images/avatar1.png);
background-size: contain; background-size: contain;
border-radius:8px; border-radius:4px;
border: 2px solid #212425; border: 2px solid #212425;
} }
...@@ -254,8 +254,7 @@ a.button:hover { ...@@ -254,8 +254,7 @@ a.button:hover {
top: 7; top: 7;
width: 1px; width: 1px;
height: 25px; height: 25px;
background: white; background: #676767;
background: -webkit-gradient(linear, 0 0, 0 100%, from(#087dba), to(#087dba), color-stop(50%, white));
} }
#right { #right {
......
...@@ -308,8 +308,7 @@ SDP.prototype.TransportToJingle = function (mediaindex, elem) { ...@@ -308,8 +308,7 @@ SDP.prototype.TransportToJingle = function (mediaindex, elem) {
var fingerprints = SDPUtil.find_lines(this.media[mediaindex], 'a=fingerprint:', this.session); var fingerprints = SDPUtil.find_lines(this.media[mediaindex], 'a=fingerprint:', this.session);
fingerprints.forEach(function(line) { fingerprints.forEach(function(line) {
tmp = SDPUtil.parse_fingerprint(line); tmp = SDPUtil.parse_fingerprint(line);
tmp.xmlns = 'urn:xmpp:tmp:jingle:apps:dtls:0'; tmp.xmlns = 'urn:xmpp:jingle:apps:dtls:0';
// tmp.xmlns = 'urn:xmpp:jingle:apps:dtls:0'; -- FIXME: update receivers first
elem.c('fingerprint').t(tmp.fingerprint); elem.c('fingerprint').t(tmp.fingerprint);
delete tmp.fingerprint; delete tmp.fingerprint;
line = SDPUtil.find_line(self.media[mediaindex], 'a=setup:', self.session); line = SDPUtil.find_line(self.media[mediaindex], 'a=setup:', self.session);
...@@ -553,4 +552,4 @@ SDP.prototype.jingle2media = function (content) { ...@@ -553,4 +552,4 @@ SDP.prototype.jingle2media = function (content) {
} }
} }
return media; return media;
}; };
\ No newline at end of file
...@@ -47,6 +47,7 @@ public class Config extends HttpServlet ...@@ -47,6 +47,7 @@ public class Config extends HttpServlet
String resolution = JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.resolution", "720"); String resolution = JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.resolution", "720");
String useNicks = JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.usenicks", "false"); String useNicks = JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.usenicks", "false");
String useIPv6 = JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.useipv6", "false"); String useIPv6 = JiveGlobals.getProperty("org.jitsi.videobridge.ofmeet.useipv6", "false");
String recordVideo = JiveGlobals.getProperty("org.jitsi.videobridge.media.record", "true");
out.println("var config = {"); out.println("var config = {");
out.println(" hosts: {"); out.println(" hosts: {");
...@@ -57,6 +58,7 @@ public class Config extends HttpServlet ...@@ -57,6 +58,7 @@ public class Config extends HttpServlet
if (!iceServers.trim().equals("")) out.println(" iceServers: " + iceServers + ","); if (!iceServers.trim().equals("")) out.println(" iceServers: " + iceServers + ",");
out.println(" useIPv6: " + useIPv6 + ","); out.println(" useIPv6: " + useIPv6 + ",");
out.println(" useNicks: " + useNicks + ","); out.println(" useNicks: " + useNicks + ",");
out.println(" recordVideo: " + recordVideo + ",");
out.println(" useWebsockets: " + (websockets ? "true" : "false") + ","); out.println(" useWebsockets: " + (websockets ? "true" : "false") + ",");
out.println(" resolution: '" + resolution + "',"); out.println(" resolution: '" + resolution + "',");
out.println(" bosh: window.location.protocol + '//' + window.location.host + '/http-bind/'"); out.println(" bosh: window.location.protocol + '//' + window.location.host + '/http-bind/'");
......
...@@ -1495,7 +1495,6 @@ public class PluginImpl implements Plugin, PropertyEventListener ...@@ -1495,7 +1495,6 @@ public class PluginImpl implements Plugin, PropertyEventListener
{ {
Presence presence = new Presence(); Presence presence = new Presence();
presence.setFrom(XMPPServer.getInstance().createJID(focusName, focusName)); presence.setFrom(XMPPServer.getInstance().createJID(focusName, focusName));
presence.setTo(owner);
if (accepted) if (accepted)
{ {
...@@ -1505,7 +1504,12 @@ public class PluginImpl implements Plugin, PropertyEventListener ...@@ -1505,7 +1504,12 @@ public class PluginImpl implements Plugin, PropertyEventListener
InviteCompletedEvent event = new InviteCompletedEvent(callId); InviteCompletedEvent event = new InviteCompletedEvent(callId);
presence.getElement().add(colibriProvider.toXML(event)); presence.getElement().add(colibriProvider.toXML(event));
} }
router.route(presence);
for (Participant participant : users.values())
{
presence.setTo(participant.getUser());
router.route(presence);
}
} }
/** /**
......
...@@ -428,7 +428,7 @@ public class Recorder extends Thread ...@@ -428,7 +428,7 @@ public class Recorder extends Thread
if (recordWebm) if (recordWebm)
{ {
long duration = 0; long duration = 0;
/*
if (d.keyframe || lastTimecode == 0) if (d.keyframe || lastTimecode == 0)
{ {
if (lastTimecode != 0) if (lastTimecode != 0)
...@@ -453,6 +453,22 @@ public class Recorder extends Thread ...@@ -453,6 +453,22 @@ public class Recorder extends Thread
mFW.addFrame(frame); mFW.addFrame(frame);
//Log.info("writeData video " + d.data); //Log.info("writeData video " + d.data);
*/
duration = d.timestamp - lastTimecode;
mFW.startCluster(d.timestamp);
MatroskaFileFrame frame = new MatroskaFileFrame();
frame.TrackNo = 1;
frame.Duration = duration;
frame.Timecode = d.timestamp;
frame.Reference = 0;
frame.KeyFrame = d.keyframe;
frame.Data = d.data;
mFW.addFrame(frame);
mFW.endCluster();
lastTimecode = d.timestamp;
} else { } else {
bo.write(d.data, 0, d.length); bo.write(d.data, 0, d.length);
......
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